From b6c49d98d612d1573a9394b4a676611963128b58 Mon Sep 17 00:00:00 2001 From: tchernobog Date: Thu, 16 Feb 2006 22:50:32 +0000 Subject: [PATCH] - Add support for abtract python classes - Create first modules: the Policy Python class git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@335 3ecf2c5c-341e-0410-92b4-d18e462d057c --- src/Makefile.am | 2 +- src/backend/policy.hh | 45 ++++++++--------- src/backend/policy_manager.hh | 24 ++++----- src/pyloader/Abstract.py | 94 +++++++++++++++++++++++++++++++++++ src/pyloader/Makefile.am | 3 +- src/pyloader/Policy.py | 15 ++++++ 6 files changed, 145 insertions(+), 38 deletions(-) create mode 100644 src/pyloader/Abstract.py create mode 100644 src/pyloader/Policy.py diff --git a/src/Makefile.am b/src/Makefile.am index 26448a3..003831e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -55,7 +55,7 @@ sgpemv2_SOURCES = \ observer.cc \ parse_opts.cc \ simulation.cc \ - standard_io.cc \ + standard_io.cc \ start_gui.cc noinst_HEADERS = \ diff --git a/src/backend/policy.hh b/src/backend/policy.hh index dc56cfc..a636028 100644 --- a/src/backend/policy.hh +++ b/src/backend/policy.hh @@ -30,36 +30,35 @@ namespace sgpem { - - class Policy; + class Policy; - /** \brief - e' una Strategy che rappresenta un algoritmo di scheduling che implementa una politica - di scheduling. - */ - class SG_DLLEXPORT Policy - { - public: - virtual ~Policy(); + /** \brief + e' una Strategy che rappresenta un algoritmo di scheduling che implementa una politica + di scheduling. + */ + class SG_DLLEXPORT Policy + { + public: + virtual ~Policy(); - virtual void configure() = 0; - virtual void sort_queue(sgpem::Scheduler::event) const = 0; - int get_id() const; - virtual Glib::ustring get_description() const = 0; - virtual bool is_pre_emptive() const = 0; - virtual int get_time_slice() const = 0; - virtual void set_time_slice(const int&) = 0; + virtual void configure() = 0; + virtual void sort_queue(sgpem::Scheduler::event) const = 0; + int get_id() const; + virtual Glib::ustring get_description() const = 0; + virtual bool is_pre_emptive() const = 0; + virtual int get_time_slice() const = 0; + virtual void set_time_slice(const int&) = 0; - const PolicyParameters& get_parameters() const; + const PolicyParameters& get_parameters() const; - private: - PolicyParameters _parameters; - int _id; - }; + private: + PolicyParameters _parameters; + int _id; + }; }//~ namespace sgpem -#endif \ No newline at end of file +#endif diff --git a/src/backend/policy_manager.hh b/src/backend/policy_manager.hh index 9adfe40..628e8bc 100644 --- a/src/backend/policy_manager.hh +++ b/src/backend/policy_manager.hh @@ -27,19 +27,17 @@ namespace sgpem { - + class PolicyManager; + + class SG_DLLEXPORT PolicyManager + { + public: + virtual ~PolicyManager() = 0; - class PolicyManager; - - class SG_DLLEXPORT PolicyManager - { - public: - virtual ~PolicyManager() = 0; - - virtual Policy* get_policy() = 0; - virtual void init() = 0; - }; - -} + virtual Policy& get_policy() = 0; + virtual void init() = 0; + }; + +} //~ namespace sgpem #endif diff --git a/src/pyloader/Abstract.py b/src/pyloader/Abstract.py new file mode 100644 index 0000000..fa4d4fe --- /dev/null +++ b/src/pyloader/Abstract.py @@ -0,0 +1,94 @@ +class AbstractMethod (object): + """Defines a class to create abstract methods + + @example: + class Foo: + foo = AbstractMethod('foo') + """ + def __init__(self, func): + """Constructor + + @params func: name of the function (used when raising an + exception). + @type func: str + """ + self._function = func + + def __get__(self, obj, type): + """Get callable object + + @returns An instance of AbstractMethodHelper. + + This trickery is needed to get the name of the class for which + an abstract method was requested, otherwise it would be + sufficient to include a __call__ method in the AbstractMethod + class itself. + """ + return self.AbstractMethodHelper(self._function, type) + + class AbstractMethodHelper (object): + """Abstract method helper class + + An AbstractMethodHelper instance is a callable object that + represents an abstract method. + """ + def __init__(self, func, cls): + self._function = func + self._class = cls + + def __call__(self, *args, **kwargs): + """Call abstract method + + Raises a TypeError, because abstract methods can not be + called. + """ + raise TypeError('Abstract method `' + self._class.__name__ \ + + '.' + self._function + '\' called') + + +class Metaclass (type): + def __init__(cls, name, bases, *args, **kwargs): + """Configure a new class + + @param cls: Class object + @param name: Name of the class + @param bases: All base classes for cls + """ + super(Metaclass, cls).__init__(cls, name, bases, *args, **kwargs) + + # Detach cls.new() from class Metaclass, and make it a method + # of cls. + cls.__new__ = staticmethod(cls.new) + + # Find all abstract methods, and assign the resulting list to + # cls.__abstractmethods__, so we can read that variable when a + # request for allocation (__new__) is done. + abstractmethods = [] + ancestors = list(cls.__mro__) + ancestors.reverse() # Start with __builtin__.object + for ancestor in ancestors: + for clsname, clst in ancestor.__dict__.items(): + if isinstance(clst, AbstractMethod): + abstractmethods.append(clsname) + else: + if clsname in abstractmethods: + abstractmethods.remove(clsname) + + abstractmethods.sort() + setattr(cls, '__abstractmethods__', abstractmethods) + + def new(self, cls): + """Allocator for class cls + + @param self: Class object for which an instance should be + created. + + @param cls: Same as self. + """ + if len(cls.__abstractmethods__): + raise NotImplementedError('Can\'t instantiate class `' + \ + cls.__name__ + '\';\n' + \ + 'Abstract methods: ' + \ + ", ".join(cls.__abstractmethods__)) + + return object.__new__(self) diff --git a/src/pyloader/Makefile.am b/src/pyloader/Makefile.am index a475474..ff31527 100644 --- a/src/pyloader/Makefile.am +++ b/src/pyloader/Makefile.am @@ -54,4 +54,5 @@ libpyloader_la_SOURCES = \ noinst_HEADERS = python_policy.hh \ python_policy_manager.hh - +mod_PYTHON = Abstract.py \ + Policy.py diff --git a/src/pyloader/Policy.py b/src/pyloader/Policy.py new file mode 100644 index 0000000..e38a8b3 --- /dev/null +++ b/src/pyloader/Policy.py @@ -0,0 +1,15 @@ + +''' from sgpem import SchedulableQueue, PolicyParameters ''' +from Abstract import * + +class Policy: + ''' + Avoid instantiation of an abstract class. + ''' + __metaclass__ = Metaclass + + configure = AbstractMethod('configure') + sort_queue = AbstractMethod('sort_queue') + is_preemptive = AbstractMethod('is_preemptive') + is_time_sliced = AbstractMethod('is_time_sliced') + get_parameters = AbstractMethod('get_parameters')