Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

Commit

Permalink
Backport performances improvement from Python 3 PyEcore version
Browse files Browse the repository at this point in the history
  • Loading branch information
aranega committed May 19, 2018
1 parent b5ddf27 commit 517eb8b
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 40 deletions.
68 changes: 38 additions & 30 deletions pyecore/ecore.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from decimal import Decimal
from datetime import datetime
from ordered_set import OrderedSet
from .notification import ENotifer, Kind, EObserver
from .notification import ENotifer, Kind
from .innerutils import ignored, javaTransMap


Expand Down Expand Up @@ -67,20 +67,20 @@ def getEClassifier(name, searchspace=None):

class Core(object):
@staticmethod
def _promote(cls, abstract=False):
cls.eClass = EClass(cls.__name__, metainstance=cls)
cls.eClass.abstract = abstract
cls._staticEClass = True
def _promote(rcls, abstract=False):
rcls.eClass = EClass(rcls.__name__, metainstance=rcls)
rcls.eClass.abstract = abstract
rcls._staticEClass = True
# init super types
eSuperTypes_add = cls.eClass.eSuperTypes.append
for _cls in cls.__bases__:
eSuperTypes_add = rcls.eClass.eSuperTypes.append
for _cls in rcls.__bases__:
if _cls is EObject:
continue
with ignored(Exception):
eSuperTypes_add(_cls.eClass)
# init eclass by reflection
eStructuralFeatures_add = cls.eClass.eStructuralFeatures.append
for k, feature in cls.__dict__.items():
eStructuralFeatures_add = rcls.eClass.eStructuralFeatures.append
for k, feature in rcls.__dict__.items():
if isinstance(feature, EStructuralFeature):
if not feature.name:
feature.name = k
Expand All @@ -101,13 +101,13 @@ def _promote(cls, abstract=False):
if i < nb_required:
parameter.required = True
operation.eParameters.append(parameter)
cls.eClass.eOperations.append(operation)
rcls.eClass.eOperations.append(operation)

@staticmethod
def register_classifier(cls, abstract=False, promote=False):
@classmethod
def register_classifier(cls, rcls, abstract=False, promote=False):
if promote:
Core._promote(cls, abstract)
epackage = sys.modules[cls.__module__]
cls._promote(rcls, abstract)
epackage = sys.modules[rcls.__module__]
if not hasattr(epackage, 'eClassifiers'):
eclassifs = {}
epackage.eClassifiers = eclassifs
Expand All @@ -121,14 +121,14 @@ def register_classifier(cls, abstract=False, promote=False):
nsURI='http://{}/'.format(pack_name))
if not hasattr(epackage, 'eURIFragment'):
epackage.eURIFragment = eURIFragment
cname = cls.name if isinstance(cls, EClassifier) else cls.__name__
epackage.eClassifiers[cname] = cls
if isinstance(cls, EDataType):
epackage.eClass.eClassifiers.append(cls)
cls._container = epackage
cname = rcls.name if isinstance(rcls, EClassifier) else rcls.__name__
epackage.eClassifiers[cname] = rcls
if isinstance(rcls, EDataType):
epackage.eClass.eClassifiers.append(rcls)
rcls._container = epackage
else:
epackage.eClass.eClassifiers.append(cls.eClass)
cls.eClass._container = epackage
epackage.eClass.eClassifiers.append(rcls.eClass)
rcls.eClass._container = epackage


class EObject(ENotifer):
Expand Down Expand Up @@ -332,6 +332,17 @@ def __init__(self, name=None, eType=None, ordered=True, unique=True,
self.ordered = ordered
self.unique = unique
self.required = required
self._many_cache = self._compute_many()
self._eternal_listener.append(self)

def _compute_many(self):
upper = self.upperBound
lower = self.lowerBound
return upper < 0 or upper > 1 and upper - lower > 1

def notifyChanged(self, notif):
if notif.feature is ETypedElement.upperBound:
self._many_cache = self._compute_many()

@property
def upper(self):
Expand All @@ -343,8 +354,7 @@ def lower(self):

@property
def many(self):
upperbound = self.upperBound
return upperbound < 0 or upperbound > 1
return self._many_cache


class EOperation(ETypedElement):
Expand Down Expand Up @@ -542,9 +552,9 @@ def __init__(self, name=None, eType=None, changeable=True, volatile=False,
self.derived = derived
self.derived_class = derived_class or ECollection
self._name = name
self._eternal_listener.append(self)

def notifyChanged(self, notif):
super(EStructuralFeature, self).notifyChanged(notif)
if notif.feature is ENamedElement.name:
self._name = notif.new

Expand All @@ -561,9 +571,9 @@ def __get__(self, instance, owner=None):
instance_dict[name] = new_value
return new_value._get()
value = instance_dict[name]
if type(value) is EValue:
try:
return value._get()
else:
except AttributeError:
return value

def __set__(self, instance, value):
Expand Down Expand Up @@ -666,23 +676,21 @@ def new_init(self, *args, **kwargs):
instance.__compute_supertypes(),
attr_dict)
instance.__name__ = name
instance.supertypes_updater = EObserver()
instance.supertypes_updater.notifyChanged = instance.__update
instance._eternal_listener.append(instance.supertypes_updater)
return instance

def __init__(self, name=None, superclass=None, abstract=False,
metainstance=None, **kwargs):
super(EClass, self).__init__(name, **kwargs)
self.abstract = abstract
self._eternal_listener.append(self)

def __call__(self, *args, **kwargs):
if self.abstract:
raise TypeError("Can't instantiate abstract EClass {0}"
.format(self.name))
return self.python_class(*args, **kwargs)

def __update(self, notif):
def notifyChanged(self, notif):
# We do not update in case of static metamodel (could be changed)
if getattr(self.python_class, '_staticEClass', False):
return
Expand Down
2 changes: 1 addition & 1 deletion pyecore/resources/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ def resolve(self, fragment, resource=None):

@staticmethod
def extract_rootnum_and_frag(fragment):
if re.match('^/\d+.*', fragment):
if re.match(r'^/\d+.*', fragment):
fragment = fragment[1:]
if '/' in fragment:
index = fragment.index('/')
Expand Down
15 changes: 8 additions & 7 deletions pyecore/valuecontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def isinstance(obj, _type):
return False

@staticmethod
def getRoot(obj):
def get_root(obj):
if not obj:
return None
previous = obj
Expand All @@ -40,13 +40,14 @@ def __init__(self, owner, efeature):
super(PyEcoreValue, self).__init__()
self.owner = owner
self.feature = efeature
self.is_ref = isinstance(efeature, EReference)

def check(self, value):
if not EcoreUtils.isinstance(value, self.feature.eType):
raise BadValueError(value, self.feature.eType)

def _update_container(self, value, previous_value=None):
if not isinstance(self.feature, EReference):
if not self.is_ref:
return
if not self.feature.containment:
return
Expand Down Expand Up @@ -82,7 +83,7 @@ def _set(self, value, update_opposite=True):
owner.notify(notif)
owner._isset.add(efeature)

if not isinstance(efeature, EReference):
if not self.is_ref:
return
self._update_container(value, previous_value)
if not update_opposite:
Expand Down Expand Up @@ -141,7 +142,7 @@ def _get(self):
return self

def _update_opposite(self, owner, new_value, remove=False):
if not isinstance(self.feature, EReference):
if not self.is_ref:
return
eOpposite = self.feature.eOpposite
if not eOpposite:
Expand Down Expand Up @@ -365,14 +366,14 @@ def __setitem__(self, index, item):
raise AttributeError('Operation not permited for "{}" feature'
.format(self.feature.name))

def add(self, item):
def add(self, value):
raise AttributeError('Operation not permited for "{}" feature'
.format(self.feature.name))

def discard(self, item):
def discard(self, value):
raise AttributeError('Operation not permited for "{}" feature'
.format(self.feature.name))

def insert(self, index, item):
def insert(self, index, value):
raise AttributeError('Operation not permited for "{}" feature'
.format(self.feature.name))
18 changes: 16 additions & 2 deletions tests/test_dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,8 @@ def test_create_dynamic_contaiment_getroot():
a1 = A()
b1 = B()
a1.b = b1
assert EcoreUtils.getRoot(b1) is a1
assert EcoreUtils.getRoot(None) is None
assert EcoreUtils.get_root(b1) is a1
assert EcoreUtils.get_root(None) is None
assert b1.eRoot() is a1


Expand Down Expand Up @@ -1009,3 +1009,17 @@ def test_containerswitching():
assert a3.eContainer() is a1
assert a2.eContainer() is None
assert a2.eContainmentFeature() is None


def test_structuralfeature_many_computation():
attrib = EAttribute('attrib')
assert attrib.many is False

attrib.upperBound = -1
assert attrib.many is True

attrib.lowerBound = 2
assert attrib.many is True

attrib.upperBound = attrib.lowerBound
assert attrib.many is False

0 comments on commit 517eb8b

Please sign in to comment.