2020-10-07 08:07:16 -05:00
|
|
|
# -*- mode:Python -*-
|
|
|
|
#
|
|
|
|
# This file is part of the Coriolis Software.
|
Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
* Write a new C++/template wrapper to get rid of boost::python
* The int & long Python type are now merged. So a C/C++ level,
it became "PyLong_X" (remove "PyInt_X") and at Python code
level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
* Configuration is now integrated as a Hurricane component,
makes use of the new C++/template wrapper.
* vlsisapd is now defunct. Keep it in the source for now as
some remaining non essential code may have to be ported in
the future.
* Note: Python code (copy of the migration howto):
* New print function syntax print().
* Changed "dict.has_key(k)" for "k" in dict.
* Changed "except Exception, e" for "except Exception as e".
* The division "/" is now the floating point division, even if
both operand are integers. So 3/2 now gives 1.5 and no longer 1.
The integer division is now "//" : 1 = 3//2. So have to carefully
review the code to update. Most of the time we want to use "//".
We must never change to float for long that, in fact, represents
DbU (exposed as Python int type).
* execfile() must be replaced by exec(open("file").read()).
* iter().__next__() becomes iter(x).__next__().
* __getslice__() has been removed, integrated to __getitem__().
* The formating used for str(type(o)) has changed, so In Stratus,
have to update them ("<class 'MyClass'>" instead of "MyClass").
* the "types" module no longer supply values for default types
like str (types.StringType) or list (types.StringType).
Must use "isinstance()" where they were occuring.
* Remove the 'L' to indicate "long integer" (like "12L"), now
all Python integer are long.
* Change in bootstrap:
* Ported Coriolis builder (ccb) to Python3.
* Ported Coriolis socInstaller.py to Python3.
* Note: In PyQt4+Python3, QVariant no longer exists. Use None or
directly convert using the python syntax: bool(x), int(x), ...
By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
* In order to compile user's must upgrade to my own rebuild of
PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
buffer of the H-Tree to the original signal (mainly: top clock).
Strangely, it was only done when working in full chip mode.
2021-09-19 12:41:24 -05:00
|
|
|
# Copyright (c) Sorbonne Université 2020-2021, All Rights Reserved
|
2020-10-07 08:07:16 -05:00
|
|
|
#
|
|
|
|
# +-----------------------------------------------------------------+
|
|
|
|
# | C O R I O L I S |
|
|
|
|
# | C o r i o l i s / C h a m s B u i l d e r |
|
|
|
|
# | |
|
|
|
|
# | Author : Jean-Paul Chaput |
|
|
|
|
# | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
|
|
# | =============================================================== |
|
|
|
|
# | Python : "./crlcore/helpers/utils.py" |
|
|
|
|
# +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
"""
|
|
|
|
Miscellaeous utilities. Contains:
|
|
|
|
|
|
|
|
* ``classdecorator`` : A class decorator, wrap a new class instance
|
|
|
|
around and exsiting one and create proxies for all it's attributes
|
|
|
|
and methods.
|
|
|
|
"""
|
|
|
|
|
|
|
|
import types
|
|
|
|
import inspect
|
|
|
|
import functools
|
|
|
|
|
|
|
|
|
|
|
|
def classdecorator ( cls ):
|
|
|
|
"""
|
|
|
|
Decorate an instance of a class. It is not an implementation of the Design
|
|
|
|
Pattern, instead of using Concrete/Abstract classes and inheritance, it just
|
|
|
|
create proxies for the base class attributes & methods in the derived one.
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
class Base ( object ):
|
|
|
|
|
|
|
|
def __init__ ( self, param1 ):
|
|
|
|
self.param1 = param1
|
|
|
|
|
|
|
|
def func1 ( self ):
|
|
|
|
return self.param1
|
|
|
|
|
|
|
|
@classdecorator
|
|
|
|
class DecoratedClass ( object ):
|
|
|
|
|
|
|
|
def __init__ ( self, param2 )
|
|
|
|
self.param2 = param2
|
|
|
|
|
|
|
|
def func2 ( self ):
|
|
|
|
return self.param2
|
|
|
|
|
|
|
|
base = Base( 'Value1' )
|
|
|
|
decorated = Decorated( 'Value2' )
|
|
|
|
print( 'decorated.param1 = {}'.format(decorated.param1) )
|
|
|
|
print( 'decorated.param2 = {}'.format(decorated.param2) )
|
|
|
|
print( 'decorated.func1 = {}'.format(decorated.func1()) )
|
|
|
|
print( 'decorated.func2 = {}'.format(decorated.func2()) )
|
|
|
|
|
|
|
|
|
|
|
|
Technical note
|
|
|
|
==============
|
|
|
|
|
|
|
|
A hidden attribute ``_baseClass`` is added that contains an *instance* of
|
|
|
|
the base class (that is, not the class type itself). Then the
|
|
|
|
``__setattr__()`` and ``__getattr__()`` of the decorated class instance
|
|
|
|
(``cls``) are replaced by versions that tries first to find attributes in
|
|
|
|
the base class. The ``__init__()`` of the decorated class is also
|
|
|
|
redefined so that it *imports* all the methods of the base class in the
|
|
|
|
decorated one at runtime.
|
|
|
|
|
|
|
|
Methods binding: the base class methods importeds into the decorated one
|
|
|
|
stay bound the the *base* class. As far as I understand, this should cause
|
|
|
|
no problem as long as the base class instance exists, which should always
|
|
|
|
be the case.
|
|
|
|
"""
|
|
|
|
|
2020-10-14 08:06:42 -05:00
|
|
|
def isprop ( attr ): return isinstance( attr, property )
|
|
|
|
|
2020-10-07 08:07:16 -05:00
|
|
|
def wrappedSetattr ( self, attr, v ):
|
Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
* Write a new C++/template wrapper to get rid of boost::python
* The int & long Python type are now merged. So a C/C++ level,
it became "PyLong_X" (remove "PyInt_X") and at Python code
level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
* Configuration is now integrated as a Hurricane component,
makes use of the new C++/template wrapper.
* vlsisapd is now defunct. Keep it in the source for now as
some remaining non essential code may have to be ported in
the future.
* Note: Python code (copy of the migration howto):
* New print function syntax print().
* Changed "dict.has_key(k)" for "k" in dict.
* Changed "except Exception, e" for "except Exception as e".
* The division "/" is now the floating point division, even if
both operand are integers. So 3/2 now gives 1.5 and no longer 1.
The integer division is now "//" : 1 = 3//2. So have to carefully
review the code to update. Most of the time we want to use "//".
We must never change to float for long that, in fact, represents
DbU (exposed as Python int type).
* execfile() must be replaced by exec(open("file").read()).
* iter().__next__() becomes iter(x).__next__().
* __getslice__() has been removed, integrated to __getitem__().
* The formating used for str(type(o)) has changed, so In Stratus,
have to update them ("<class 'MyClass'>" instead of "MyClass").
* the "types" module no longer supply values for default types
like str (types.StringType) or list (types.StringType).
Must use "isinstance()" where they were occuring.
* Remove the 'L' to indicate "long integer" (like "12L"), now
all Python integer are long.
* Change in bootstrap:
* Ported Coriolis builder (ccb) to Python3.
* Ported Coriolis socInstaller.py to Python3.
* Note: In PyQt4+Python3, QVariant no longer exists. Use None or
directly convert using the python syntax: bool(x), int(x), ...
By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
* In order to compile user's must upgrade to my own rebuild of
PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
buffer of the H-Tree to the original signal (mainly: top clock).
Strangely, it was only done when working in full chip mode.
2021-09-19 12:41:24 -05:00
|
|
|
if attr != '_baseClass' and (attr in self._baseClass.__dict__):
|
2020-10-07 08:07:16 -05:00
|
|
|
self._baseClass.__setattr__( attr, v )
|
|
|
|
object.__setattr__( self, attr, v )
|
|
|
|
|
|
|
|
def wrappedGetattr ( self, attr ):
|
|
|
|
if attr == '_baseClass': return self.__dict__['_baseClass']
|
Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
* Write a new C++/template wrapper to get rid of boost::python
* The int & long Python type are now merged. So a C/C++ level,
it became "PyLong_X" (remove "PyInt_X") and at Python code
level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
* Configuration is now integrated as a Hurricane component,
makes use of the new C++/template wrapper.
* vlsisapd is now defunct. Keep it in the source for now as
some remaining non essential code may have to be ported in
the future.
* Note: Python code (copy of the migration howto):
* New print function syntax print().
* Changed "dict.has_key(k)" for "k" in dict.
* Changed "except Exception, e" for "except Exception as e".
* The division "/" is now the floating point division, even if
both operand are integers. So 3/2 now gives 1.5 and no longer 1.
The integer division is now "//" : 1 = 3//2. So have to carefully
review the code to update. Most of the time we want to use "//".
We must never change to float for long that, in fact, represents
DbU (exposed as Python int type).
* execfile() must be replaced by exec(open("file").read()).
* iter().__next__() becomes iter(x).__next__().
* __getslice__() has been removed, integrated to __getitem__().
* The formating used for str(type(o)) has changed, so In Stratus,
have to update them ("<class 'MyClass'>" instead of "MyClass").
* the "types" module no longer supply values for default types
like str (types.StringType) or list (types.StringType).
Must use "isinstance()" where they were occuring.
* Remove the 'L' to indicate "long integer" (like "12L"), now
all Python integer are long.
* Change in bootstrap:
* Ported Coriolis builder (ccb) to Python3.
* Ported Coriolis socInstaller.py to Python3.
* Note: In PyQt4+Python3, QVariant no longer exists. Use None or
directly convert using the python syntax: bool(x), int(x), ...
By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
* In order to compile user's must upgrade to my own rebuild of
PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
buffer of the H-Tree to the original signal (mainly: top clock).
Strangely, it was only done when working in full chip mode.
2021-09-19 12:41:24 -05:00
|
|
|
if attr in self.__dict__: return self.__dict__[attr]
|
2020-10-14 08:06:42 -05:00
|
|
|
selfClass = type( self )
|
Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
* Write a new C++/template wrapper to get rid of boost::python
* The int & long Python type are now merged. So a C/C++ level,
it became "PyLong_X" (remove "PyInt_X") and at Python code
level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
* Configuration is now integrated as a Hurricane component,
makes use of the new C++/template wrapper.
* vlsisapd is now defunct. Keep it in the source for now as
some remaining non essential code may have to be ported in
the future.
* Note: Python code (copy of the migration howto):
* New print function syntax print().
* Changed "dict.has_key(k)" for "k" in dict.
* Changed "except Exception, e" for "except Exception as e".
* The division "/" is now the floating point division, even if
both operand are integers. So 3/2 now gives 1.5 and no longer 1.
The integer division is now "//" : 1 = 3//2. So have to carefully
review the code to update. Most of the time we want to use "//".
We must never change to float for long that, in fact, represents
DbU (exposed as Python int type).
* execfile() must be replaced by exec(open("file").read()).
* iter().__next__() becomes iter(x).__next__().
* __getslice__() has been removed, integrated to __getitem__().
* The formating used for str(type(o)) has changed, so In Stratus,
have to update them ("<class 'MyClass'>" instead of "MyClass").
* the "types" module no longer supply values for default types
like str (types.StringType) or list (types.StringType).
Must use "isinstance()" where they were occuring.
* Remove the 'L' to indicate "long integer" (like "12L"), now
all Python integer are long.
* Change in bootstrap:
* Ported Coriolis builder (ccb) to Python3.
* Ported Coriolis socInstaller.py to Python3.
* Note: In PyQt4+Python3, QVariant no longer exists. Use None or
directly convert using the python syntax: bool(x), int(x), ...
By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
* In order to compile user's must upgrade to my own rebuild of
PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
buffer of the H-Tree to the original signal (mainly: top clock).
Strangely, it was only done when working in full chip mode.
2021-09-19 12:41:24 -05:00
|
|
|
if attr in selfClass.__dict__:
|
2020-10-14 08:06:42 -05:00
|
|
|
prop = selfClass.__dict__[attr]
|
|
|
|
if isprop(prop):
|
|
|
|
return prop.__get__(self)
|
|
|
|
return prop
|
|
|
|
if not hasattr(self,'_baseClass'):
|
|
|
|
raise AttributeError( '\'{}\' object has no attribute or method named \'{}\'' \
|
2020-10-07 08:07:16 -05:00
|
|
|
.format(self.__class__.__name__,attr) )
|
2020-10-14 08:06:42 -05:00
|
|
|
return wrappedGetattr( self._baseClass, attr )
|
2020-10-07 08:07:16 -05:00
|
|
|
|
|
|
|
classInit = cls.__init__
|
|
|
|
|
|
|
|
@functools.wraps(classInit)
|
|
|
|
def wrappedInit ( self, baseClass, *args, **kwargs ):
|
|
|
|
self._baseClass = baseClass
|
|
|
|
for method in inspect.getmembers(self._baseClass, predicate=inspect.ismethod):
|
|
|
|
if method[0] == '__init__': continue
|
|
|
|
self.__setattr__( method[0], method[1] )
|
|
|
|
classInit( self, *args, **kwargs )
|
|
|
|
|
|
|
|
cls.__init__ = wrappedInit
|
|
|
|
cls.__setattr__ = wrappedSetattr
|
|
|
|
cls.__getattr__ = wrappedGetattr
|
|
|
|
return cls
|
|
|
|
|