Clone object attributes


#1

Hi !
I create an ontology and I have multiple objects with the same Attribute.
For example, in case of exchange I can have an account ID for the sender and account Id for the destination.
Both Account ID are present in the same object and they are linked to the Same Attribute.
I obtain the following error Exception: More than one attribute with name Account ID. Names must be unique
And thus despite the fact I use the AccountID.clone() inside my object

To illustrate:
Ontology.py inspired by Lampyre ontology file.

class AttributesProvider:
    def __init__(self):
        self.__attr_types = {}
        self.Exchange = self.__ExchangeAttrsProvider()

    class __ExchangeAttrsProvider:
        @property
        def AccountID(self):
            return Attributes.str('Account ID')
			
		@property
        def Article(self):
            return Attributes.str('Article')

    # region Internal methods
    def generate(self, name, vtype):
        if not name:
            raise Exception('Attribute name can\'t be empty')

        if name in self.__attr_types and vtype != self.__attr_types[name]:
            raise Exception(f'Attribute {name} redeclared with different type')
        else:
            self.__attr_types[name] = vtype
        return Attribute(name, vtype)  # must be always new instance

    def str(self, name):
        return self.generate(name, ValueType.String)

Attributes = AttributesProvider()


class Exchange(metaclass=Object):
    SenderAccountID = Attributes.Exchange.AccountID.clone()
    DestinationAccountID = Attributes.Exchange.AccountID.clone()
    Article = Attributes.Exchange.Article

    IdentAttrs = [SenderAccountID]
    CaptionAttrs = [SenderAccountID, DestinationAccountID, Article]

Can you help me ?
Thanks !


#2

As it said in the error message, attribute names for object must be unique, and you are trying to create an object type with two attributes named "Account ID". Attributes are characteristics of your entity, and having many same characteristics is impossible. Just split it into two attributes:

class __ExchangeAttrsProvider:
    @property
    def SenderAccountID(self):
        return Attributes.str('Sender account ID')

    @property
    def DestinationAccountID(self):
        return Attributes.str('Destination account ID')
...

class Exchange(metaclass=Object):
    SenderAccountID = Attributes.Exchange.SenderAccountID
    DestinationAccountID = Attributes.Exchange.DestinationAccountID
    Article = Attributes.Exchange.Article

    IdentAttrs = [SenderAccountID]
    CaptionAttrs = [SenderAccountID, DestinationAccountID, Article]

A clone() method is used to reuse attribute variable in many entity descriptions. If you reuse entity attribute without cloning, it may become identifying or caption for new entity. clone() creates a new attribute without such properties.

name_attr = Attribute('Name', ValueType.String)

# in both object descriptions clone() should be used or new attribute created

class Cat(metaclass=Object):
    Name = name_attr
    # attribute changed here, it became identifiyng and caption
    IdentAttrs = CaptionAttrs = [Name]  

class Person(metaclass=Object):
    # this attribute will be identifying and caption for person too
    Name = name_attr  

That’s why in ontology’s Attributes every property returns new attribute each time.


#3

Thanks for the answer !
I have misunderstand the Clone() method.

Thanks a lot for the clarification.

Just to be sure, the clone() is done implicitly with the AttributesProvider class. That’s right ?


#4

Yes, it does the same thing + provides syntactic sugar for you to reuse attributes in different entities.