
    ph                     V    S r SSKrSSKJr  SSKrSSKJr  S r " S S5      r	S	 r
S
 rg)z&
Utilities for comparing phi-objects.
    N)Iterable   )utilsc                 F   ^  [         R                  " T 5      U 4S j5       nU$ )a  Method decorator to return ``NotImplemented`` if the args of the wrapped
method are of different types.

When wrapping a rich model comparison method this will delegate (reflect)
the comparison to the right-hand-side object, or fallback by passing it up
the inheritance tree.
c                 N   > [        U5      [        U 5      La  [        $ T" X5      $ N)typeNotImplemented)selfotherfuncs     J/home/james-whalen/.local/lib/python3.13/site-packages/pyphi/models/cmp.pywrappersametype.<locals>.wrapper   s$    ;d4j(!!D      )	functoolswraps)r   r   s   ` r   sametyper      s'     __T! ! Nr   c                       \ rS rSrSr/ rS r\S 5       r\S 5       r	\S 5       r
\S 5       r\S 5       r\S	 5       rS
rg)	Orderable#   a  Base mixin for implementing rich object comparisons on phi-objects.

Both ``__eq__`` and `order_by`` need to be implemented on the subclass.
The ``order_by`` method returns a list of attributes which are compared
to implement the ordering.

Subclasses can optionally set a value for `unorderable_unless_eq`. This
attribute controls whether objects are orderable: if all attributes listed
in `unorderable_unless_eq` are not equal then the objects are not orderable
with respect to one another and a TypeError is raised. For example: it
doesn't make sense to compare ``Concepts`` unless they are from the same
``Subsystem`` or compare ``MechanismIrreducibilityAnalyses`` with different
directions.
c                     [         e)zReturn a list of values to compare for ordering.

The first value in the list has the greatest priority; if the first
objects are equal the second object is compared, etc.
NotImplementedError)r   s    r   order_byOrderable.order_by5   s
     "!r   c                     [        XU R                  5      (       d$  [        SR                  U R                  5      5      eU R	                  5       UR	                  5       :  $ )Nz2Unorderable: the following attrs must be equal: {})
general_equnorderable_unless_eq	TypeErrorformatr   r   r   s     r   __lt__Orderable.__lt__=   sS    $t'A'ABBDKK..01 1 }}!111r   c                      X:  =(       d    X:H  $ r    r"   s     r   __le__Orderable.__le__E   s    |,t},r   c                 
    X:  $ r   r&   r"   s     r   __gt__Orderable.__gt__I   s
    |r   c                      X:  =(       d    X:H  $ r   r&   r"   s     r   __ge__Orderable.__ge__M   s    |,t},r   c                     [         er   r   r"   s     r   __eq__Orderable.__eq__Q   s    !!r   c                     X:X  + $ r   r&   r"   s     r   __ne__Orderable.__ne__U   s      r   r&   N)__name__
__module____qualname____firstlineno____doc__r   r   r   r#   r'   r*   r-   r0   r3   __static_attributes__r&   r   r   r   r   #   s     " 2 2 - -   - - " " ! !r   r   c                    [        U [        R                  5      (       d  [        U[        R                  5      (       a  [        R                  " X5      $ [        U [        5      (       as  [        U[        5      (       a^  [        U [
        5      (       dI  [        U[
        5      (       d4  [        U 5      [        U5      :w  a  g[        S [        X5       5       5      $ X:H  $ )zoReturn whether two objects are equal via recursion, using
:func:`numpy.array_equal` for comparing numpy arays.
Fc              3   <   #    U  H  u  p[        X5      v   M     g 7fr   )numpy_aware_eq).0xys      r   	<genexpr>!numpy_aware_eq.<locals>.<genexpr>h   s     >IDA>!''Is   )	
isinstancenpndarrayarray_equalr   strlenallzip)abs     r   r=   r=   ^   s     !RZZ  Jq"**$=$=~~a##	Ax	 	 Z8%<%<1c"":a+=+=q6SV>CI>>>6Mr   c                 2    U H  n[        X5      [        X5      pTUS;   a  [        R                  " XE5      (       d    gM=  US;   a+  Ub  Uc	  XE:w  a    gMR  [        U5      [        U5      :X  d    gMn  [	        XE5      (       a  M    g   g! [
         a     gf = f)a(  Return whether two objects are equal up to the given attributes.

If an attribute is called ``'phi'``, it is compared up to |PRECISION|.
If an attribute is called ``'mechanism'`` or ``'purview'``, it is
compared using set equality.  All other attributes are compared with
:func:`numpy_aware_eq`.
)phialphaF)	mechanismpurviewT)getattrr   eqsetr=   AttributeError)rK   rL   
attributesattr_a_bs         r   r   r   l   s    DQ%wq'7''xx''  (11:x$  RCG+  , &b--    s.   <B	 B	 B	 0B	 B	 B	 	
BB)r9   r   collectionsr   numpyrD    r   r   r   r=   r   r&   r   r   <module>r]      s2   
     
 4! 4!vr   