
    hlU                    x   S SK Jr  S SKJrJrJrJrJrJrJ	r	  S SK
r
S SKrS SKJr  S SKJr  S SKJr  S SKJrJr  S SKJr   " S	 S
5      r " S S\R                  5      rSS jr    SS jr " S S5      rS r " S S5      r      SS jr      SS jrSS jr SS S jjr!SS!S jjr" S"     S#S jjr#g)$    )annotations)IterableIteratorCallableHashableSequenceUnionOptionalN)abc)	DXFEntity)groupby)Vec3Vec2)EntityQueryParserc                  4    \ rS rSrSS jrS	S jrS rS rSrg)
_AttributeDescriptor   c                    Xl         g Nname)selfr   s     =/var/www/html/env/lib/python3.13/site-packages/ezdxf/query.py__init___AttributeDescriptor.__init__   s    	    Nc                8    UR                  U R                  5      $ r   )__getitem__r   )r   objobjtypes      r   __get___AttributeDescriptor.__get__   s    tyy))r   c                <    UR                  U R                  U5        g r   )__setitem__r   )r   r   values      r   __set___AttributeDescriptor.__set__   s    		5)r   c                :    UR                  U R                  5        g r   )__delitem__r   )r   r   s     r   
__delete___AttributeDescriptor.__delete__"   s    		"r   r   )r   strr   )	__name__
__module____qualname____firstlineno__r   r!   r&   r*   __static_attributes__ r   r   r   r      s    **#r   r   c                     \ rS rSrSr\" S5      r\" S5      r\" S5      r\" S5      r	\" S5      r
\" S5      r\" S	5      r\" S
5      r S/   S0S jjrS1S jrS2S jrS rS rS rS3S jr    S4S jrS rS rS rS rS rS rS rS rS rS rS r S r!S5S3S  jjr"S6S! jr#S6S" jr$\%S# 5       r&\%S$ 5       r' S7     S8S% jjr(S7S9S& jjr)S7S9S' jjr*  S:     S;S( jjr+S<S) jr,S=S* jr-S=S+ jr.S=S, jr/S=S- jr0S.r1g)>EntityQuery&   aC	  EntityQuery is a result container, which is filled with dxf entities
matching the query string. It is possible to add entities to the container
(extend), remove entities from the container and to filter the container.

Query String
============

QueryString := EntityQuery ("[" AttribQuery "]")*

The query string is the combination of two queries, first the required
entity query and second the optional attribute query, enclosed in square
brackets.

Entity Query
------------

The entity query is a whitespace separated list of DXF entity names or the
special name ``*``. Where ``*`` means all DXF entities, exclude some entity
types by appending their names with a preceding ``!`` (e.g. all entities
except LINE = ``* !LINE``). All DXF names have to be uppercase.

Attribute Query
---------------

The attribute query is used to select DXF entities by its DXF attributes.
The attribute query is an addition to the entity query and matches only if
the entity already match the entity query.
The attribute query is a boolean expression, supported operators are:

  - not: !term is true, if term is false
  - and: term & term is true, if both terms are true
  - or: term | term is true, if one term is true
  - and arbitrary nested round brackets

Attribute selection is a term: "name comparator value", where name is a DXF
entity attribute in lowercase, value is a integer, float or double quoted
string, valid comparators are:

  - "==" equal "value"
  - "!=" not equal "value"
  - "<" lower than "value"
  - "<=" lower or equal than "value"
  - ">" greater than "value"
  - ">=" greater or equal than "value"
  - "?" match regular expression "value"
  - "!?" does not match regular expression "value"

Query Result
------------

The EntityQuery() class based on the abstract Sequence() class, contains all
DXF entities of the source collection, which matches one name of the entity
query AND the whole attribute query. If a DXF entity does not have or
support a required attribute, the corresponding attribute search term is
false.

Examples:

    - 'LINE[text ? ".*"]' is always empty, because the LINE entity has no
      text attribute.
    - 'LINE CIRCLE[layer=="construction"]' => all LINE and CIRCLE entities
      on layer "construction"
    - '*[!(layer=="construction" & color<7)]' => all entities except those
      on layer == "construction" and color < 7

layercolorlinetype
lineweightltscale	invisible
true_colortransparencyNc                    SU l         SU l        U   Uc  / U l        gUS:X  a  [        U5      U l        g[	        U5      nU Vs/ s H  oC" U5      (       d  M  UPM     snU l        gs  snf )z
Setup container with entities matching the initial query.

Args:
    entities: sequence of wrapped DXF entities (at least GraphicEntity class)
    query: query string, see class documentation

 TN*)selected_dxf_attributeignore_caseentitieslistentity_matcher)r   rC   querymatchentitys        r   r   EntityQuery.__init__s   s_     ,.#DMc\ NDM"5)E2:L(eFmV(LDMLs   A%A%c                ,    [        U R                  5      $ )zReturns count of DXF entities.lenrC   r   s    r   __len__EntityQuery.__len__   s    4==!!r   c                ,    [        U R                  5      $ )z&Returns iterable of DXFEntity objects.)iterrC   rM   s    r   __iter__EntityQuery.__iter__   s    DMM""r   c                    [        U[        5      (       a  U R                  U5      $ U R                  R	                  U5      $ )zReturns DXFEntity at index `item`, supports negative indices and
slicing. Returns all entities which support a specific DXF attribute,
if `item` is a DXF attribute name as string.
)
isinstancer,   &_get_entities_with_supported_attributerC   r   )r   items     r   r   EntityQuery.__getitem__   s7    
 dC  >>tDD}}((..r   c                f    [        U[        5      (       d  [        S5      eU R                  X5        g)zOSet the DXF attribute `key` for all supported DXF entities to `value`.
        +key has to be a string (DXF attribute name)N)rU   r,   	TypeError_set_dxf_attribute_for_all)r   keyr%   s      r   r$   EntityQuery.__setitem__   s+     #s##IJJ''3r   c                f    [        U[        5      (       d  [        S5      eU R                  U5        g)z@Discard the DXF attribute `key` from all supported DXF entities.rZ   N)rU   r,   r[   _discard_dxf_attribute_for_all)r   r]   s     r   r)   EntityQuery.__delitem__   s)    #s##IJJ++C0r   c                x    U R                    Vs/ s H  oR                  (       d  M  UPM     snU l         U $ s  snf )zRemove destroyed entities.)rC   is_alive)r   es     r   purgeEntityQuery.purge   s+    $(MM@MqZZM@ As   77c                `   ^ U R                  U4S jU R                   5       5      nTUl        U$ )Nc              3  j   >#    U  H(  oR                   R                  T5      (       d  M$  Uv   M*     g 7fr   )dxfis_supported).0rd   	attributes     r   	<genexpr>EEntityQuery._get_entities_with_supported_attribute.<locals>.<genexpr>   s%      
$!(:(:9(EAA}s   #3	3)	__class__rC   rA   )r   rl   rF   s    ` r   rV   2EntityQuery._get_entities_with_supported_attribute   s3      
}}
 
 (1$r   c                    U R                    H  n UR                  R                  X5        M!     g ! [         a     M1  f = fr   )rC   ri   setAttributeError)r   r]   r%   rd   s       r   r\   &EntityQuery._set_dxf_attribute_for_all   s9    A		#%  " s   1
??c                `    U R                    H  nUR                  R                  U5        M      g r   )rC   ri   discard)r   r]   rd   s      r   r`   *EntityQuery._discard_dxf_attribute_for_all   s     AEEMM# r   c                z    U R                   (       d  [        S5      eU R                  U[        R                  5      $ )zkEqual selector (self == other).
Returns all entities where the selected DXF attribute is equal to
`other`.
no DXF attribute selected)rA   r[   _select_by_operatoroperatoreqr   others     r   __eq__EntityQuery.__eq__   s0    
 **788''x{{;;r   c                z    U R                   (       d  [        S5      eU R                  U[        R                  5      $ )zsNot equal selector (self != other). Returns all entities where the
selected DXF attribute is not equal to `other`.
ry   )rA   r[   rz   r{   ner}   s     r   __ne__EntityQuery.__ne__   s0     **788''x{{;;r   c                x    U R                   (       d  [        S5      eU R                  U[        R                  SS9$ )zLess than selector (self < other). Returns all entities where the
selected DXF attribute is less than `other`.

Raises:
     TypeError: for vector based attributes like `center` or `insert`
ry   Fvectors)rA   r[   rz   r{   ltr}   s     r   __lt__EntityQuery.__lt__   5     **788''x{{E'JJr   c                x    U R                   (       d  [        S5      eU R                  U[        R                  SS9$ )zGreater than selector (self > other). Returns all entities where the
selected DXF attribute is greater than `other`.

Raises:
     TypeError: for vector based attributes like `center` or `insert`
ry   Fr   )rA   r[   rz   r{   gtr}   s     r   __gt__EntityQuery.__gt__   r   r   c                x    U R                   (       d  [        S5      eU R                  U[        R                  SS9$ )zLess equal selector (self <= other). Returns all entities where the
selected DXF attribute is less or equal `other`.

Raises:
     TypeError: for vector based attributes like `center` or `insert`
ry   Fr   )rA   r[   rz   r{   ler}   s     r   __le__EntityQuery.__le__   r   r   c                x    U R                   (       d  [        S5      eU R                  U[        R                  SS9$ )zGreater equal selector (self >= other). Returns all entities where
the selected DXF attribute is greater or equal `other`.

Raises:
     TypeError: for vector based attributes like `center` or `insert`
ry   Fr   )rA   r[   rz   r{   ger}   s     r   __ge__EntityQuery.__ge__   r   r   c                Z    [        U[        5      (       a  U R                  U5      $ [        $ )z"Union operator, see :meth:`union`.)rU   r4   unionNotImplementedr}   s     r   __or__EntityQuery.__or__  s$    e[))::e$$r   c                Z    [        U[        5      (       a  U R                  U5      $ [        $ )z0Intersection operator, see :meth:`intersection`.)rU   r4   intersectionr   r}   s     r   __and__EntityQuery.__and__  s&    e[))$$U++r   c                Z    [        U[        5      (       a  U R                  U5      $ [        $ )z,Difference operator, see :meth:`difference`.)rU   r4   
differencer   r}   s     r   __sub__EntityQuery.__sub__  s$    e[))??5))r   c                Z    [        U[        5      (       a  U R                  U5      $ [        $ )z@Symmetric difference operator, see :meth:`symmetric_difference`.)rU   r4   symmetric_differencer   r}   s     r   __xor__EntityQuery.__xor__  s&    e[)),,U33r   c                   U R                   nU R                  (       a%  [        U[        5      (       a  UR	                  5       nU R                  5       nXEl         UR                  nU(       a  U R                   H  n UR                  R                  U5      nU(       d?  [        U[        [        45      (       a$  [        S[        UR                  5       SU 35      eU R                  (       a%  [        U[        5      (       a  UR	                  5       nU" X5      (       d  M  UR                  U5        M     U$ ! [         a     M  f = f)Nzunsupported operation 'z' for DXF attribute )rA   rB   rU   r,   lowerro   rC   ri   get_defaultrs   r   r   r[   r-   append)	r   r%   opr   rl   rF   rC   rH   entity_values	            r   rz   EntityQuery._select_by_operator  s   //	
5# 6 6KKME '0$>>--#)::#9#9)#DL :lT4L#I#I#1#bkk2B1C D%%.K1  ##
<(E(E#/#5#5#7Ll**OOF+ (  & s   <D99
EEc                2   ^  U 4S jnT R                  X5      $ )zReturns all entities where the selected DXF attribute matches the
regular expression `pattern`.

Raises:
     TypeError: for non-string based attributes

c                   > [        U [        5      (       a  UR                  U 5      S L$ [        STR                   35      e)Nz2cannot apply regular expression to DXF attribute: )rU   r,   rG   r[   rA   )r%   regexr   s     r   rG    EntityQuery.match.<locals>.match;  sE    %%%{{5)55D../1 r   )_regex_match)r   patternrG   s   `  r   rG   EntityQuery.match2  s    	   00r   c                    U R                   nSU l         U(       a  [        R                  OSnUR                  S5      (       d  US-  nU R	                  [        R
                  " XS9U5      nX0l         U$ )NFr   $flags)rB   re
IGNORECASEendswithrz   compile)r   r   funcrB   re_flagsresults         r   r   EntityQuery._regex_matchE  si    && $/2==Q $$sNG))JJw/
 'r   c                V    [        U R                  5      (       a  U R                  S   $ g)zFirst entity or ``None``.r   NrK   rM   s    r   firstEntityQuery.firstS  s%     t}}==##r   c                V    [        U R                  5      (       a  U R                  S   $ g)zLast entity or ``None``.NrK   rM   s    r   lastEntityQuery.last[  s%     t}}==$$r   c                d    U R                  U R                  X5      5      R                  U l        U $ )zUExtent the :class:`EntityQuery` container by entities matching an
additional query.

)r   ro   rC   )r   rC   rF   s      r   extendEntityQuery.extendc  s(     

4>>(#BCLLr   c                z    U R                  U R                  U R                  U5      5      R                  U l        U $ )zYRemove all entities from :class:`EntityQuery` container matching this
additional query.

)r   ro   rC   r   rF   s     r   removeEntityQuery.removeo  s5    
 NN4==%0

( 	 r   c                :    U R                  U R                  U5      $ )zReturns a new :class:`EntityQuery` container with all entities
matching this additional query.

Raises:
    pyparsing.ParseException: query string parsing error

)ro   rC   r   s     r   rF   EntityQuery.queryy  s     ~~dmmU33r   c                .    [        U R                  X5      $ )a  Returns a dict of entity lists, where entities are grouped by a DXF
attribute or a key function.

Args:
    dxfattrib: grouping DXF attribute as string like ``'layer'``
    key: key function, which accepts a DXFEntity as argument, returns
        grouping key of this entity or ``None`` for ignore this object.
        Reason for ignoring: a queried DXF attribute is not supported by
        this entity

)r   rC   )r   	dxfattribr]   s      r   r   EntityQuery.groupby  s      t}}i55r   c                J    U R                  [        XR                  5      5      $ )aH  Returns a new :class:`EntityQuery` with all entities from this
container for which the callable `func` returns ``True``.

Build your own operator to filter by attributes which are not DXF
attributes or to build complex queries::

    result = msp.query().filter(
        lambda e: hasattr(e, "rgb") and e.rbg == (0, 0, 0)
    )
)ro   filterrC   )r   r   s     r   r   EntityQuery.filter  s     ~~fT==9::r   c                v    U R                  [        U R                  5      [        UR                  5      -  5      $ )zsReturns a new :class:`EntityQuery` with entities from `self` and
`other`. All entities are unique - no duplicates.
ro   rr   rC   r}   s     r   r   EntityQuery.union  *     ~~c$--03u~~3FFGGr   c                v    U R                  [        U R                  5      [        UR                  5      -  5      $ )zOReturns a new :class:`EntityQuery` with entities common to `self`
and `other`.
r   r}   s     r   r   EntityQuery.intersection  r   r   c                v    U R                  [        U R                  5      [        UR                  5      -
  5      $ )zZReturns a new :class:`EntityQuery` with all entities from `self` that
are not in `other`.
r   r}   s     r   r   EntityQuery.difference  r   r   c                v    U R                  [        U R                  5      [        UR                  5      -  5      $ )z[Returns a new :class:`EntityQuery` with entities in either `self` or
`other` but not both.
r   r}   s     r   r    EntityQuery.symmetric_difference  r   r   )rC   rB   rA   Nr@   )rC   Optional[Iterable[DXFEntity]]rF   r,   )returnint)r   Iterator[DXFEntity])r   r4   )rl   r,   r   r4   )T)r   r,   r   r4   r@   )rC   Iterable[DXFEntity]rF   r,   r   r4   )rF   r,   r   r4   )r?   N)r   r,   r]   z)Optional[Callable[[DXFEntity], Hashable]]r   zdict[Hashable, list[DXFEntity]])r   Callable[[DXFEntity], bool]r   r4   )r~   r4   r   r4   )2r-   r.   r/   r0   __doc__r   r6   r7   r8   r9   r:   r;   r<   r=   r   rN   rR   r   r$   r)   re   rV   r\   r`   r   r   r   r   r   r   r   r   r   r   rz   rG   r   propertyr   r   r   r   rF   r   r   r   r   r   r   r1   r2   r   r   r4   r4   &   s   AF !)E )E#J/H%l3J"9-G$[1I%l3J'7L LOM5MEHM2"#/41
	<<	K	K	K	K21&     
%
 
 
	
4 9=66 76 
)	6$;HHHHr   r4   c                   ^^ [         R                  " U SS9n[        UR                  5      m[	        UR
                  UR                  5      mSUU4S jjnU$ )NT)parseAllc                2   > T" U 5      =(       a    T" U 5      $ r   r2   )rH   attrib_matcherentity_matcher_s    r   matcherentity_matcher.<locals>.matcher  s    v&A>&+AAr   rH   r   r   bool)r   parseStringbuild_entity_name_matcherr4   build_entity_attributes_matcherAttribQueryAttribQueryOptions)rF   
query_argsr   r   r   s      @@r   rE   rE     sS    "..utDJ/
0F0FGO4
 = =NB B Nr   c                H   ^ SU4S jjn[        SR                  U 5      S9mU$ )Nc                0   > T" U R                  5       5      $ r   )dxftype)rd   _matchs    r   rG   (build_entity_name_matcher.<locals>.match  s    aiik""r    )rF   )rd   r   r   r   )name_matcherjoin)namesrG   r   s     @r   r   r     s!    # 0FLr   c            	          \ rS rSr\R
                  \R                  \R                  \R                  \R                  \R                  S S S.r\" \R                  5       5      rS	S jrS
S jrSrg)Relationi  c                (    UR                  U 5      S L$ r   rG   rd   r   s     r   <lambda>Relation.<lambda>  s    ekk!nD8r   c                (    UR                  U 5      S L $ r   r  r	  s     r   r
  r    s    u{{1~5r   )z==z!=<z<=>z>=?z!?c                   Uu  p4nX0l         [        R                  U   U l        U(       a  [        OS U l        U(       a  [        R                  OSnSU;   a  [        R                  " US-   US9U l	        g U R                  U5      U l	        g )Nc                    U $ r   r2   xs    r   r
  #Relation.__init__.<locals>.<lambda>  s    1r   r   r  r   r   )

dxf_attribr  CMP_OPERATORScompareto_lowerconvert_caser   r   r   r%   )r   relationrB   r   r   r%   r   s          r   r   Relation.__init__  so    "%--b1(3H$/2==Q"98DJ **51DJr   c                     U R                  UR                  R                  U R                  5      5      nU R	                  X R
                  5      $ ! [         a     g[         a     gf = f)NF)r  ri   r   r  r  r%   rs   
ValueError)r   rH   r%   s      r   evaluateRelation.evaluate  sZ    	%%fjj&<&<T__&MNE<<zz22 	 		s   AA 
A)	A)(A))r  r  r  r%   N)r  r   rB   r   r   )r-   r.   r/   r0   r{   r|   r   r   r   r   r   r  	frozensetkeysVALID_CMP_OPERATORSr   r  r1   r2   r   r   r  r    sY    kkkk[[kk[[kk85	M $M$6$6$892r   r  c                H    [        U S5      (       a  U R                  5       $ U $ )Nr   )hasattrr   )r%   s    r   r  r    s    #E7335;;=>>r   c                  `    \ rS rSr\R
                  \R                  S.rSS jrS r	S	S jr
Srg)
BoolExpressioni  )&|c                    Xl         g r   tokens)r   r+  s     r   r   BoolExpression.__init__  s    r   c                ,    [        U R                  5      $ r   )rQ   r+  rM   s    r   rR   BoolExpression.__iter__  s    DKK  r   c                D   [        U R                  [        5      (       a  U R                  R                  U5      $ / n/ nU R                   HG  n[	        US5      (       a"  UR                  UR                  U5      5        M6  UR                  U5        MI     UR                  5         U Hf  nUS:X  a  UR                  5       (       + nO6[        R                  U   " UR                  5       UR                  5       5      nUR                  U5        Mh     UR                  5       $ )Nr  !)
rU   r+  r  r  r$  r   reversepopr&  	OPERATORS)r   rH   values	operatorstokenr   r%   s          r   r  BoolExpression.evaluate  s    KK
 
 ;;''//	[[Euj))ennV45  '	 !
 	BSy"JJL(&004VZZ\6::<PMM%   zz|r   r*  N)r+  r   r   )r-   r.   r/   r0   r{   and_or_r3  r   rR   r  r1   r2   r   r   r&  r&    s&    ]]\\I
!r   r&  c           	         SS jn[        U [        5      (       a  U $ [        U 5      n U" U 5      (       a  [        X5      $ [	        U  Vs/ s H  n[        X15      PM     sn5      $ s  snf )Nc                X    [        U 5      S:H  =(       a    U S   [        R                  ;   $ )N      )rL   r  r"  r*  s    r   is_relation$_compile_tokens.<locals>.is_relation!  s%    6{aMF1I1M1M$MMr   )r+  r   r   r   )rU   r,   tupler  r&  _compile_tokens)r+  rB   r>  r6  s       r   rA  rA    sb    N &#6]F6,,>DEfU_U0fE
 	
Es   	A%c                p   ^ [        U 5      (       d  S $ SU:H  n[        [        X5      5      mSU4S jjnU$ )Nc                    g)NTr2   r  s    r   r
  1build_entity_attributes_matcher.<locals>.<lambda>4  s    r   ic                &   > TR                  U 5      $ r   )r  )rH   exprs    r   match_bool_expr8build_entity_attributes_matcher.<locals>.match_bool_expr8  s    }}V$$r   r   )rL   r&  rA  )r+  optionsrB   rH  rG  s       @r   r   r   0  s9     v;;.K/&>?D% r   c              #  j   #    [        5       nU  H  nX!;  d  M
  UR                  U5        Uv   M!     g7f)zCYield all unique entities, order of all entities will be preserved.N)rr   add)rC   donerH   s      r   unique_entitiesrN  >  s-     5DHHVL s   33c                2   ^ [        U5      mU4S jU  5       $ )a  Filters `names` by `query` string. The `query` string of entity names
divided by spaces. The special name "*" matches any given name, a
preceding "!" means exclude this name. Excluding names is only useful if
the match any name is also given (e.g. "LINE !CIRCLE" is equal to just
"LINE", where "* !CIRCLE" matches everything except CIRCLE").

Args:
    names: iterable of names to test
    query: query string of entity names separated by spaces

Returns: yield matching names

c              3  F   >#    U  H  nT" U5      (       d  M  Uv   M     g 7fr   r2   )rk   r   rG   s     r   rm   name_query.<locals>.<genexpr>V  s     2UTeDkDDUs   !	!)r  )r  rF   rG   s     @r   
name_queryrR  G  s     E2U22r   c                :  ^^^ SUUU4S jjn[        U R                  5       R                  5       5      nSm[        5       m[        5       mU HJ  nUS:X  a  SmM  UR                  S5      (       a  TR	                  USS  5        M9  TR	                  U5        ML     U$ )Nc                &   > T(       a  U T;  $ U T;   $ r   r2   )rd   excludeincludetake_alls    r   rG   name_matcher.<locals>.matchZ  s    G##<r   Fr@   Tr0  r=  )rd   r,   r   r   )rr   uppersplit
startswithrL  )rF   rG   match_stringsr   rU  rV  rW  s       @@@r   r  r  Y  s        ++-.MHeGeG3;H__S!!KKQR!KK  Lr   c                    [        X5      $ )zStart a new query based on sequence `entities`. The `entities` argument
has to be an iterable of :class:`~ezdxf.entities.DXFEntity` or inherited
objects and returns an :class:`EntityQuery` object.

)r4   )rC   rF   s     r   newr^  o  s     x''r   )rF   r,   r   r   )r  zSequence[str]r   r   )r+  zUnion[str, Sequence]rB   r   r   z$Union[str, Relation, BoolExpression])r+  r   rJ  r,   r   r   )rC   r   r   r   r   )r  zIterable[str]rF   r,   r   zIterator[str])rF   r,   r   zCallable[[str], bool]r   )rC   r   rF   r,   r   r4   )$
__future__r   typingr   r   r   r   r   r	   r
   r   r{   collectionsr   ezdxf.entities.dxfentityr   ezdxf.groupbyr   
ezdxf.mathr   r   ezdxf.queryparserr   r   r4   rE   r   r  r  r&  rA  r   rN  rR  r  r^  r2   r   r   <module>rf     s    #   
   . ! ! /# #RH#,, RHj
 " "J?   F
 
/3
)
$" 3$. BE(+(;>((r   