Example #1
0
def test_alias_function_static():

    @EMetaclass
    class A(object):
        from_ = EAttribute(eType=EString)

    a = A()
    assert getattr(a, 'from', -1) == -1

    alias('from', A.from_, eclass=A)
    assert getattr(a, 'from') is None

    @EMetaclass
    class B(object):
        as_ = EAttribute(eType=EInt)

    b = B()
    assert getattr(b, 'as', -1) == -1

    alias('as', B.as_)
    assert getattr(b, 'as') is 0

    b.as_ = 4
    assert b.as_ == 4
    assert getattr(b, 'as') == 4
Example #2
0
    def load_energy_system(self, name):
        # create a resourceSet that hold the contents of the esdl.ecore model and the instances we use/create
        rset = ResourceSet()

        # Assign files with the .esdl extension to the XMLResource instead of default XMI
        rset.resource_factory['esdl'] = lambda uri: XMLResource(uri)

        # Read the lastest esdl.ecore from github
        esdl_model_resource = rset.get_resource(
            HttpURI(
                'https://raw.githubusercontent.com/EnergyTransition/ESDL/master/esdl/model/esdl.ecore'
            ))

        esdl_model = esdl_model_resource.contents[0]
        # print('Namespace: {}'.format(esdl_model.nsURI))
        rset.metamodel_registry[esdl_model.nsURI] = esdl_model

        # Create a dynamic model from the loaded esdl.ecore model, which we can use to build Energy Systems
        esdl = DynamicEPackage(esdl_model)

        # fix python buildin 'from' that is also used in ProfileElement as attribute
        # use 'start' instead of 'from' when using a ProfileElement
        alias('start', esdl.ProfileElement.findEStructuralFeature('from'))

        # have a nice __repr__ for some ESDL classes when printing ESDL objects (includes all Assets and EnergyAssets)
        esdl.Item.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        esdl.Carrier.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        esdl.Geometry.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        esdl.QuantityAndUnitType.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.id, EnergySystemHandler.attr_to_dict(x))
        esdl.QuantityAndUnitReference.python_class.__repr__ = lambda x: '{}: ({})'.format(
            'QuantityAndUnitReference', EnergySystemHandler.attr_to_dict(x))
        esdl.KPI.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        esdl.ProfileElement.python_class.__repr__ = lambda x: 'ProfileElement ({})'.format(
            EnergySystemHandler.attr_to_dict(x))

        # load the ESDL file
        resource = rset.get_resource(URI(name))
        es = resource.contents[0]
        # At this point, the model instance is loaded!

        # get notifications of changes in the EnergySystem model
        #observer = PrintNotification(es)
        #observer2 = PrintNotification(es.instance[0].area)

        # also return the esdlm and rset reference, so we can create esdl classes and store them as strings
        return es, resource, esdl, rset
    def __init__(self, name=None):
        # create a resourceSet that hold the contents of the esdl.ecore model and the instances we use/create
        self.rset = ResourceSet()

        # Assign files with the .esdl extension to the XMLResource instead of default XMI
        self.rset.resource_factory['esdl'] = lambda uri: XMLResource(uri)

        # Read the esdl.ecore from the tmp folder
        esdl_model_resource = self.rset.get_resource(
            URI('tmp/esdl/esdl.ecore'))

        esdl_model = esdl_model_resource.contents[0]
        # print('Namespace: {}'.format(esdl_model.nsURI))
        self.rset.metamodel_registry[esdl_model.nsURI] = esdl_model

        # Create a dynamic model from the loaded esdl.ecore model, which we can use to build Energy Systems
        self.esdl = DynamicEPackage(esdl_model)

        # fix python buildin 'from' that is also used in ProfileElement as attribute
        # use 'start' instead of 'from' when using a ProfileElement
        alias('start', self.esdl.ProfileElement.findEStructuralFeature('from'))

        # have a nice __repr__ for some ESDL classes when printing ESDL objects (includes all Assets and EnergyAssets)
        self.esdl.Item.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.Carrier.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.Geometry.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.QuantityAndUnitType.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.id, EnergySystemHandler.attr_to_dict(x))
        self.esdl.QuantityAndUnitReference.python_class.__repr__ = lambda x: '{}: ({})'.format(
            'QuantityAndUnitReference', EnergySystemHandler.attr_to_dict(x))
        self.esdl.KPI.python_class.__repr__ = lambda x: '{}: ({})'.format(
            x.name, EnergySystemHandler.attr_to_dict(x))
        self.esdl.ProfileElement.python_class.__repr__ = lambda x: 'ProfileElement ({})'.format(
            EnergySystemHandler.attr_to_dict(x))

        if name:
            self.name = name
            self.load_energy_system(name)
Example #4
0
    def __init__(self, energy_system=None):
        if energy_system is not None:
            self.energy_system = energy_system
        self.resource = None
        self.rset = ResourceSet()
        self.esid_uri_dict = {}

        self._set_resource_factories()

        # fix python builtin 'from' that is also used in ProfileElement as attribute
        # use 'start' instead of 'from' when using a ProfileElement
        # and make sure that it is serialized back as 'from' instead of 'from_'
        esdl.ProfileElement.from_.name = 'from'
        setattr(esdl.ProfileElement, 'from', esdl.ProfileElement.from_)
        alias('start', esdl.ProfileElement.from_)
        # also for FromToIntItem
        esdl.FromToIntItem.from_.name = 'from'
        setattr(esdl.FromToIntItem, 'from', esdl.FromToIntItem.from_)
        alias('start', esdl.FromToIntItem.from_)
        # also for FromToDoubleItem
        esdl.FromToDoubleItem.from_.name = 'from'
        setattr(esdl.FromToDoubleItem, 'from', esdl.FromToDoubleItem.from_)
        alias('start', esdl.FromToDoubleItem.from_)

        # add support for cloning of EObjects and coppy.copy()
        setattr(EObject, '__copy__', support_functions.clone)
        setattr(EObject, 'clone', support_functions.clone)

        # add support for deepcopying EObjects and copy.deepcopy()
        setattr(EObject, '__deepcopy__', support_functions.deepcopy)
        setattr(EObject, 'deepcopy', support_functions.deepcopy)

        # have a nice __repr__ for some ESDL classes when printing ESDL objects (includes all Assets and EnergyAssets)
        esdl.EnergySystem.__repr__ = \
            lambda x: '{}: ({})'.format(x.name, EnergySystemHandler.attr_to_dict(x))
Example #5
0
def test_alias_function_dynamic():
    A = EClass('A')
    A.eStructuralFeatures.append(EAttribute('from', EString))

    a = A()
    assert getattr(a, 'from_', -1) == -1

    alias('from_', A.findEStructuralFeature('from'), eclass=A)
    assert a.from_ is None

    B = EClass('B')
    B.eStructuralFeatures.append(EAttribute('as', EInt))

    b = B()
    assert getattr(b, 'as_', -1) == -1

    alias('as_', B.findEStructuralFeature('as'))
    assert b.as_ is 0

    b.as_ = 4
    assert b.as_ == 4
    assert getattr(b, 'as') == 4
Example #6
0
    def __init__(self):
        self.rset = None
        self.resource = None
        self.energy_system = None

        self._new_resource_set()

        esdl.ProfileElement.from_.name = 'from'
        setattr(esdl.ProfileElement, 'from', esdl.ProfileElement.from_)
        alias('start', esdl.ProfileElement.from_)

        esdl.FromToIntPerc.from_.name = 'from'
        setattr(esdl.FromToIntPerc, 'from', esdl.FromToIntPerc.from_)
        alias('start', esdl.FromToIntPerc.from_)

        esdl.FromToDoublePerc.from_.name = 'from'
        setattr(esdl.FromToDoublePerc, 'from', esdl.FromToDoublePerc.from_)
        alias('start', esdl.FromToDoublePerc.from_)
Example #7
0
    def __init__(self, energy_system=None):
        if energy_system is not None:
            self.energy_system = energy_system
        self.resource = None
        self.rset = ResourceSet()
        self.esid_uri_dict = {}

        self._set_resource_factories()

        # fix python builtin 'from' that is also used in ProfileElement as attribute
        # use 'start' instead of 'from' when using a ProfileElement
        # alias('start', esdl.ProfileElement.findEStructuralFeature('from'))
        esdl.ProfileElement.from_.name = 'from'
        setattr(esdl.ProfileElement, 'from', esdl.ProfileElement.from_)
        alias('start', esdl.ProfileElement.from_)

        esdl.FromToIntItem.from_.name = 'from'
        setattr(esdl.FromToIntItem, 'from', esdl.FromToIntItem.from_)
        alias('start', esdl.FromToIntItem.from_)

        esdl.FromToDoubleItem.from_.name = 'from'
        setattr(esdl.FromToDoubleItem, 'from', esdl.FromToDoubleItem.from_)
        alias('start', esdl.FromToDoubleItem.from_)

        # add support for shallow copying or cloning an object
        # it copies the object's attributes (e.g. clone an object), does only shallow copying
        def clone(self):
            """
            Shallow copying or cloning an object
            It only copies the object's attributes (e.g. clone an object)
            Usage object.clone() or copy.copy(object) (as _copy__() is also implemented)
            :param self:
            :return: A clone of the object
            """
            newone = type(self)()
            eclass = self.eClass
            for x in eclass.eAllStructuralFeatures():
                if isinstance(x, EAttribute):
                    #logger.trace("clone: processing attribute {}".format(x.name))
                    if x.many:
                        eOrderedSet = newone.eGet(x.name)
                        for v in self.eGet(x.name):
                            eOrderedSet.append(v)
                    else:
                        newone.eSet(x.name, self.eGet(x.name))
            return newone

        setattr(EObject, '__copy__', clone)
        setattr(EObject, 'clone', clone)
        """
        Deep copying an EObject.
        Does not work yet for copying references from other resources than this one.
        """

        def deepcopy(self, memo=None):
            logger.debug("deepcopy: processing {}".format(self))
            first_call = False
            if memo is None:
                memo = dict()
                first_call = True
            if self in memo:
                return memo[self]

            copy: EObject = self.clone()
            logger.debug("Shallow copy: {}".format(copy))
            eclass: EClass = self.eClass
            for x in eclass.eAllStructuralFeatures():
                if isinstance(x, EReference):
                    #logger.debug("deepcopy: processing reference {}".format(x.name))
                    ref: EReference = x
                    value: EStructuralFeature = self.eGet(ref)
                    if value is None:
                        continue
                    if ref.containment:
                        if ref.many and isinstance(value, EAbstractSet):
                            #clone all containment elements
                            eAbstractSet = copy.eGet(ref.name)
                            for ref_value in value:
                                duplicate = ref_value.__deepcopy__(memo)
                                eAbstractSet.append(duplicate)
                        else:
                            copy.eSet(ref.name, value.__deepcopy__(memo))
                    #else:
                    #    # no containment relation, but a reference
                    #    # this can only be done after a full copy
                    #    pass
            # now copy should a full copy, but without cross references

            memo[self] = copy

            if first_call:
                logger.debug("copying references")
                for k, v in memo.items():
                    eclass: EClass = k.eClass
                    for x in eclass.eAllStructuralFeatures():
                        if isinstance(x, EReference):
                            #logger.debug("deepcopy: processing x-reference {}".format(x.name))
                            ref: EReference = x
                            orig_value: EStructuralFeature = k.eGet(ref)
                            if orig_value is None:
                                continue
                            if not ref.containment:
                                opposite = ref.eOpposite
                                if opposite and opposite.containment:
                                    # do not handle eOpposite relations, they are handled automatically in pyEcore
                                    continue
                                if x.many:
                                    eAbstractSet = v.eGet(ref.name)
                                    for orig_ref_value in orig_value:
                                        try:
                                            copy_ref_value = memo[
                                                orig_ref_value]
                                        except KeyError:
                                            logger.warning(
                                                f'Cannot find reference of type {orig_ref_value.eClass.Name} \
                                                for reference {k.eClass.name}.{ref.name} in deepcopy memo, using original'
                                            )
                                            copy_ref_value = orig_ref_value
                                        eAbstractSet.append(copy_ref_value)
                                else:
                                    try:
                                        copy_value = memo[orig_value]
                                    except KeyError:
                                        logger.warning(
                                            f'Cannot find reference of type {orig_value.eClass.name} of \
                                            reference {k.eClass.name}.{ref.name} in deepcopy memo, using original'
                                        )
                                        copy_value = orig_value
                                    v.eSet(ref.name, copy_value)
            return copy

        setattr(EObject, '__deepcopy__', deepcopy)
        setattr(EObject, 'deepcopy', deepcopy)
        # show deleted object from memory
        # setattr(EObject, '__del__', lambda x: print('Deleted {}'.format(x.eClass.name)))

        # def update_id(n: Notification):
        #     if isinstance(n.feature, EAttribute):
        #         #print(n)
        #         if n.feature.name == 'id':
        #             resource = n.notifier.eResource
        #             if resource is not None and (n.kind != Kind.UNSET and n.kind != Kind.REMOVE):
        #                 print('ADDING to UUID dict {}#{}, notification type {}'.format(n.notifier.eClass.name, n.feature.name, n.kind.name))
        #                 resource.uuid_dict[n.new] = n.notifier
        #                 if n.old is not None and n.old is not '':
        #                     del resource.uuid_dict[n.old]
        # observer = EObserver()
        # observer.notifyChanged = update_id
        #
        # old_init = EObject.__init__
        # def new_init(self, **kwargs):
        #     observer.observe(self)
        #     old_init(self, **kwargs)
        #
        # setattr(EObject, '__init__', new_init)

        # Methods to automatically update the uuid_dict.
        # Currently disabled, because it does not work in all circumstances
        # This only works when the object which id is to be added to the dict is already part
        # of the energysystem xml tree, otherwise there is no way of knowing to which uuid_dict it should be added.
        # E.g.
        # > asset = esdl.Asset(id='uuid)
        # > asset.port.append(esdl.InPort(id='uuid)) # this does not work because asset is not part of the energy system yet
        # > area.asset.append(asset) #works for asset, but not for port. In order to have port working too, this statement
        # should be executed bofore adding the port...

        # old_set = EObject.__setattr__
        # def updated_set(self, feature, value):
        #     old_set(self, feature, value)
        #     #if feature == 'id':
        #     #print('Feature :{}#{}, value={}, resource={}'.format(self.eClass.name, feature, value, '?'))
        #     #if isinstance(feature, EReference):
        #     if hasattr(value, 'id') and feature[0] != '_':
        #         print('*****Update uuid_dict {}#{} for {}#id'.format(self.eClass.name, feature, value.eClass.name))
        #         self.eResource.uuid_dict[value.id] = value
        # setattr(EObject, '__setattr__', updated_set)
        #
        #
        #
        # old_append = EAbstractSet.append
        # def updated_append(self, value, update_opposite=True):
        #     old_append(self, value, update_opposite)
        #     #print('EAbstractSet :{}, value={}, resource={}, featureEr={}'.format(self, value, value.eResource, self.feature.eResource))
        #     if hasattr(value, 'id'):
        #         if self.feature.eResource:
        #             print('****Update uuid_dict AbstractSet-{}#id'.format(value.eClass.name))
        #             self.feature.eResource.uuid_dict[value.id] = value
        #         elif value.eResource:
        #             print('****Update uuid_dict AbstractSet-{}#id'.format(value.eClass.name))
        #             value.eResource.uuid_dict[value.id] = value
        #
        # setattr(EAbstractSet, 'append', updated_append)

        # def toJSON(self):
        #     return json.dumps(self, default=lambda o: list(o),
        #                       sort_keys=True, indent=4)
        # setattr(EOrderedSet, 'toJSON', toJSON)

        # have a nice __repr__ for some ESDL classes when printing ESDL objects (includes all Assets and EnergyAssets)
        esdl.EnergySystem.__repr__ = \
            lambda x: '{}: ({})'.format(x.name, EnergySystemHandler.attr_to_dict(x))