@@ -436,12 +436,29 @@ def record_field(self, entry_id: int, field_name: str):
436
436
self ._field_records [c ] = {(entry_id , field_name )}
437
437
438
438
def on_entry_creation (
439
- self , entry : Entry , component_name : Optional [str ] = None
439
+ self ,
440
+ entry : Entry ,
441
+ component_name : Optional [str ] = None ,
440
442
):
441
443
"""
442
444
Call this when adding a new entry, will be called
443
445
in :class:`~forte.data.ontology.core.Entry` when
444
- its `__init__` function is called.
446
+ its `__init__` function is called. This method does
447
+ the following 2 operations with regards to creating
448
+ a new entry.
449
+
450
+ - All ``dataclass`` attributes of the entry to be created
451
+ are stored in the class level dictionary of
452
+ :class:`~forte.data.ontology.core.Entry` called
453
+ ``cached_attributes_data``. This is used to initialize
454
+ the corresponding entry's objects data store entry
455
+ - On creation of the data store entry, this methods associates
456
+ ``getter`` and ``setter`` properties to all `dataclass`
457
+ attributes of this entry to allow direct interaction
458
+ between the attributes of the entry and their copy being
459
+ stored in the data store. For example, the `setter` method
460
+ updates the data store value of an attribute of a given entry
461
+ whenever the attribute in the entry's object is updated.
445
462
446
463
Args:
447
464
entry: The entry to be added.
@@ -541,16 +558,51 @@ def entry_getter(cls: Entry, attr_name: str):
541
558
def entry_setter (cls : Entry , value : Any , attr_name : str ):
542
559
"""A setter function for dataclass fields of entry object.
543
560
When the value contains entry objects, we will convert them into
544
- ``tid``s before storing to ``DataStore``.
561
+ ``tid``s before storing to ``DataStore``. Additionally, if the entry
562
+ setter method is called on an attribute that does not have a pack
563
+ associated with it (as is the case during intialization), the value
564
+ of the atttribute is stored in the class level cache of the ``Entry``
565
+ class. On the other hand, if a pack is associated with the entry,
566
+ the value will directly be stored in the data store.
545
567
546
568
Args:
547
569
cls: An ``Entry`` class object.
548
570
value: The value to be assigned to the attribute.
549
571
attr_name: The name of the attribute.
550
572
"""
551
573
attr_value : Any
574
+
575
+ try :
576
+ pack = cls .pack
577
+ except AttributeError as err :
578
+ # This is the case when an object of an entry that has already been
579
+ # created before (which means an setter and getter properties are
580
+ # associated with its dataclass fields) is trying to be initialized.
581
+ # In this case, a pack is not yet associated with this entry. Thus,
582
+ # we store the initial values dataclass fields of such entries in the
583
+ # _cached_attribute_data of the Entry class.
584
+
585
+ # pylint: disable=protected-access
586
+ if cls .entry_type () not in Entry ._cached_attribute_data :
587
+ Entry ._cached_attribute_data [cls .entry_type ()] = {}
588
+
589
+ if (
590
+ attr_name
591
+ not in Entry ._cached_attribute_data [cls .entry_type ()]
592
+ ):
593
+ Entry ._cached_attribute_data [cls .entry_type ()][
594
+ attr_name
595
+ ] = value
596
+ return
597
+ else :
598
+ raise KeyError (
599
+ "You are trying to overwrite the value "
600
+ f"of { attr_name } for a data store entry "
601
+ "before it is created."
602
+ ) from err
603
+
552
604
data_store_ref = (
553
- cls . pack ._data_store # pylint: disable=protected-access
605
+ pack ._data_store # pylint: disable=protected-access
554
606
)
555
607
556
608
attr_type = data_store_ref .get_attr_type (
@@ -594,6 +646,27 @@ def entry_setter(cls: Entry, value: Any, attr_name: str):
594
646
tid = cls .tid , attr_name = attr_name , attr_value = attr_value
595
647
)
596
648
649
+ # If this is the first time an entry of this type is
650
+ # created, its attributes do not have a getter and setter
651
+ # property associated with them. We can thus assume that there
652
+ # no key in the _cached_attribute_data dictionary that has yet
653
+ # been created to store the dataclass fields of this entry. Thus,
654
+ # we create an empty dictionary to store the dataclass fields
655
+ # of this new entry and manually add all dataclass attributes
656
+ # that have been initialized to the _cached_attribute_data dict.
657
+ # We fetch the values of all dataclass fields by using the getattr
658
+ # method.
659
+
660
+ # pylint: disable=protected-access
661
+ if entry .entry_type () not in Entry ._cached_attribute_data :
662
+ Entry ._cached_attribute_data [entry .entry_type ()] = {}
663
+ for name in entry .__dataclass_fields__ :
664
+ attr_val = getattr (entry , name , None )
665
+ if attr_val is not None :
666
+ Entry ._cached_attribute_data [entry .entry_type ()][
667
+ name
668
+ ] = attr_val
669
+
597
670
# Save the input entry object in DataStore
598
671
self ._save_entry_to_data_store (entry = entry )
599
672
0 commit comments