Port everything to work with Python 2.6 and (hopefully) 3.0.
Phew, this was harder than I expected, mostly because I noticed I never grokked metaclasses all that well. Now it's slightly better ;-). git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@1344 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
parent
59ebcace2a
commit
cd10080cca
|
@ -95,7 +95,6 @@ noinst_HEADERS += \
|
|||
src/python_cpu_policy_manager.hh
|
||||
|
||||
share_PYTHON = \
|
||||
src/Abstract.py \
|
||||
src/CPUPolicy.py \
|
||||
src/ScriptAdapter.py
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ AM_GNU_GETTEXT_VERSION([0.17])
|
|||
|
||||
dnl PYTHON_VERSION is declared precious by AC_PYTHON_DEVEL,
|
||||
dnl so don't use it here
|
||||
PY_VERSION=2.3
|
||||
PY_VERSION=2.6
|
||||
GTKMM_VERSION=2.8.0
|
||||
SGPEMV2_VERSION=1.0
|
||||
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
## @brief Defines a class to create abstract methods
|
||||
#
|
||||
# @author Ivo Timmermans
|
||||
# @date 2004/01/23
|
||||
# @version 1.1
|
||||
#
|
||||
# Example:
|
||||
# @code
|
||||
# import Abstract;
|
||||
# class Foo:
|
||||
# __metaclass__ = Abstract.Metaclass
|
||||
# foo = Abstract.AbstractMethod('foo')
|
||||
# @endcode
|
||||
class AbstractMethod (object):
|
||||
## @brief Constructor
|
||||
#
|
||||
# @param func name of the function (used when raising an
|
||||
# exception). Its type is str.
|
||||
def __init__(self, func):
|
||||
self._function = func
|
||||
|
||||
## @brief Get callable object
|
||||
#
|
||||
# @return 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.
|
||||
def __get__(self, obj, type):
|
||||
return self.AbstractMethodHelper(self._function, type)
|
||||
|
||||
## @brief Abstract method helper class
|
||||
#
|
||||
# An AbstractMethodHelper instance is a callable object that
|
||||
# represents an abstract method.
|
||||
class AbstractMethodHelper (object):
|
||||
def __init__(self, func, cls):
|
||||
self._function = func
|
||||
self._class = cls
|
||||
|
||||
## @brief Call abstract method
|
||||
#
|
||||
# Raises a TypeError, because abstract methods can not be
|
||||
# called.
|
||||
def __call__(self, *args, **kwargs):
|
||||
raise TypeError('Abstract method `' + self._class.__name__ \
|
||||
+ '.' + self._function + '\' called')
|
||||
|
||||
## @brief Configure a new class to be abstract
|
||||
#
|
||||
# @author Ivo Timmermans
|
||||
# @date 2004/01/23
|
||||
# @version 1.1
|
||||
class Metaclass (type):
|
||||
## Configure a new class
|
||||
#
|
||||
# @param cls Class object
|
||||
# @param name Name of the class
|
||||
# @param bases All base classes for cls
|
||||
def __init__(cls, name, bases, *args, **kwargs):
|
||||
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)
|
||||
|
||||
## @brief Allocator for class cls
|
||||
#
|
||||
# @param self Class object for which an instance should be
|
||||
# created.
|
||||
# @param cls Same as self.
|
||||
def new(self, cls):
|
||||
if len(cls.__abstractmethods__):
|
||||
raise NotImplementedError('Can\'t instantiate class `' + \
|
||||
cls.__name__ + '\';\n' + \
|
||||
'Abstract methods: ' + \
|
||||
", ".join(cls.__abstractmethods__))
|
||||
|
||||
return object.__new__(self)
|
|
@ -1,17 +1,11 @@
|
|||
from Abstract import *
|
||||
from abc import *
|
||||
import sgpem
|
||||
|
||||
## @brief This is the abstract class a user-defined policy
|
||||
# should inherit from
|
||||
## @brief The abstract base class needed for compatibility between
|
||||
# Python 2.6 and Python 3.x.
|
||||
#
|
||||
# This class also exposes the method sort(), which can be
|
||||
# used to easily sort the queue of ready process with a
|
||||
# user-defined given compare function.
|
||||
class CPUPolicy:
|
||||
## @var Avoid instantiation of an abstract class.
|
||||
# @see Abstract.Metaclass
|
||||
__metaclass__ = Metaclass
|
||||
|
||||
# @see CPUPolicy
|
||||
class CPUPolicyBase(object):
|
||||
## @brief Configure policy to initial values
|
||||
#
|
||||
# This is called just before a simulation starts, and is responsible
|
||||
|
@ -26,7 +20,9 @@ class CPUPolicy:
|
|||
# @endcode
|
||||
#
|
||||
# @see sgpem::Policy::get_parameters()
|
||||
configure = AbstractMethod('configure')
|
||||
@abstractmethod
|
||||
def configure(self):
|
||||
pass
|
||||
|
||||
## @brief Sort ready processes queue
|
||||
#
|
||||
|
@ -46,7 +42,9 @@ class CPUPolicy:
|
|||
# swap(positionA, positionB) and size().
|
||||
#
|
||||
# @see Policy::Policy::sort()
|
||||
sort_queue = AbstractMethod('sort_queue')
|
||||
@abstractmethod
|
||||
def sort_queue(self, queue):
|
||||
pass
|
||||
|
||||
## @brief Returns whether the policy wants to be preemptive,
|
||||
# other than by normal time slice termination
|
||||
|
@ -70,7 +68,9 @@ class CPUPolicy:
|
|||
# slice (or a process blocking/termination, of course) before
|
||||
# selecting a new running process, even if it has greater priority
|
||||
# than the current one
|
||||
is_preemptive = AbstractMethod('is_preemptive')
|
||||
@abstractmethod
|
||||
def is_preemptive(self):
|
||||
pass
|
||||
|
||||
## @brief Returns how long is a time-slice for this policy
|
||||
#
|
||||
|
@ -90,7 +90,9 @@ class CPUPolicy:
|
|||
#
|
||||
# @return -1 If the policy doesn't want to use time slices
|
||||
# @return 0+ To specify a time slice duration for this policy
|
||||
get_time_slice = AbstractMethod('get_time_slice')
|
||||
@abstractmethod
|
||||
def get_time_slice(self):
|
||||
pass
|
||||
|
||||
## @brief Returns the PolicyParameters instance you can use in
|
||||
# Policy::Policy::configure()
|
||||
|
@ -178,3 +180,18 @@ class CPUPolicy:
|
|||
# puts pivot in place
|
||||
queue.swap(i,b)
|
||||
return i
|
||||
|
||||
|
||||
|
||||
## @brief This is the abstract class a user-defined policy
|
||||
# should inherit from
|
||||
#
|
||||
# This class also exposes the method sort(), which can be
|
||||
# used to easily sort the queue of ready process with a
|
||||
# user-defined given compare function.
|
||||
#
|
||||
# @see CPUPolicyBase
|
||||
CPUPolicy = ABCMeta('CPUPolicy', (CPUPolicyBase, ), {})
|
||||
|
||||
|
||||
print (dir (CPUPolicy))
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
from CPUPolicy import CPUPolicy
|
||||
|
||||
class rr(CPUPolicy) :
|
||||
class rr(CPUPolicy):
|
||||
"""Round Robin scheduling policy
|
||||
|
||||
This policy executes a thread for a given amount
|
||||
|
|
|
@ -34,13 +34,39 @@ using namespace std;
|
|||
Glib::StaticRecMutex PythonCPUPolicy::_mtx = GLIBMM_STATIC_REC_MUTEX_INIT;
|
||||
|
||||
|
||||
// Convenience porting function for converting from Python 3.0
|
||||
// UCS-(2|4) strings to glib::ustring
|
||||
namespace sgpem
|
||||
{
|
||||
static Glib::ustring
|
||||
PyString_AsString (PyObject* obj)
|
||||
{
|
||||
using ::PyString_AsString;
|
||||
|
||||
Glib::ustring ret;
|
||||
|
||||
PyObject *str = PyObject_Str (obj);
|
||||
if (PyUnicode_Check (str))
|
||||
{
|
||||
PyObject *ustr = PyUnicode_AsUTF8String (str);
|
||||
ret = PyBytes_AsString (ustr);
|
||||
Py_DECREF (ustr);
|
||||
}
|
||||
else
|
||||
ret = PyString_AS_STRING (str);
|
||||
|
||||
Py_DECREF (str);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// WARNING : this class needs extensive and above all
|
||||
// *strong* exception checking / handling!
|
||||
|
||||
PythonCPUPolicy::PythonCPUPolicy(const char* name) throw(MalformedPolicyException)
|
||||
: _upolicy_dict(NULL), _adapter(NULL), _name(name), _description()
|
||||
{
|
||||
PyObject* pLoadmeStr = PyString_FromString(name);
|
||||
PyObject* pLoadmeStr = PyUnicode_FromString (name);
|
||||
PyObject* pUserCPUPolicyModule = PyImport_Import(pLoadmeStr);
|
||||
Py_DECREF(pLoadmeStr);
|
||||
|
||||
|
@ -52,7 +78,7 @@ PythonCPUPolicy::PythonCPUPolicy(const char* name) throw(MalformedPolicyExceptio
|
|||
assert(_upolicy_dict);
|
||||
|
||||
// Loads ScriptAdapter module and get its dictionary
|
||||
pLoadmeStr = PyString_FromString("ScriptAdapter");
|
||||
pLoadmeStr = PyUnicode_FromString("ScriptAdapter");
|
||||
PyObject* pScriptAdapterModule = PyImport_Import(pLoadmeStr);
|
||||
Py_DECREF(pLoadmeStr);
|
||||
assert(pScriptAdapterModule);
|
||||
|
@ -68,7 +94,7 @@ PythonCPUPolicy::PythonCPUPolicy(const char* name) throw(MalformedPolicyExceptio
|
|||
// Retrieve a description for the policy using the __doc__ attribute
|
||||
PyObject* pDescriptionString = PyObject_GetAttrString(pCPUPolicyClass, "__doc__");
|
||||
if(pDescriptionString != Py_None)
|
||||
_description = PyString_AsString(pDescriptionString);
|
||||
_description = sgpem::PyString_AsString(pDescriptionString);
|
||||
Py_DECREF(pDescriptionString);
|
||||
|
||||
// Creates a new object of type ScriptAdapter :
|
||||
|
@ -77,7 +103,7 @@ PythonCPUPolicy::PythonCPUPolicy(const char* name) throw(MalformedPolicyExceptio
|
|||
PyObject* pAdapterCtorParam = PyTuple_New(1);
|
||||
Py_INCREF(pCPUPolicyClass); // PyTuple_SetItem steals a reference
|
||||
PyTuple_SetItem(pAdapterCtorParam, 0, pCPUPolicyClass);
|
||||
_adapter = PyInstance_New(pAdapterClass, pAdapterCtorParam, NULL);
|
||||
_adapter = PyObject_CallObject((PyObject*) pAdapterClass, pAdapterCtorParam);
|
||||
Py_DECREF(pAdapterCtorParam);
|
||||
|
||||
Py_DECREF(pScriptAdapterModule);
|
||||
|
@ -214,7 +240,7 @@ PythonCPUPolicy::get_time_slice() const throw(UserInterruptException, MalformedP
|
|||
// Parse return value stored in global Python object
|
||||
retval = PyObject_CallMethod(_adapter, const_cast<char*>("get_return_value"), NULL);
|
||||
assert(retval);
|
||||
long tmp = PyInt_AsLong(retval);
|
||||
long tmp = PyLong_AsLong(retval);
|
||||
Py_DECREF(retval);
|
||||
|
||||
set_callback_policy(NULL);
|
||||
|
@ -269,12 +295,8 @@ PythonCPUPolicy::wait_unlock() const throw(UserInterruptException, MalformedPoli
|
|||
{
|
||||
if(pException != Py_None)
|
||||
{
|
||||
PyObject* pExceptStr = PyObject_Str(pException);
|
||||
|
||||
string msg = _("unhandled exception in user policy: ");
|
||||
msg += PyString_AsString(pExceptStr);
|
||||
|
||||
Py_DECREF(pExceptStr);
|
||||
msg += sgpem::PyString_AsString(pException);
|
||||
Py_DECREF(pException);
|
||||
|
||||
throw MalformedPolicyException(msg);
|
||||
|
@ -316,11 +338,8 @@ PythonCPUPolicy::get_exception_information()
|
|||
|
||||
if (pValue != NULL)
|
||||
{
|
||||
PyObject* pValueStr = PyObject_Str(pValue);
|
||||
|
||||
msg = PyString_AsString(pValueStr);
|
||||
|
||||
Py_DECREF(pValueStr);
|
||||
msg = sgpem::PyString_AsString(pValue) + "\n";
|
||||
PyErr_PrintEx (false);
|
||||
}
|
||||
else
|
||||
msg = string(_("no available information for this error"));
|
||||
|
|
|
@ -70,8 +70,8 @@ PythonCPUPolicyManager::PythonCPUPolicyManager()
|
|||
// environment variables.
|
||||
|
||||
GlobalPreferences& prefs = GlobalPreferences::get_instance();
|
||||
Glib::ustring importdirs = "import sys\n"
|
||||
"sys.path[:0] = [ ";
|
||||
|
||||
Glib::ustring importdirs = "import sys; sys.path[:0] = [ ";
|
||||
for_each(prefs.get_policy_dirs().begin(),
|
||||
prefs.get_policy_dirs().end(),
|
||||
pol_dirs_concat(importdirs));
|
||||
|
|
Loading…
Reference in New Issue