
    'jK                    |   d dl mZ d dlmZmZmZmZmZmZ d dl	Z	d dl
mZ d dlmZmZ d dlmZ d dlmZmZ d dlmZmZmZmZmZ d d	lmZmZmZmZmZm Z m!Z! d d
l"m#Z#m$Z$m%Z% d dl&m'Z' er d dl(m)Z) d dlm*Z*m+Z+ d dl,m-Z- d dl.m/Z/ d dl0m1Z1  e	j2        d          Z3ddZ4ddZ5ddZ6 e            Z7 G d d          Z8dS )    )annotations)TYPE_CHECKINGIterableIteratorUnioncastOptionalN)ParseException)Auditor
AuditError)BlockLayout)const	validator)DXFBlockInUseErrorDXFKeyErrorDXFStructureErrorDXFTableEntryErrorDXFTypeError)AttribBlockBlockRecordEndBlkentity_linkerfactoryis_graphic_entity)UVecNULLVECVec3)ARROWS)Drawing)	DXFEntityDXFTagStorage)EntityDB)AbstractTagWriter)Tableezdxfnamestrreturnboolc                    |                                  } t          |           rdS t          j        |           rdS |                     d          r(t          j        t          j        |                     rdS dS )NT_F)upperis_anonymous_blockr   is_ezdxf_arrow
startswithis_acad_arrow
arrow_namer'   s    O/DATA/AppData/hermes/venv/lib/python3.11/site-packages/ezdxf/sections/blocks.pyis_special_blockr5   .   s|    ::<<D $ t T"" ts  1$ 7 788 	45    c                T    t          |           dk    o| d         dk    o	| d         dv S )N   r   *UEXDAT)lenr3   s    r4   r.   r.   @   s/     t99q=CT!W^CQ80CCr6   blockr   c                6   | j                             dd          }|r|S | j                             dd          }|sdS | j        }|Q|j        J|j                            |          }t	          |t
                    r|j                             dd          S dS )Nr'    owner)dxfgetdocentitydb
isinstancer   )r<   r'   r?   rB   block_records        r4   recover_block_namerF   J   s    9==$$D IMM'2&&E r
)C 3<3|''..lK00 	4#''3332r6   c                     e Zd ZdZ	 	 d:d;dZd Zed<d            Zed=d            Z	ed>d            Z
d?dZd Zd@dZdAdZdBdZdCd!ZdDd"ZdEd#ZdFd%ZdGdDd&ZdHd(ZedfdId+Zd,efdJd.ZdKd/ZdLd2ZdMdNd5ZdOd6ZdPd9ZdS )QBlocksSectionzm
    Manages BLOCK definitions in a dict(), block names are case insensitive
    e.g. 'Test' == 'TEST'.

    NrB   Optional[Drawing]entitiesOptional[list[DXFEntity]]c                x    || _         ||                     |           |                                  d| _        d S )Nr   )rB   load#_reconstruct_orphaned_block_records_anonymous_block_counter)selfrB   rJ   s      r4   __init__zBlocksSection.__init__e   sC    
 IIh00222()%%%r6   c                *    t          | j                  S N)r;   block_recordsrP   s    r4   __len__zBlocksSection.__len__p   s    4%&&&r6   entityUnion[str, BlockLayout]r)   r(   c                b    t          | t                    s| j        } |                                 S rS   )rD   r(   r'   lower)rW   s    r4   keyzBlocksSection.keys   s)    &#&& 	![F||~~r6   r%   c                    | j         j        S rS   )rB   rT   rU   s    r4   rT   zBlocksSection.block_recordsy   s    x%%r6   r#   c                    | j         j        S rS   )rB   rC   rU   s    r4   rC   zBlocksSection.entitydb}   s    x  r6   list[DXFEntity]Nonec                R   dfd	}dfd}| j         t          dd                   }|                                dk    s|j        d         dk    rt	          d          d= g }t
          } |            D ]}t          |t                    r:|t
          urt          	                    d           |}|
                                 Rt          |t                    r.|t
          u rt          	                    d           n|j                            dd          }|j                            dd          }	|s>t          |          }|r-t                              d| d|	 d           ||j        _        |rW ||||          }
t          |
t"                    r|                     |
           n=t          	                    d|	 d           nt          	                    d|	 d           t
          }|
                                 |                    |           dS ) z
        Load DXF entities into BlockLayouts. `entities` is a list of
        entity tags, separated by BLOCK and ENDBLK entities.

        r<   r   endblkr   block_entitiesr^   r)   BlockRecord | Nonec           	        	 t          d                    | j        j                            }nf# t          $ r4 t          d                    | j        j        ddi                    }Y n)t          $ r t          d| j        j                   w xY w|	                    | |           |D ]}|
                    |           |S )Nr   scaler   )
dxfattribsz"Invalid or missing name of BLOCK #)r   rA   r@   r'   r   newr   r   handle	set_block
add_entity)r<   ra   rb   rE   rW   rT   s        r4   load_block_recordz-BlocksSection.load.<locals>.load_block_record   s    
#M=3D3DUY^3T3TUU%   #!!%%ein'1%NN        'K9IKK   ""5&111( 0 0''////s   -1 ;B.&BIterable['DXFEntity']c               3  P   K   t                      } D ]} | |          s|V  d S rS   )r   )linkedrW   rJ   s     r4   link_entitiesz)BlocksSection.load.<locals>.link_entities   sE      "__F" ! ! vf~~ ! LLL! !r6   r"   r   SECTIONr8   )   BLOCKSz+Critical structure error in BLOCKS section.z*Missing required ENDBLK, ignoring content.z9Found ENDBLK without a preceding BLOCK, ignoring content.r'   r>   rh   z<undefined>zRecovered block name "z" for block #.z#Ignoring invalid BLOCK definition #zIgnoring BLOCK without name #N)r<   r   ra   r   rb   r^   r)   rc   )r)   rl   )rT   r   dxftype
base_classr   _MISSING_BLOCK_rD   r   loggerwarningclearr   r@   rA   rF   infor'   r   addappend)rP   rJ   rk   ro   section_headcontentr<   rW   
block_namerh   rE   rT   s    `         @r4   rM   zBlocksSection.load   s   	  	  	  	  	  	 2	! 	! 	! 	! 	! 	! *OXa[99!!Y..,2I!2L Q
 3
 3
 $$QRRRQK#%&#moo $	' $	'F&%(( #'//NN#OPPPFF++ 'O++NNS    "'vr!:!:J"Y]]8]CCF% 8%7%>%>
% 8"KK [ [ [RX [ [ [   .8EIN! 	R'8'8'P'P%lK@@  HH\2222"NN Of O O O    'Pv'P'P'PQQQ+E v&&&&I$	' $	'r6   c                   | j         D ]y}|j        pt          j        d|j        j        dd| j                  }t          j        di | j                  }|                    ||           |                     |           zdS )zFind BLOCK_RECORD entries without block definition in the blocks
        section and create block definitions for this orphaned block records.

        NBLOCK)r   r   r   )r'   
base_point)rf   rB   ENDBLK)	rT   r<   r   create_db_entryr@   r'   rB   ri   r{   )rP   rE   r<   ra   s       r4   rN   z1BlocksSection._reconstruct_orphaned_block_records   s    
 !. 	' 	'L!)/ , 0 5&/       !0!  
 &&uf555&&&!	' 	'r6   	tagwriterr$   c                    |                     d           | j        D ].}t          |t                    sJ |                    |           /|                    dd           d S )Nz  0
SECTION
  2
BLOCKS
r   ENDSEC)	write_strrT   rD   r   export_block_definition
write_tag2)rP   r   rE   s      r4   
export_dxfzBlocksSection.export_dxf   sr    9::: . 	< 	<LlK8888800;;;;Q)))))r6   rE   r   r   c                ~    t          |          }||_        | j                            |j        j                  sJ |S )zaAdd or replace a block layout object defined by its block record.
        (internal API)
        )r   block_layoutrT   	has_entryr@   r'   )rP   rE   r   s      r4   r{   zBlocksSection.add   sB     #<00$0!!++L,<,ABBBBBr6   Iterator[BlockLayout]c                $    d | j         D             S )z<Iterable of all :class:`~ezdxf.layouts.BlockLayout` objects.c              3  $   K   | ]}|j         V  d S rS   )r   ).0rE   s     r4   	<genexpr>z)BlocksSection.__iter__.<locals>.<genexpr>  s%      QQl)QQQQQQr6   )rT   rU   s    r4   __iter__zBlocksSection.__iter__  s    QQd>PQQQQr6   r'   r*   c                6    | j                             |          S )zVReturns ``True`` if :class:`~ezdxf.layouts.BlockLayout` `name`
        exist.
        )rT   r   rP   r'   s     r4   __contains__zBlocksSection.__contains__  s     !++D111r6   c                    	 t          d| j                            |                    }|j        S # t          $ r t          |          w xY w)zuReturns :class:`~ezdxf.layouts.BlockLayout` `name`,
        raises :class:`DXFKeyError` if `name` not exist.
        r   )r   rT   rA   r   r   r   )rP   r'   rE   s      r4   __getitem__zBlocksSection.__getitem__  sY    	$t/A/E/Ed/K/KLLL,,! 	$ 	$ 	$d###	$s	   .1 Ac                h    || v r| j                             |           dS t          d| d          )zDeletes :class:`~ezdxf.layouts.BlockLayout` `name` and all of
        its content, raises :class:`DXFKeyError` if `name` not exist.
        Block "" does not exist.N)rT   remover   r   s     r4   __delitem__zBlocksSection.__delitem__  sD     4<<%%d+++++????@@@r6   	list[str]c                b    t          | j        j        j                                                  S )z"Returns a list of all block names.)listrB   rT   entrieskeysrU   s    r4   block_nameszBlocksSection.block_names  s$    DH*27799:::r6   c                R    	 |                      |          S # t          $ r |cY S w xY w)zkReturns :class:`~ezdxf.layouts.BlockLayout` `name`, returns
        `default` if `name` not exist.
        )r   r   )rP   r'   defaults      r4   rA   zBlocksSection.get#  s?    	##D))) 	 	 	NNN	s    &&block_record_handlec                0    | j         j        |         j        S )z=Returns a block layout by block record handle. (internal API))rB   rC   r   )rP   r   s     r4   get_block_layout_by_handlez(BlocksSection.get_block_layout_by_handle,  s    x !45BBr6   r   r   c                   | j         J t          t          | j         j                            |                    }|pi }|j        j        |d<   ||d<   t          |          |d<   t          j	        d|| j                   }t          j	        dd|j        j        i| j                   }|
                    ||           |                     |          S )zCreate and add a new :class:`~ezdxf.layouts.BlockLayout`, `name`
        is the BLOCK name, `base_point` is the insertion point of the BLOCK.
        Nr?   r'   r   r   r   )rB   )rB   r   r   rT   rg   r@   rh   r   r   r   ri   r{   )rP   r'   r   rf   rE   headtails          r4   rg   zBlocksSection.new0  s     x###K)?)C)CD)I)IJJ%2
*.5
7!
6#'
#3#3
< &w
DHEE&w 0 78dh
 
 
 	tT***xx%%%r6   U	type_charc                v    |                      |          }|                     ||dt          j        i          }|S )a  Create and add a new anonymous :class:`~ezdxf.layouts.BlockLayout`,
        `type_char` is the BLOCK type, `base_point` is the insertion point of
        the BLOCK.

            ========= ==========
            type_char Anonymous Block Type
            ========= ==========
            ``'U'``   ``'*U###'`` anonymous BLOCK
            ``'E'``   ``'*E###'`` anonymous non-uniformly scaled BLOCK
            ``'X'``   ``'*X###'`` anonymous HATCH graphic
            ``'D'``   ``'*D###'`` anonymous DIMENSION graphic
            ``'A'``   ``'*A###'`` anonymous GROUP
            ``'T'``   ``'*T###'`` anonymous block for ACAD_TABLE content
            ========= ==========

        flags)anonymous_block_namerg   r   BLK_ANONYMOUS)rP   r   r   r   r<   s        r4   new_anonymous_blockz!BlocksSection.new_anonymous_blockG  s9    & ..y99
Z'5;N1OPPr6   c                v    	 | xj         dz  c_         d| | j          }| j                            |          s|S 9)a  Create name for an anonymous block. (internal API)

        Args:
            type_char: letter

                U = *U### anonymous blocks
                E = *E### anonymous non-uniformly scaled blocks
                X = *X### anonymous hatches
                D = *D### anonymous dimensions
                A = *A### anonymous groups
                T = *T### anonymous ACAD_TABLE content

        Tr8   r9   )rO   rT   r   )rP   r   r   s      r4   r   z"BlocksSection.anonymous_block_name^  sT    	"))Q.))GYG(EGGJ%//
;; "!!		"r6   old_namenew_namec                    t          t          | j                            |                    }|                    |           | j                            ||           |                     |           dS )a"  Rename :class:`~ezdxf.layouts.BlockLayout` `old_name` to `new_name`

        .. warning::

            This is a low-level tool and does not rename the block references,
            so all block references to `old_name` are pointing to a non-existing
            block definition!

        N)r   r   rT   rA   renamereplacer{   )rP   r   r   rE   s       r4   rename_blockzBlocksSection.rename_blockr  si     K);)?)?)I)IJJH%%%""8\:::r6   Tsafec                .   |r| j         
J d            | j         j                            |          }|t          d| d          |j        sdS |j        rt          d| d          t          |          rt          d| d          d| d	}	 | j                             |          }n/# t          $ r" t                              d
| d           Y dS w xY wt          |          rt          d| d          |                     |           dS )a  Delete block.

        Applies some safety checks when `safe` is ``True``.
        A :class:`DXFBlockInUseError` will be raised for:

            - blocks with active references
            - blocks representing existing layouts
            - special blocks used internally

        Args:
            name: block name (case-insensitive)
            safe: apply safety checks

        Raises:
            DXFKeyError: if block not exists
            DXFBlockInUseError: when safe is ``True`` and block is in use
        Nzvalid DXF document requiredr   r   z " represents an existing layout.zSpecial block "z," maybe used without explicit INSERT entity.zINSERT[name=="z"]iz Parsing error in query string: ""z" is still in use.)rB   blocksrA   r   is_aliveis_any_layoutr   r5   queryr
   rw   errorr;   r   )rP   r'   r   r<   query_string
block_refss         r4   delete_blockzBlocksSection.delete_block  sw   $  	M8'')F'''HO''--E}!"CD"C"C"CDDD> " (DdDDD    %% (XdXXX   6D555L!X^^L99

!   OOOOPPP : M()K4)K)K)KLLLs   B/ /(CCc                b   | j         J t          d | j                             d          D                       d	fd}t                      }| D ]B}t          j        |j                  }|j        s  ||          r|                    |           C|D ]}|                     |           dS )
a  Delete all blocks without references except modelspace- or
        paperspace layout blocks, special arrow- and anonymous blocks
        (DIMENSION, ACAD_TABLE).

        .. warning::

            There could exist references to blocks which are not documented in the DXF
            reference, hidden in extended data sections or application defined data,
            which could invalidate a DXF document if these blocks will be deleted.

        Nc              3  R   K   | ]"}t          j        |j        j                  V  #d S rS   )r   make_table_keyr@   r'   )r   rW   s     r4   r   z2BlocksSection.delete_all_blocks.<locals>.<genexpr>  sE        
  
 $VZ_55 
  
  
  
  
  
r6   INSERTr'   r(   r)   r*   c                .    t          |           rdS | vS )NF)r5   )r'   active_referencess    r4   is_safez0BlocksSection.delete_all_blocks.<locals>.is_safe  s$    %% u000r6   r'   r(   r)   r*   )	rB   setr   r   r   r'   r   r{   r   )rP   r   trashr<   r'   r   s        @r4   delete_all_blockszBlocksSection.delete_all_blocks  s     x###  
  
(..22 
  
  
 
 

	1 	1 	1 	1 	1 	1
  	  	 E+EJ77D&  774==  		$ 	# 	#DT""""	# 	#r6   auditorr   c                   | j         |j         u s
J d            | j        D ]}t          |t                    sJ |j        j        }g }|j        }|D ]L}t          |          sU|                    t          j
        dt          |           d|j        j         d           |                    |           nit          |t                    rT|                    t          j        dt          |           d|j        j         d           |                    |           |j        s|j        j        |k    rd|                    t          j        dt          |           d	|j        j         d
| d|j        j         d	           |                    |           N|D ]0}|j        r'	 |                    |            # t*          $ r Y ,w xY w1dS )aD  Audit and repair BLOCKS section.

        .. important::

            Do not delete entities during the auditing process as this will alter
            the entity database while iterating it, instead use::

                auditor.trash(entity)

            to delete invalid entities after auditing automatically.

        z#Auditor for different DXF document.zRemoved invalid DXF entity z from BLOCK 'z'.)codemessagezRemoved standalone z entity from BLOCK 'zRemoved DXF entity z with invalid owner handle (#z != #z) from BLOCK 'N)rB   rT   rD   r   r@   rh   entity_spacer   fixed_errorr   REMOVED_INVALID_GRAPHIC_ENTITYr(   r'   r   r    REMOVED_STANDALONE_ATTRIB_ENTITYr   r?   (REMOVED_ENTITY_WITH_INVALID_OWNER_HANDLEr|   r   
ValueError)rP   r   rE   r   unlink_entitiesesrW   s          r4   auditzBlocksSection.audit  s}    x7;&&&(M&&& . *	 *	LlK88888'3'7'>/1O*B 3 3(00 *'''F!=c&kk != !=#/#3#8!= != != (   
 MM&))))// * '''H!=c&kk != !=#/#3#8!= != != (   
 MM&))) :#':::'''P!Ac&kk !A !A$*J$4!A !A;N!A !A'3'7'<!A !A !A (    $**6222)  ? 		&))))%   K*	 *	s   +G
GG)NN)rB   rI   rJ   rK   )rW   rX   r)   r(   )r)   r%   )r)   r#   )rJ   r^   r)   r_   )r   r$   r)   r_   )rE   r   r)   r   )r)   r   r   )r'   r(   r)   r   )r'   r(   r)   r_   )r)   r   rS   )r   r(   r)   r   )r'   r(   r   r   r)   r   )r   r(   r   r   r)   r   )r   r(   r)   r(   )r   r(   r   r(   r)   r_   )T)r'   r(   r   r*   r)   r_   )r)   r_   )r   r   r)   r_   )__name__
__module____qualname____doc__rQ   rV   staticmethodr[   propertyrT   rC   rM   rN   r   r{   r   r   r   r   r   rA   r   r   rg   r   r   r   r   r   r    r6   r4   rH   rH   ^   sG         "&.2	* 	* 	* 	* 	*' ' '    \
 & & & X& ! ! ! X!X' X' X' X't' ' '.* * * *   R R R R2 2 2 2$ $ $ $A A A A; ; ; ;    C C C C #	& & & & &0  #w    ." " " "(   * * * * *X# # # #@9 9 9 9 9 9r6   rH   r   )r<   r   r)   r(   )9
__future__r   typingr   r   r   r   r   r	   logging	pyparsingr
   ezdxf.auditr   r   ezdxf.layouts.blocklayoutr   ezdxf.lldxfr   r   ezdxf.lldxf.constr   r   r   r   r   ezdxf.entitiesr   r   r   r   r   r   r   
ezdxf.mathr   r   r   ezdxf.render.arrowsr   ezdxf.documentr    r!   r"   ezdxf.entitydbr#   ezdxf.lldxf.tagwriterr$   ezdxf.sections.tabler%   	getLoggerrw   r5   r.   rF   rv   rH   r   r6   r4   <module>r      s   # " " " " "                 $ $ $ $ $ $ + + + + + + + + 1 1 1 1 1 1 ( ( ( ( ( ( ( (                               + * * * * * * * * * & & & & & & +&&&&&&77777777''''''777777******		7	#	#   $D D D D   " %''h h h h h h h h h hr6   