3535from .utils import is_iterable , make_list
3636from ..class_diagrams .wrapped_field import WrappedField
3737
38- if TYPE_CHECKING :
39- from .property_descriptor import MonitoredSet
40-
4138cls_args = {}
39+ """
40+ Cache of class arguments.
41+ """
4242
4343
4444def symbolic_function (
@@ -175,10 +175,26 @@ def holds_direct(
175175
176176 @property
177177 def domain_value (self ):
178+ """
179+ Property that retrieves the domain value for the current instance.
180+
181+ This property should be implemented in a subclass where it returns
182+ the specific domain value. Attempting to access it directly from
183+ this base implementation will raise a NotImplementedError.
184+
185+ :raise: NotImplementedError: If the property is accessed and not
186+ implemented in a subclass.
187+ """
178188 raise NotImplementedError
179189
180190 @property
181191 def range_value (self ):
192+ """
193+ Gets the range value. This is an abstract property and must be implemented
194+ by subclasses to return a value indicating the range.
195+
196+ :raises NotImplementedError: If not implemented in a subclass.
197+ """
182198 raise NotImplementedError
183199
184200 @classmethod
@@ -209,41 +225,6 @@ def _neighbors(cls, value: Symbol, outgoing: bool = True) -> Iterable[Symbol]:
209225 )
210226 )
211227
212- @classmethod
213- def _get_super_property_descriptors (cls , value : Symbol ) -> Iterable [MonitoredSet ]:
214- """
215- Find neighboring symbols connected by super edges.
216-
217- This method identifies neighboring symbols that are connected
218- through edge with predicate types that are superclasses of the current predicate.
219-
220- :param value: (Symbol): The symbol for which neighboring symbols are
221- evaluated through super predicate type edges.
222-
223- :return: A list containing neighboring symbols connected by super type edges.
224- """
225- wrapped_cls = SymbolGraph ().type_graph .get_wrapped_class (type (value ))
226- if not wrapped_cls :
227- return
228- yield from (
229- getattr (value , property_field .public_name )
230- for property_field in SymbolGraph ().type_graph .get_fields_of_superclass_property_descriptors (
231- wrapped_cls , cls
232- )
233- )
234- role_taker_property_fields = (
235- SymbolGraph ().type_graph .get_role_taker_superclass_properties (
236- wrapped_cls , cls
237- )
238- )
239- if not role_taker_property_fields :
240- return
241- for role_taker_field in role_taker_property_fields .fields :
242- yield getattr (
243- getattr (value , role_taker_property_fields .role_taker .public_name ),
244- role_taker_field .public_name ,
245- )
246-
247228 def __call__ (
248229 self ,
249230 domain_value : Optional [Symbol ] = None ,
@@ -258,33 +239,6 @@ def __call__(
258239 range_value = range_value or self .range_value
259240 return self .holds_direct (domain_value , range_value )
260241
261- @classmethod
262- def get_inverse (cls , obj ) -> MonitoredSet :
263- wrapped_cls = SymbolGraph ().type_graph .get_wrapped_class (type (obj ))
264- inverse_field = (
265- SymbolGraph ().type_graph .get_the_field_of_property_descriptor_type (
266- wrapped_cls , cls .inverse_of
267- )
268- )
269- if not inverse_field :
270- # try to get it from role taker if there is one.
271- role_taker = SymbolGraph ().get_role_takers_of_instance (obj )
272- role_taker_wrapped_cls = SymbolGraph ().type_graph .get_wrapped_class (
273- type (role_taker )
274- )
275- if role_taker :
276- inverse_field = (
277- SymbolGraph ().type_graph .get_the_field_of_property_descriptor_type (
278- role_taker_wrapped_cls , cls .inverse_of
279- )
280- )
281- return getattr (role_taker , inverse_field .public_name )
282- if not inverse_field :
283- raise ValueError (
284- f"cannot find a field for the inverse { cls .inverse_of } defined for { wrapped_cls } "
285- )
286- return getattr (obj , inverse_field .public_name )
287-
288242 def add_relation (
289243 cls ,
290244 domain_value : Symbol ,
@@ -298,12 +252,6 @@ def add_relation(
298252 range_value = make_list (range_value )
299253 for rv in range_value :
300254 SymbolGraph ().add_edge (cls .get_relation (domain_value , rv , inferred ))
301- for property_value in cls ._get_super_property_descriptors (domain_value ):
302- property_value .add (rv , inferred = True )
303- if cls .inverse_of :
304- inverse = cls .get_inverse (rv )
305- if domain_value not in inverse :
306- cls .get_inverse (rv ).add (domain_value , inferred = True )
307255 if cls .transitive :
308256 for nxt in cls ._neighbors (rv ):
309257 cls .add_relation (domain_value , nxt , inferred = True )
@@ -317,6 +265,18 @@ def get_relation(
317265 range_value : Symbol ,
318266 inferred : bool = False ,
319267 ) -> PredicateRelation :
268+ """
269+ Gets or creates a relation between two symbols, representing the domain and range
270+ values. The function ensures that the symbols are wrapped in instances, adding
271+ them to the symbol graph if they do not already exist. It then creates and returns
272+ a `PredicateRelation` object linking the domain and range symbols.
273+
274+ :param domain_value: The symbol representing the domain value.
275+ :param range_value: The symbol representing the range value.
276+ :param inferred: A boolean flag indicating whether the relationship is inferred. Defaults to False.
277+
278+ :return: A `PredicateRelation` instance that links the given domain and range values.
279+ """
320280 wrapped_domain_instance = SymbolGraph ().get_wrapped_instance (domain_value )
321281 if not wrapped_domain_instance :
322282 wrapped_domain_instance = WrappedInstance (domain_value )
@@ -335,8 +295,22 @@ def get_relation(
335295
336296@dataclass (eq = False )
337297class HasType (BinaryPredicate ):
298+ """
299+ Represents a predicate to check if a given variable is an instance of a specified type.
300+
301+ This class is used to evaluate whether the domain value belongs to a given type by leveraging
302+ Python's built-in `isinstance` functionality. It provides methods to retrieve the domain and
303+ range values and perform direct checks.
304+ """
305+
338306 variable : Any
307+ """
308+ The variable whose type is being checked.
309+ """
339310 types_ : Type
311+ """
312+ The type or tuple of types against which the `variable` is validated.
313+ """
340314
341315 @classmethod
342316 def holds_direct (cls , domain_value : Any , range_value : Type ) -> bool :
@@ -353,12 +327,36 @@ def range_value(self):
353327
354328@dataclass (eq = False )
355329class HasTypes (HasType ):
330+ """
331+ Represents a specialized data structure holding multiple types.
332+
333+ This class is a data container designed to store and manage a tuple of
334+ types. It inherits from the `HasType` class and extends its functionality
335+ to handle multiple types efficiently. The primary goal of this class is to
336+ allow structured representation and access to a collection of type
337+ information with equality comparison explicitly disabled.
338+ """
339+
356340 types_ : Tuple [Type , ...]
341+ """
342+ A tuple containing Type objects that are associated with this instance.
343+ """
357344
358345
359346def bind_first_argument_of_predicate_if_in_query_context (
360347 node : SymbolicExpression , predicate_type : Optional [PredicateType ], * args
361348):
349+ """
350+ Binds the first argument of a predicate to a result quantifier's selected variable if
351+ in a query context and predicate type is specified.
352+
353+ :param node: The symbolic expression node to evaluate or use.
354+ :param predicate_type: The type of predicate, can be None.
355+ :param args: Additional arguments to bind with the predicate.
356+
357+ :return: A list of arguments where the first argument of the predicate is potentially
358+ replaced by the result quantifier's selected variable.
359+ """
362360 if predicate_type and node and in_symbolic_mode (EQLMode .Query ):
363361 if not isinstance (node , ResultQuantifier ):
364362 result_quantifier = node ._parent_ ._parent_
@@ -374,6 +372,18 @@ def update_query_child_expression_if_in_query_context(
374372 predicate_type : Optional [PredicateType ],
375373 var : SymbolicExpression ,
376374):
375+ """
376+ Updates the child expression of a given symbolic expression node in the context of a
377+ query mode. This function modifies the structure of the symbolic expression to inject
378+ a logical condition involving the provided variable, based on the specified predicate
379+ type and the current query mode.
380+
381+ :param node: The symbolic expression node whose child expression may be updated.
382+ :param predicate_type: The type of logical predicate guiding the behavior of this update.
383+ :param var: The symbolic expression to be integrated into the node's child expression if applicable.
384+ :raise: AssertionError: If any condition for in_symbolic_mode or other logical assertions fail during
385+ execution.
386+ """
377387 if predicate_type and node and in_symbolic_mode (EQLMode .Query ):
378388 if node ._child_ ._child_ :
379389 node ._child_ ._child_ = AND (node ._child_ ._child_ , var )
@@ -414,11 +424,18 @@ def extract_selected_variable_and_expression(
414424 ** kwargs ,
415425):
416426 """
417- :param symbolic_cls: The constructed class.
418- :param domain: The domain source for the values of the variable by.
419- :param predicate_type: The predicate type.
420- :param kwargs: The keyword arguments to the class constructor.
421- :return: The selected variable and expression.
427+ Extracts a variable and constructs its expression tree for the given symbolic class.
428+
429+ This function generates a variable of the specified `symbolic_cls` and uses the
430+ provided domain, predicate type, and additional arguments to create its expression
431+ tree. The domain can optionally be filtered when iterating through its elements
432+ if specified or retrieved from the cache keys associated with the symbolic class.
433+
434+ :param symbolic_cls: The symbolic class type to be used for variable creation.
435+ :param domain: Optional domain to provide constraints for the variable.
436+ :param predicate_type: Optional predicate type associated with the variable.
437+ :param kwargs: Additional properties to define and construct the variable.
438+ :return: A tuple containing the generated variable and its corresponding expression tree.
422439 """
423440 cache_keys = get_cache_keys_for_class_ (Variable ._cache_ , symbolic_cls )
424441 if not domain and cache_keys :
@@ -451,7 +468,14 @@ def extract_selected_variable_and_expression(
451468
452469def update_cache (instance : Symbol ):
453470 """
454- :param instance: The instance to update the cache with.
471+ Updates the cache with the given instance of a symbolic type. The function ensures
472+ proper handling of symbolic class cache, updates associated arguments, and adds
473+ relevant instances to the variable cache and symbol graph. This function operates
474+ based on the type and characteristics of the given instance.
475+
476+ :param instance: The symbolic instance to be cached, which can include types such as
477+ Symbol or BinaryPredicate, among others.
478+ :return: Returns the updated instance that has been added to the cache.
455479 """
456480 symbolic_cls = type (instance )
457481 index = index_class_cache (symbolic_cls )
@@ -476,6 +500,18 @@ def update_cache(instance: Symbol):
476500
477501
478502def update_cls_args (symbolic_cls : Type ):
503+ """
504+ Updates the global `cls_args` dictionary with the constructor arguments
505+ of the given symbolic class, if it is not already present. The keys in
506+ `cls_args` are symbolic class types, and the values are lists of
507+ constructor parameter names for those classes.
508+
509+ This function inspects the signature of the `__init__` method of the
510+ given symbolic class and stores the parameter names if the class
511+ is not already in the global `cls_args`.
512+
513+ :param symbolic_cls: A symbolic class type to be inspected.
514+ """
479515 global cls_args
480516 if symbolic_cls not in cls_args :
481517 cls_args [symbolic_cls ] = list (
@@ -486,5 +522,7 @@ def update_cls_args(symbolic_cls: Type):
486522def index_class_cache (symbolic_cls : Type ) -> bool :
487523 """
488524 Determine whether the class cache should be indexed.
525+
526+ :param symbolic_cls: The symbolic class type.
489527 """
490528 return issubclass (symbolic_cls , BinaryPredicate ) and symbolic_cls .is_expensive
0 commit comments