o
    &h                    @   s  d dl Zd dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	m
Z
mZmZmZmZmZmZmZmZmZmZmZ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"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+ ddl,m-Z-m.Z.m/Z/m0Z0m1Z1 g dZ2i Z3h dZ4de5d	e5fd
dZ6de5d	e5e7e5df ffddZ8d_ddZ9G dd dZ:G dd dZ;G dd dZ<dd Z=G dd dZ>G dd dZ?G dd dZ@G d d! d!ZAG d"d# d#ZBi ZCd$d% ZDd&d' ZEd(d) ZFd*d+ ZGd,d- ZHG d.d/ d/ZIG d0d1 d1eIeJZKG d2d3 d3eKZLe1eIe& e1eKe eKd4ZMeMNd5 eMNd6 eKd7ZOeKd8ZPeKd9ZQeQNd: eKd;ZReKd<ZSeKd=ZTeKd>ZUeKd?ZVeKd@ZWdAdB ZXdCdD ZYeYZZeHeWG dEdF dFeIZ[e[d4Z\zeKdGZ]W n e^yz   G dHdG dGeMZ]Y nw dIdJ Z_e	eeZ`e	eeZae	eeeZbG dKdL dLeZcG dMdN dNeZdG dOdP dPeZedQdR ZfdSdT Zgeh ZiG dUdV dVZjG dWdX dXZkG dYdZ dZeIZled[ me#d\Zneh ZoG d]d^ d^ZpdS )`    N)	CFUNCTYPEPOINTERArray	StructureUnion	addressofbyrefc_boolc_char_pc_intc_uintc_uint8c_ulongc_void_pcast	py_objectsizeof	string_at   )SELClassadd_ivar
add_methodensure_bytes	get_classget_ivarlibclibobjc
objc_blockobjc_idobjc_property_attribute_tobject_isClasssend_message
send_superset_ivar)compound_value_for_sequencectype_for_typectypes_for_method_encodingencoding_for_ctyperegister_ctype_for_type)BlockNSArrayNSDataNSDecimalNumberNSDictionaryNSMutableArrayNSMutableDictionaryNSNumberNSObjectNSObjectProtocolNSString	ObjCBlock	ObjCClassObjCInstanceObjCMetaClassObjCProtocolProtocolatfor_objcclassget_type_for_objcclass_map
ns_from_pyobjc_classmethod
objc_const	objc_ivarobjc_methodobjc_propertyobjc_rawmethod
py_from_nsregister_type_for_objcclasstype_for_objcclassunregister_type_for_objcclass>   newcopyZmutableCopyinitallocmethod_namereturnc                 C   sR   |  ddd }tD ]}||r&||}|dks"|d  s&|  S qdS )zReturns the method family from the method name.

    See
    https://clang.llvm.org/docs/AutomaticReferenceCounting.html#method-families
    for documentation on method families and corresponding selector names.
    _:r    )lstripsplit_RETURNS_RETAINED_FAMILIES
startswithremoveprefixislower)rM   Zfirst_componentfamily	remainder rZ   g/Users/merlin/projects/employee-monitoring-system/venv/lib/python3.10/site-packages/rubicon/objc/api.pyget_method_familyc   s   

r\   name.c                 C   sH   |  dr| d^}}}|dd t|}||fS | }d}||fS )aj  
    Performs the following transformation:

    "methodWithArg0:withArg1:withArg2:" ->
    "methodWithArg0", ("", "withArg1", "withArg2")

    "methodWithArg0:" -> "methodWithArg0", ("", )

    "method" -> "method", ()

    The first element of the returned tuple is the "base name" of the method. The second
    element is a tuple with its argument names.
    rP   r   rQ   rZ   )endswithrS   inserttuple)r]   firstrestrO   rZ   rZ   r[   method_name_to_tuplet   s   
rc   c                 C   sV   t t | }t| }|dtttg}|j|d  D ]}|	||t q|S )NrN   )
inspectgetfullargspecunwraptypingget_type_hintsgetr7   r   argsappend)foffsetZargspechintsencodingvarnamerZ   rZ   r[   encoding_from_annotation   s   
rq   c                   @   s0   e Zd ZdZdd Zdd Zddddd	Zd
S )
ObjCMethoda  An unbound Objective-C method. This is Rubicon's high-level equivalent of
    :class:`~rubicon.objc.runtime.Method`.

    :class:`ObjCMethod` objects normally don't need to be used directly. To call
    a method on an Objective-C object, you should use the method call syntax
    supported by :class:`ObjCInstance`, or the
    :func:`~rubicon.objc.runtime.send_message` function.

    .. note::

        This is *not* the same class as the one used for *bound* Objective-C
        methods, as returned from :meth:`ObjCInstance.__getattr__`. Currently,
        Rubicon doesn't provide any documented way to get an unbound
        :class:`ObjCMethod` object for an instance method of an
        :class:`ObjCClass`.
    c                 C   sb   t || _| jj| _t || _t| j^| _| _| jdd t	t
gks'J | jdd | _dS )a)  The constructor takes a :class:`~rubicon.objc.runtime.Method` object, whose
        information is used to create an :class:`ObjCMethod`.

        This can be used to call or introspect a
        :class:`~rubicon.objc.runtime.Method` pointer received from the
        Objective-C runtime.
        N   )r   method_getNameselectorr]   Zmethod_getTypeEncodingro   r'   restypeZimp_argtypesr   r   method_argtypes)selfmethodrZ   rZ   r[   __init__   s   
zObjCMethod.__init__c                 C   s*   dt | j d| j  d| j  dS )N<:  >)type__qualname__r]   decodero   rx   rZ   rZ   r[   __repr__   s   zObjCMethod.__repr__T)convert_argsconvert_resultc                G   sh  t |t | jkrtd| j dt | dt | j d|rtg }t| j|D ]K\}}t|tjr4|j}t	|t
rP|du rBt|}n+t|rOt|tsOt|}nt	|trZt|}nt|tjjrmt	|ttfrmt||}|| q'n|}t| j }|dkrt|dtg d t|| jg|R | j| jd}	|s|	S | jdurt	| jtr|tv }
t|	|
d	}	|	S )
a  Call the method on an object with the given arguments.

        The passed arguments are automatically converted to the expected
        argument types as needed:

        * :class:`enum.Enum` objects are replaced by their
          :attr:`~enum.Enum.value` before further conversion
        * For parameters that expect a block, Python callables are converted to
          :class:`Block`\s
        * For parameters that expect an Objective-C object, Python objects are
          converted using :func:`ns_from_py`
        * For parameters that expect a C structure, Python sequences are
          converted using
          :func:`~rubicon.objc.types.compound_value_for_sequence`.
        * Finally, :mod:`ctypes` applies its normal function argument
          conversions.

        The above argument conversions (except those performed by :mod:`ctypes`)
        can be disabled by setting the ``convert_args`` keyword argument to
        ``False``.

        If the method returns an Objective-C object, it is automatically
        converted to an :class:`ObjCInstance`. This conversion can be disabled
        by setting the ``convert_result`` keyword argument to ``False``, in
        which case the object is returned as a raw
        :class:`~rubicon.objc.runtime.objc_id` value.

        The ``_cmd`` selector argument does *not* need to be passed in manually
        --- the method's :attr:`selector` is automatically added between the
        receiver and the method arguments.
        zMethod z takes z arguments, but got z
 argumentsNrK   retainrv   argtypes)_implicitly_owned)lenrw   	TypeErrorr]   zip
isinstanceenumEnumvalue
issubclassr   r>   callabler*   r   collectionsabcSequencer   r   r%   rk   r\   r   r"   ru   rv   rT   r7   )rx   receiverr   r   rj   Zconverted_argsargtypeargZmethod_familyresultZimplicitly_ownedrZ   rZ   r[   __call__   s\   !





	zObjCMethod.__call__N__name__
__module__r   __doc__rz   r   r   rZ   rZ   rZ   r[   rr      s
    rr   c                       s6   e Zd Ze Z fddZdd ZefddZ  ZS )ObjCPartialMethodc                    s   t    || _i | _d S N)superrz   
name_startmethods)rx   r   	__class__rZ   r[   rz   -  s   

zObjCPartialMethod.__init__c                 C      t | j d| jdS N())r   r   r   r   rZ   rZ   r[   r   6     zObjCPartialMethod.__repr__c           	   	   K   s  t dd |D }t| }|tju r|rtd|}n
|d| d| }z| j| }|j	|}||g|R  W S  t
yD   Y nw || ju rN| j}n| j dd|  d}|j	|}|rq|| j|< ||g|R  S td| dd	d
d | j D  d )Nc                 s   s    | ]
}| d d V  qdS )__r   N)rS   ).0argnamerZ   rZ   r[   	<genexpr>;  s    z-ObjCPartialMethod.__call__.<locals>.<genexpr>z#Missing first (positional) argumentr   )rQ   rP   zInvalid selector z. Available selectors are: , c                 s   s    | ]}|V  qd S r   rZ   )r   selrZ   rZ   r[   r   ]  s    )r`   listvaluesr   	_sentinelr   r_   r   
objc_class_cache_methodKeyErrorr   joinkeys
ValueError)	rx   r   Z	first_argkwargsorderrj   rb   r]   methrZ   rZ   r[   r   9  s:   



zObjCPartialMethod.__call__)	r   r   r   objectr   rz   r   r   __classcell__rZ   rZ   r   r[   r   *  s
    	r   c                   @   (   e Zd ZdZdd Zdd Zdd ZdS )	ObjCBoundMethodzThis represents an Objective-C method (an IMP) which has been bound to some id
    which will be passed as the first parameter to the method.c                 C   s,   || _ t|tu rt|t| _dS || _dS )z>Initialize with a method and ObjCInstance or ObjCClass object.N)ry   r   r   r   r   r   )rx   ry   r   rZ   rZ   r[   rz   e  s   
zObjCBoundMethod.__init__c                 C   s    t | j d| j d| j dS )Nr   r   r   )r   r   ry   r   r   rZ   rZ   r[   r   m  s    zObjCBoundMethod.__repr__c                 O   s   | j | jg|R i |S )z)Call the method with the given arguments.)ry   r   rx   rj   r   rZ   rZ   r[   r   p  s   zObjCBoundMethod.__call__Nr   rZ   rZ   rZ   r[   r   a  s
    r   c                 C   sL   g }t | dd |D ]\}}t|ttfr|t| q|| q|S )zvUsed to convert Objective-C method arguments to Python values before passing them
    on to the Python-defined method.   N)r   r   r   r7   rk   )ro   rj   new_argsearZ   rZ   r[   convert_method_argumentsu  s   r   c                       8   e Zd ZdZ fddZdd Zdd Zdd	 Z  ZS )
rB   a  Exposes the decorated method as an Objective-C instance method in a custom class
    or protocol.

    In a custom Objective-C class, decorating a method with :func:`@objc_method
    <objc_method>` makes it available to Objective-C: a corresponding
    Objective-C method is created in the new Objective-C class, whose
    implementation calls the decorated Python method. The Python method receives
    all arguments (including ``self``) from the Objective-C method call, and its
    return value is passed back to Objective-C.

    In a custom Objective-C protocol, the behavior is similar, but the method
    body is ignored, since Objective-C protocol methods have no implementations.
    By convention, the method body in this case should be empty (``pass``).
    (Since the method is never called, you could put any other code there as
    well, but doing so is misleading and discouraged.)
    c                       t    || _t|| _d S r   r   rz   	py_methodrq   ro   rx   r   r   rZ   r[   rz        
zobjc_method.__init__c                 G   sr   t |}t| j|}| j|g|R  }| jd d ur/t| jd tt fr/t|}|d ur/|j}t|t	r7|j
S |S Nr   )r7   r   ro   r   r   r   r>   ptrr   r   r   )rx   	objc_selfobjc_cmdrj   Zpy_selfr   rZ   rZ   r[   r        
zobjc_method.__call__c                 C       | dd}t||| | j d S NrO   rP   replacer   ro   rx   	class_ptr	attr_namer]   rZ   rZ   r[   class_register     zobjc_method.class_registerc                 C   s<   | dd}ddd | jD }t|t||dd d S )NrO   rP       c                 s       | ]	}t t|V  qd S r   r(   r&   r   tprZ   rZ   r[   r         z0objc_method.protocol_register.<locals>.<genexpr>Tr   r   ro   r   Zprotocol_addMethodDescriptionr   rx   	proto_ptrr   r]   typesrZ   rZ   r[   protocol_register     zobjc_method.protocol_register	r   r   r   r   rz   r   r   r   r   rZ   rZ   r   r[   rB     s    rB   c                       r   )
r?   a6  Exposes the decorated method as an Objective-C class method in a custom class or
    protocol.

    This decorator behaves exactly like :func:`@objc_method <objc_method>`, except that
    the decorated method becomes a class method, so it is exposed on the Objective-C
    class rather than its instances.
    c                    r   r   r   r   r   rZ   r[   rz     r   zobjc_classmethod.__init__c                 G   sr   t |}t| j|}| j|g|R  }| jd d ur/t| jd ttfr/t|}|d ur/|j}t	|t
r7|jS |S r   )r6   r   ro   r   r   r   r7   r>   r   r   r   r   )rx   Zobjc_clsr   rj   Zpy_clsr   rZ   rZ   r[   r     r   zobjc_classmethod.__call__c                 C   s&   | dd}tt||| | j d S r   )r   r   r   object_getClassro   r   rZ   rZ   r[   r     s   zobjc_classmethod.class_registerc                 C   s<   | dd}ddd | jD }t|t||dd d S )NrO   rP   r   c                 s   r   r   r   r   rZ   rZ   r[   r     r   z5objc_classmethod.protocol_register.<locals>.<genexpr>TFr   r   rZ   rZ   r[   r     r   z"objc_classmethod.protocol_registerr   rZ   rZ   r   r[   r?     s    r?   c                   @   r   )	rA   a  Defines an ``ivar`` in a custom Objective-C class.

    If you want to store additional data on a custom Objective-C class, it is
    recommended to use properties (:func:`objc_property`) instead of ``ivars``.
    Properties are a more modern and high-level Objective-C feature, which
    automatically deal with reference counting for objects, and creation of
    getters and setters.

    The ``ivar`` type may be any :mod:`ctypes` type.

    Unlike properties, the contents of an ``ivar`` cannot be accessed or
    modified using Python attribute syntax. Instead, the :func:`get_ivar`
    and :func:`set_ivar` functions need to be used.
    c                 C   s
   || _ d S r   )vartype)rx   r   rZ   rZ   r[   rz        
zobjc_ivar.__init__c                 C   s   t ||| jS r   )r   r   )rx   r   r   rZ   rZ   r[   r     s   zobjc_ivar.class_registerc                 C      t d)Nz'Objective-C protocols cannot have ivarsr   rx   r   r   rZ   rZ   r[   r     s   zobjc_ivar.protocol_registerN)r   r   r   r   rz   r   r   rZ   rZ   rZ   r[   rA     s
    rA   c                       sF   e Zd ZdZedf fdd	Zdd Zdd Zd	d
 Zdd Z	  Z
S )rC   ai  Defines a property in a custom Objective-C class or protocol.

    This class should be called in the body of an Objective-C subclass or
    protocol, for example:

    .. code-block:: python

        class MySubclass(NSObject):
            counter = objc_property(NSInteger)

    The property type may be any :mod:`ctypes` type, as well as any of the
    Python types accepted by :func:`~rubicon.objc.types.ctype_for_type`.

    Defining a property automatically defines a corresponding getter and setter.
    Following standard Objective-C naming conventions, for a property ``name``
    the getter is called ``name`` and the setter is called ``setName:``.

    In a custom Objective-C class, implementations for the getter and setter are
    also generated, which store the property's value in an ``ivar`` called
    ``_name``. If the property has an object type, the generated setter keeps
    the stored object retained, and releases it when it is replaced.

    In a custom Objective-C protocol, only the metadata for the property is
    generated.

    If ``weak`` is ``True``, the property will be created as a weak property.
    When assigning an object to it, the reference count of the object will not
    be increased. When the object is deallocated, the property value is set to
    None. Weak properties are only supported for Objective-C or Python object
    types.
    Fc                    st   t    t|| _|| _t| jt| _t| jt| _	| jo!| j | _
| jr4| js6| j	s8td|dd S d S d S )NzIncompatible type for ivar zK: Weak properties are only supported for Objective-C or Python object types)r   rz   r&   r   weakr   r   _is_py_objectr   _is_objc_object
_ivar_weakr   )rx   r   r   r   rZ   r[   rz     s   


zobjc_property.__init__c                 C   sF   t dt| jg}| jr| jrdnd}|t |d t t| | S )N   T   W   &r   )r    r(   r   r   r   rk   r   )rx   attrs	referencerZ   rZ   r[   _get_property_attributes)  s   z&objc_property._get_property_attributesc                    s   d|  t | j  fdd} fdd}d|d   |dd   d	 }t|||jttg t|||d ttjg  }t|t	||t
| d S )
NrO   c                    sR   t |  jd}t|ttfsz|j}W n	 ty   Y nw jr'jr'| }|S )Nr   )	r   r   r   r   r   r   AttributeErrorr   r   )r   _cmdr   	ivar_namerx   rZ   r[   _objc_getterD  s   
z2objc_property.class_register.<locals>._objc_getterc                    s   j rjrt|}t|js|}jr,js,t|  jd}|j|jkr,d S t	|  |j
d jrSjsS|rEt|dd g d |rQt|dtg d d S d S j r`|jt| jf< d S d S )Nr   releaser   r   )r   r   weakrefrefr   r   r   r   r   r$   r   r"   r   _keep_alive_objects)r   r   	new_value	old_valuer   rZ   r[   _objc_setterW  s$   

z2objc_property.class_register.<locals>._objc_settersetr   r   rP   )r   r   upperr   r7   r   r   r   Zclass_addPropertyr   r   )rx   r   r   r   r  Zsetter_namer   rZ   r   r[   r   3  s&    %
zobjc_property.class_registerc                 C   sb   d| }| j rt||| d dd n| jr&t||| jd}t|dd g d t|j	| fd  d S )NrO   Tr   r   r   )
r   r$   r   r   r   r   r"   r  popr   )rx   r   r   r   r  rZ   rZ   r[   dealloc_callback  s   zobjc_property.dealloc_callbackc                 C   s(   |   }t|t||t|dd d S )NT)r   r   Zprotocol_addPropertyr   r   )rx   r   r   r   rZ   rZ   r[   r     s   zobjc_property.protocol_register)r   r   r   r   r   rz   r   r   r  r   r   rZ   rZ   r   r[   rC     s     
[rC   c                       r   )
rD   aP  Exposes the decorated method as an Objective-C instance method in a custom class,
    with fewer convenience features than :func:`objc_method`.

    This decorator behaves similarly to :func:`@objc_method <objc_method>`.
    However, unlike with :func:`objc_method`, no automatic conversions are
    performed (aside from those by :mod:`ctypes`). This means that all parameter
    and return types must be provided as :mod:`ctypes` types (no
    :func:`~rubicon.objc.types.ctype_for_type` conversion is performed), all
    arguments are passed in their raw form as received from :mod:`ctypes`, and
    the return value must be understood by :mod:`ctypes`.

    In addition, the implicit ``_cmd`` parameter is exposed to the Python
    method, which is not the case when using :func:`objc_method`. This means
    that the decorated Python method must always have an additional ``_cmd``
    parameter after ``self``; if it is missing, there will be errors at runtime
    due to mismatched argument counts. Like ``self``, ``_cmd`` never needs to be
    annotated, and any annotations on it are ignored.
    c                    s"   t    || _t|dd| _d S )Nrs   )rm   r   r   r   rZ   r[   rz     s   
zobjc_rawmethod.__init__c                 O   s   | j |i |S r   )r   r   rZ   rZ   r[   r        zobjc_rawmethod.__call__c                 C   r   r   r   r   rZ   rZ   r[   r     r   zobjc_rawmethod.class_registerc                 C   r   )NzWProtocols cannot have method implementations, use objc_method instead of objc_rawmethodr   r   rZ   rZ   r[   r     s   z objc_rawmethod.protocol_registerr   rZ   rZ   r   r[   rD     s    rD   c                 C   s   t | tr| j} | }g }t}|jdur4zt|j }W n ty-   || t	|}Y nw n|jdus|D ]}t
|| q6|S )a  Look up the :class:`ObjCInstance` subclass used to represent instances of the
    given Objective-C class in Python.

    If the exact Objective-C class is not registered, each superclass is also
    checked, defaulting to :class:`ObjCInstance` if none of the classes in the
    superclass chain is registered. Afterwards, all searched superclasses are
    registered for the :class:`ObjCInstance` subclass that was found. (This
    speeds up future lookups, and ensures that previously computed mappings are
    not changed by unrelated registrations.)

    This method is mainly intended for internal use by Rubicon, but is exposed
    in the public API for completeness.
    N)r   r6   r   r7   r   _type_for_objcclass_mapr   rk   r   class_getSuperclassrF   )	objcclass
superclassZtraversed_classespytypeclsrZ   rZ   r[   rG     s"   



	rG   c                 C   s   t |tr|j}| t|j< dS )a  Register a conversion from an Objective-C class to an :class:`ObjCInstance`
    subclass.

    After a call of this function, when Rubicon wraps an Objective-C object that
    is an instance of ``objcclass`` (or a subclass), the Python object will have
    the class ``pytype`` rather than :class:`ObjCInstance`. See
    :func:`type_for_objcclass` for a full description of the lookup process.

    .. warning::

        This function should only be called if no instances of ``objcclass`` (or
        a subclass) have been wrapped by Rubicon yet. If the function is called
        later, it will not fully take effect: the types of existing instances do
        not change, and mappings for subclasses of ``objcclass`` are not
        updated.
    Nr   r6   r   r
  r   )r  r  rZ   rZ   r[   rF     s   
rF   c                 C   s   t | tr| j} t| j= dS )a  Unregister a conversion from an Objective-C class to an :class:`ObjCInstance`
    subclass.

    .. warning::

        This function should only be called if no instances of ``objcclass`` (or
        a subclass) have been wrapped by Rubicon yet. If the function is called
        later, it will not fully take effect: the types of existing instances do
        not change, and mappings for subclasses of ``objcclass`` are not
        removed.
    Nr  r  rZ   rZ   r[   rH     s   
rH   c                   C   s   t tS )zGet a copy of all currently registered :class:`ObjCInstance` subclasses as a
    mapping.

    Keys are Objective-C class addresses as :class:`int`\s.
    )dictr
  rZ   rZ   rZ   r[   r=     s   r=   c                    s    fdd}|S )zDecorator for registering a conversion from an Objective-C class to an
    :class:`ObjCInstance` subclass.

    This is equivalent to calling :func:`register_type_for_objcclass` on
    the decorated class.
    c                    s   t |   | S r   )rF   )r  r  rZ   r[   _for_objcclass0  s   
z%for_objcclass.<locals>._for_objcclassrZ   )r  r  rZ   r  r[   r<   (  s   r<   c                       s   e Zd ZdZe Ze Z	e
 fddZedd Z	d fdd		Zd
d Zdd Zdd Zdd Z fddZ fddZ  ZS )r7   z+Python wrapper for an Objective-C instance.c                    sd   zt tt| | dW S  ty1   t tt| | dtt|  t tt| | d Y S w )z9The Objective-C object's class, as an :class:`ObjCClass`.Z_objc_class)	r   r7   r   __getattribute__r   __setattr__r6   r   r   r   r   rZ   r[   r   Q  s   	zObjCInstance.objc_classc                 C   s   t d|  S )Nzrubicon.objc.py_attr.)r   )r]   rZ   rZ   r[   _associated_attr_key_for_nameg  s   z*ObjCInstance._associated_attr_key_for_nameNFc              	      sx  t |ts
t|t}|jsdS tj z| j|j }|r$t|dtg d |W W  d   S  ty6   Y nw |sAt|dtg d t	| t
sUt|rUt
|W  d   S t	| trdt | |||}nt |trlt} ntt|} t | }ttt||d| ttt||d| t |trttt||dt| || j|j< W d   |S 1 sw   Y  |S )am  The constructor accepts an :class:`~rubicon.objc.runtime.objc_id` or anything
        that can be cast to one, such as a :class:`~ctypes.c_void_p`, or an existing
        :class:`ObjCInstance`.

        :class:`ObjCInstance` objects are cached --- this means that for every
        Objective-C object there can be at most one :class:`ObjCInstance` object
        at any time. Rubicon will automatically create new
        :class:`ObjCInstance`\s or return existing ones as needed.

        The returned object's Python class is not always exactly
        :class:`ObjCInstance`. For example, if the passed pointer refers to a
        class or a metaclass, an instance of :class:`ObjCClass` or
        :class:`ObjCMetaClass` is returned as appropriate. Additional custom
        :class:`ObjCInstance` subclasses may be defined and registered using
        :func:`register_type_for_objcclass`. Creating an :class:`ObjCInstance`
        from a ``nil`` pointer returns ``None``.

        Rubicon retains an Objective-C object when it is wrapped in an
        :class:`ObjCInstance` and autoreleases it when the :class:`ObjCInstance` is
        garbage collected.

        The only exception to this are objects returned by methods which create an
        object (starting with "alloc", "new", "copy", or "mutableCopy"). We do not
        explicitly retain them because we already own objects created by us, but we do
        autorelease them on garbage collection of the Python wrapper.

        This ensures that the :class:`ObjCInstance` can always be used from Python
        without segfaults while preventing Rubicon from leaking memory.
        Nr   r   r   r   _as_parameter_block)r   r   r   r   r7   _instance_lock_cached_objectsr"   r   r   r6   r!   r   r   __new__r   ObjCBlockInstancerG   r   r   r  r5   )r  Z
object_ptr_nameZ_basesZ_nsr   Z
cached_objrx   r   rZ   r[   r  k  sL   
"

$



;;zObjCInstance.__new__c              	   C   s0   zt | dtg d W d S  ttfy   Y d S w )NZautoreleaser   )r"   r   	NameErrorr   r   rZ   rZ   r[   __del__  s
   zObjCInstance.__del__c                 C   s4   | j }|durt|S | j}|durt|S t| S )aY  Get a human-readable representation of ``self``.

        By default, ``self.description`` converted to a Python string is
        returned. If ``self.description`` is ``nil``,
        ``self.debugDescription`` converted to a Python is returned
        instead. If that is also ``nil``, ``repr(self)`` is returned as
        a fallback.
        N)descriptionstrdebugDescriptionrepr)rx   ZdescrZ   rZ   r[   __str__  s   	zObjCInstance.__str__c              	   C   s0   dt | j d| jj dt| dd| j d	S )z{Get a debugging representation of ``self``, which includes the Objective-C
        object's class and ``debugDescription``.r{   r|   z at #xr~   )r   r   r   r]   idr"  r   rZ   rZ   r[   r     s   zObjCInstance.__repr__c              	   C   sP  | ds| j|}|rt||  S | j}|durT|j+ |jdu r'|  z|j| }W W d   n! ty@   |j	}Y nw W d   n1 sKw   Y  |dusd}|du sbt
|jdhkrl| j|dd}|rst|| S | |}t| |}|jdu rtt| j dt| j d| jj d| t|d}t|jt}|jS )	a  Allows accessing Objective-C properties and methods using Python attribute
        syntax.

        If ``self`` has a Python attribute with the given name, its value is
        returned.

        If there is an Objective-C property with the given name, its value is
        returned using its getter method. An attribute is considered a property
        if any of the following are true:

        * A property with the name is present on the class (i.e. declared using
          ``@property`` in the source code)
        * There is both a getter and setter method for the name
        * The name has been declared as a property using
          :meth:`ObjCClass.declare_property`

        Otherwise, a method matching the given name is looked up.
        :class:`ObjCInstance` understands two syntaxes for calling Objective-C
        methods:

        * "Flat" syntax: the Objective-C method name is spelled out in the
          attribute name, with all colons replaced with underscores, and all
          arguments are passed as positional arguments. For example, the
          Objective-C method call ``[self initWithWidth:w height:h]`` translates
          to ``self.initWithWidth_height_(w, h)``.
        * "Interleaved" syntax: the Objective-C method name is split up between
          the attribute name and the keyword arguments passed to the returned
          method. For example, the Objective-C method call ``[self initWithRed:r
          green:g blue:b]`` translates to ``self.initWithRed(r, green=g,
          blue=b)``.

        The "interleaved" syntax is usually preferred, since it looks more
        similar to normal Objective-C syntax. However, the "flat" syntax is also
        fully supported. If two arguments have the same name (e.g.
        ``performSelector:withObject:withObject:``), you can use ``__`` in the
        keywords to disambiguate (e.g., ``performSelector(..., withObject__1=...,
        withObject__2=...)``. Any content after and including the ``__`` in an argument
        will be ignored.
        rO   NrZ   rP   .r}    has no attribute wrapped_pointer)r^   r   _cache_property_accessorr   
cache_lockmethods_ptr_load_methodspartial_methodsr   r  r  r   r   r   r  r   objc_getAssociatedObjectr   r   r   r   r   r]   r   r   r   )rx   r]   ry   r  keypyo_wrapperaddresspyorZ   rZ   r[   __getattr__  sJ   
2






zObjCInstance.__getattr__c                    s   || j v rttt| | || dS | j|}|r-t|tj	r$|j
}t|| | dS tttddtg ddt|ttgd}| |}t| ||d t|dtg d dS )a  Allows modifying Objective-C properties using Python syntax.

        If ``self`` has a Python attribute with the given name, it is set.
        Otherwise, the name should refer to an Objective-C property, whose
        setter method is called with ``value``.
        WrappedPyObjectrL   r   zinitWithObjectId:  r   N)__dict__r   r7   r   r  r   _cache_property_mutatorr   r   r   r   r   r"   r   r   r&  r  r   objc_setAssociatedObject)rx   r]   r   ry   wrapperr0  r   rZ   r[   r  Y  s,   

zObjCInstance.__setattr__c                    s   || j v rttt| | | d S | |}t| |}|jd u r9t	t| j
 dt| j d| jj d| t| |d d d S )Nr'  r}   r(  r6  )r7  r   r7   r   __delattr__r  r   r/  r   r   r   r   r   r]   r9  )rx   r]   r0  r1  r   rZ   r[   r;    s   


zObjCInstance.__delattr__)NNNF)r   r   r   r   r   WeakValueDictionaryr  	threadingRLockr  propertyr   staticmethodr  r  r  r$  r   r4  r  r;  r   rZ   rZ   r   r[   r7   7  s     
fb*r7   c                       s   e Zd ZdZedd Zedd ZdZ	 edd Z	ed	d
 Z
edd Z		d,ddd fddZ fddZdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Z  ZS )-r6   zPython wrapper for an Objective-C class.

    :class:`ObjCClass` is a subclass of :class:`ObjCInstance` and supports the
    same syntaxes for calling methods and accessing properties.
    c                 C   s    t | }|jdu rdS t|S )zfThe superclass of this class, or ``None`` if this is a root class (such as
        :class:`NSObject`).N)r   r  r   r6   )rx   Z	super_ptrrZ   rZ   r[   r    s   

zObjCClass.superclassc                    2   t  }t| t| t fddt|jD S )z$The protocols adopted by this class.c                 3       | ]	}t  | V  qd S r   r9   r   iZprotocols_ptrrZ   r[   r     r   z&ObjCClass.protocols.<locals>.<genexpr>)r   r   Zclass_copyProtocolListr   r`   ranger   rx   Z	out_countrZ   rF  r[   	protocols     zObjCClass.protocolsFc                 C   s2   t |}t|}|jd u rtd| d||fS )NzObjC Class z couldn't be found.)r   r   r   r  )r  r]   r   rZ   rZ   r[   _new_from_name  s
   
zObjCClass._new_from_namec                 C   sP   t |t}|jd u rtdt|std| d|jddt|}||fS )Nz(Cannot create ObjCClass from nil pointerPointer  (r%  z) does not refer to a class)r   r   r   r   r!   r   Zclass_getName)r  r   r]   rZ   rZ   r[   _new_from_ptr  s   


zObjCClass._new_from_ptrc             
      s  |}t |}t|jd ur<|s|d u r4| jr4d}t|jd ur3|d7 }| d|  }t|jd usntd|dz|\}W n tyW }	 z
tdt| |	d }	~	ww t|t	smt
dt|j dt|j |D ]'}
t|
tst
dt|
j dt|
j ||
dkrtd	|
j d
qot||dd u rtd|D ]}
t|
std|
j q  D ]\}}|dkrz|j}W n	 ty   Y qw || q dd  fdd}td|d ttg t | fS )Nr   rO   zAn Objective-C class named  already existsz;An Objective-C class must have exactly one base class, not zCThe superclass of an Objective-C class must be an ObjCClass, not a r'  zRThe protocols list of an Objective-C class must contain ObjCProtocol objects, not z	Protocol z is adopted more than oncer   zClass pair allocation failedzFailed to adopt protocol deallocc              	      s`   r| |    D ]\}}z|j}W n	 ty   Y qw || | qt| dd g dd d S )NrP  T)rv   r   Z_allow_dealloc)itemsr  r   r#   )r   r   r   objr  r   r   Zuser_deallocrZ   r[   _new_delloc  s"   


z8ObjCClass._new_from_class_statement.<locals>._new_delloc)r   r   r   auto_renameencodeRuntimeErrorr   r   r   r6   r   r   r   r   r9   countr]   r   Zobjc_allocateClassPairZclass_addProtocolrQ  r   r   ri   r   r7   r   Zobjc_registerClassPair)r  r]   basesr   rI  rU  basenamesuffixr  excprotor   rR  r   rT  rZ   rS  r[   _new_from_class_statement  s   







z#ObjCClass._new_from_class_statementNrZ   rI  rU  c             	      s   |du |du A rt d|du rA|du rA|rtdi }t|ttfr+| |\}}n#| |\}}t| ts@t	
|r@t|S n| j|||||d\}}}|d}|di i i t i t d}	d|v rk|d |	d< t | ||tf|	}
|
S )a  The constructor accepts either the name of an Objective-C class to look up
        (as :class:`str` or :class:`bytes`), or a pointer to an existing class object
        (in any form accepted by :class:`ObjCInstance`).

        If given a pointer, it must refer to an Objective-C class; pointers to
        other objects are not accepted. (Use :class:`ObjCInstance` to wrap a
        pointer that might also refer to other kinds of objects.) If the pointer
        refers to a metaclass, an instance of :class:`ObjCMetaClass` is returned
        instead. Creating an :class:`ObjCClass` from a ``Nil`` pointer returns
        ``None``.

        :class:`ObjCClass` can also be called like :class:`type`, with three
        arguments (name, bases list, namespace mapping). This form is called
        implicitly by Python's ``class`` syntax, and is used to create a new
        Objective-C class from Python (see :ref:`custom-classes-and-protocols`).
        The bases list must contain exactly one :class:`ObjCClass` to be
        extended by the new class. An optional ``protocols`` keyword argument is
        also accepted, which must be a sequence of :class:`ObjCProtocol`\s for
        the new class to adopt.

        If the name of the class has already registered with the Objective C
        runtime, the ``auto_rename`` option can be used to ensure that the
        Objective C name for the new class will be unique. A numeric suffix will
        be appended to the Objective C name to ensure uniqueness (for example,
        ``MyClass`` will be renamed to ``MyClass_2``, ``MyClass_3`` etc until a
        unique name is found). By default, classes will *not* be renamed, unless
        :attr:`ObjCClass.auto_rename` is set at the class level.
        Nz2ObjCClass arguments 2 and 3 must be given togetherzHprotocols kwarg is not allowed for the single-argument form of ObjCClassr_  utf-8)r]   r,  instance_method_ptrsinstance_methodsinstance_propertiesforced_propertiesr.  r+  r   )r   r   r   bytesr!  rK  rN  r   r8   r   class_isMetaClassr^  r   r  r=  r>  r   r  r7   )r  name_or_ptrrY  r   rI  rU  r   r]   Zobjc_class_name	new_attrsrx   r   rZ   r[   r  5  sJ   &
zObjCClass.__new__c                    s   t  j|  d S r   )r   rz   r   r   rZ   r[   rz     s   zObjCClass.__init__c                 C   s   | j o z| j| W W  d   S  tyq   | }d}|durT|jdu r)|  z|j| }W n# ty9   Y nw z	t|j| }W n tyL   Y nw |j}|dus |du raY W d   dS || j|< | Y W  d   S w 1 suw   Y  dS )zReturns a python representation of the named instance method, either by
        looking it up in the cached list of methods or by searching for and creating a
        new method object.N)r+  rb  r   r,  r-  rr   ra  r  )rx   r]   ZsuperclsrB   rZ   rZ   r[   r     s@   



zObjCClass._cache_methodc                 C   s   | dr	d}|S t| |d}| |}| d|d   |dd  d }d}| }|durA||jv r:d	}n|j}|dus2|sI|rG|sI|rO||f}|S d}|S )
z7Return the accessor and mutator for the named property.rO   Nr`  r  r   r   rP   FT)r^   r   Zclass_getPropertyrV  r   titlerd  r  )rx   r]   r   ZrespondsaccessorZmutatorZforcedr  rZ   rZ   r[   _cache_property_methods  s&   

&
z!ObjCClass._cache_property_methodsc              	   C   l   | j # z| j| }W n ty   | |}|| j|< Y nw W d   n1 s)w   Y  |r4|d S dS )Returns a python representation of an accessor for the named property.

        Existence of a property is done by looking for the write selector (set<Name>:).
        Nr   r+  rc  r   rk  rx   r]   r   rZ   rZ   r[   r*       
z"ObjCClass._cache_property_accessorc              	   C   rl  )rm  Nr   rn  ro  rZ   rZ   r[   r8    rp  z!ObjCClass._cache_property_mutatorc                 C   s   | j | dS )a  Declare the instance method ``name`` to be a property getter.

        This causes the attribute named ``name`` on instances of this class to be
        treated as a property rather than a method --- accessing it returns the
        property's value, without requiring an explicit method call. See
        :class:`ObjCInstance.__getattr__` for a full description of how attribute access
        behaves for properties.

        Most properties do not need to be declared explicitly using this method, as they
        are detected automatically by :class:`ObjCInstance.__getattr__`. This method
        only needs to be used for properties that are read-only and don't have a
        ``@property`` declaration in the source code, because Rubicon cannot tell such
        properties apart from normal zero-argument methods.

        .. note::

            In the standard Apple SDKs, some properties are introduced as regular
            methods in one system version, and then declared as properties in a later
            system version. For example, the ``description`` method/property of
            :class:`NSObject` was declared as a regular method `up to OS X 10.9
            <https://github.com/phracker/MacOSX-SDKs/blob/9fc3ed0ad0345950ac25c28695b0427846eea966/MacOSX10.9.sdk/usr/include/objc/NSObject.h#L40>`__,
            but changed to a property `as of OS X 10.10
            <https://github.com/phracker/MacOSX-SDKs/blob/9fc3ed0ad0345950ac25c28695b0427846eea966/MacOSX10.10.sdk/usr/include/objc/NSObject.h#L43>`__.

            Such properties cause compatibility issues when accessed from Rubicon:
            ``obj.description()`` works on 10.9 but is a :class:`TypeError` on 10.10,
            whereas ``obj.description`` works on 10.10 but returns a method object on
            10.9. To solve this issue, the property can be declared explicitly using
            ``NSObject.declare_property('description')``, so that it can always be
            accessed using ``obj.description``.
        N)rd  addrx   r]   rZ   rZ   r[   declare_property  s   !zObjCClass.declare_propertyc                 C   s   | j j| dS )zDeclare the class method ``name`` to be a property getter.

        This is equivalent to
        ``self.objc_class.declare_property(name)``.
        N)r   rd  rq  rr  rZ   rZ   r[   declare_class_property.  s   z ObjCClass.declare_class_propertyc                 C      dt | j d| j dS Nr{   r|   r~   r   r   r]   r   rZ   rZ   r[   r   7     zObjCClass.__repr__c                 C   r   r   )r   r   r]   r   rZ   rZ   r[   r$  :  r   zObjCClass.__str__c                 C   s   t | j d S r   )r   freer,  r   rZ   rZ   r[   r  =  r	  zObjCClass.__del__c                 C      t |trt|| S dS )a]  Check whether the given object is an instance of this class.

        If the given object is not an Objective-C object, ``False`` is returned.

        This method allows using :class:`ObjCClass`\es as the second argument
        of :func:`isinstance`: ``isinstance(obj, NSString)`` is equivalent to
        ``obj.isKindOfClass(NSString)``.
        F)r   r7   boolisKindOfClassrx   instancerZ   rZ   r[   __instancecheck__@     

zObjCClass.__instancecheck__c                 C   s>   t |trt|| S td| dt|j dt|j )ak  Check whether the given class is a subclass of this class.

        If the given object is not an Objective-C class, :class:`TypeError` is
        raised.

        This method allows using :class:`ObjCClass`\es as the second argument
        of :func:`issubclass`: ``issubclass(cls, NSValue)`` is equivalent to
        ``obj.isSubclassOfClass(NSValue)``.
        issubclass(X, z") arg 1 must be an ObjCClass, not r'  )r   r6   r{  ZisSubclassOfClassr   r   r   r   rx   subclassrZ   rZ   r[   __subclasscheck__O  s   
zObjCClass.__subclasscheck__c              	   C   s@  | j d urt|  d| j}|d urP|j d u r/|j |  W d    n1 s*w   Y  |j D ]\}}t|}|| j|< |j	|j q4|j}|d ust
d}t| t|}t|jD ]9}|| }t|jd}	|| j|	< t|	\}
}z| j|
 }W n ty   t|
}|| j|
< Y nw |	|j|< qa|| _ d S )Nz.._load_methods cannot be called more than oncer   r`  )r,  rW  r  r+  r-  r.  rQ  r   r   updater   r   Zclass_copyMethodListr   rG  r   rt   r]   r   ra  rc   r   )rx   r  ra   ZsuperpartialpartialZmethods_ptr_countr,  rE  ry   r]   	base_nameZargument_namesrZ   rZ   r[   r-  b  s:   





zObjCClass._load_methods)NN)r   r   r   r   r?  r  rI  rU  classmethodrK  rN  r^  r  rz   r   rk  r*  r8  rs  rt  r   r$  r  r  r  r-  r   rZ   rZ   r   r[   r6     sB    





el$##	r6   c                       s    e Zd ZdZ fddZ  ZS )r8   a6  Python wrapper for an Objective-C metaclass.

    :class:`ObjCMetaClass` is a subclass of :class:`ObjCClass` and supports
    almost exactly the same operations and methods. However, there is usually no
    need to look up a metaclass manually. The main reason why
    :class:`ObjCMetaClass` is a separate class is to differentiate it from
    :class:`ObjCClass` in the :func:`repr`. (Otherwise there would be no way to
    tell classes and metaclasses apart, since metaclasses are also classes, and
    have exactly the same name as their corresponding class.)
    c                    s   t |ttfrt|}t|}|jdu rtd| dn$t|t	}|jdu r,t
dt|r5t|sBt
d| d|jddt | |S )	a!  The constructor accepts either the name of an Objective-C metaclass to look
        up (as :class:`str` or :class:`bytes`), or a pointer to an existing metaclass
        object (in any form accepted by :class:`ObjCInstance`).

        If given a pointer, it must refer to an Objective-C metaclass; pointers
        to other objects are not accepted. (Use :class:`ObjCInstance` to wrap a
        pointer that might also refer to other kinds of objects.) Creating an
        :class:`ObjCMetaClass` from a ``Nil`` pointer returns ``None``.
        NzObjective-C metaclass 
 not foundz+Cannot create ObjCMetaClass for nil pointerrL  rM  r%  z) does not refer to a metaclass)r   re  r!  r   r   Zobjc_getMetaClassr   r  r   r   r   r!   rf  r   r  )r  rg  r]   r   r   rZ   r[   r    s   



zObjCMetaClass.__new__)r   r   r   r   r  r   rZ   rZ   r   r[   r8     s    r8   r2   r"  r   r1   r-   r4   Z
UTF8Stringr,   r+   r/   r.   r0   r:   c                 C   s
  t | ttfrt| } t | ts| S | tr!tt| 	dS | t
rM| j}|dkr0| jS |dv r7| jS |dv r>| jS |dv rE| jS td|d| trVt| S | tritt| dttg d	| jS | trwd
d |  D S | trdd | D S | S )a,  Convert a Foundation object into an equivalent Python object if possible.

    Currently supported types:

    * :class:`~rubicon.objc.runtime.objc_id`: Wrapped in an
         :class:`ObjCInstance` and converted as below
    * :class:`NSString`: Converted to :class:`str`
    * :class:`NSData`: Converted to :class:`bytes`
    * :class:`NSDecimalNumber`: Converted to :class:`decimal.Decimal`
    * :class:`NSDictionary`: Converted to :class:`dict`, with all keys and
         values converted recursively
    * :class:`NSArray`: Converted to :class:`list`, with all elements converted
         recursively
    * :class:`NSNumber`: Converted to a :class:`bool`, :class:`int` or
         :class:`float` based on the type of its contents

    Other objects are returned unmodified as an :class:`ObjCInstance`.
    N   Bs   csilqs   CSILQs   fdz%NSNumber containing unsupported type z' cannot be converted to a Python objectre  r   c                 S   s   i | ]\}}t |t |qS rZ   rE   )r   kvrZ   rZ   r[   
<dictcomp>  s    zpy_from_ns.<locals>.<dictcomp>c                 S      g | ]}t |qS rZ   r  )r   orZ   rZ   r[   
<listcomp>      zpy_from_ns.<locals>.<listcomp>)r   r   r   r7   r|  r-   decimalDecimalr!  ZdescriptionWithLocaler1   ZobjCTypeZ	boolValueZlongLongValueZunsignedLongLongValueZdoubleValuer   r4   r,   r   r"   r   r   lengthr.   rQ  r+   )nsobjZ	objc_typerZ   rZ   r[   rE     s>   







rE   c                 C   sn  t | tjr	| j} | du st | tr| S t | tr%ttj| dddS t | t	r5tt
j| t| dS t | tjrFttj|  ddS t | trdtt| }|  D ]\}}|j||d qV|S t | tr|tt| }| D ]}|| qr|S t | trttj| ddS t | trttj| ddS t | t rttj!| ddS t"dt#| j$ dt#| j% d	)
a  Convert a Python object into an equivalent Foundation object. The returned object
    is autoreleased.

    This function is also available under the name :func:`at`, because its
    functionality is very similar to that of the Objective-C ``@`` operator and
    literals.

    Currently supported types:

    * ``None``, :class:`ObjCInstance`: Returned as-is
    * :class:`enum.Enum`: Replaced by their :attr:`~enum.Enum.value` and
         converted as below
    * :class:`str`: Converted to :class:`NSString`
    * :class:`bytes`: Converted to :class:`NSData`
    * :class:`decimal.Decimal`: Converted to :class:`NSDecimalNumber`
    * :class:`dict`: Converted to :class:`NSDictionary`, with all keys and
         values converted recursively
    * :class:`list`: Converted to :class:`NSArray`, with all elements converted
         recursively
    * :class:`bool`, :class:`int`, :class:`float`: Converted to
         :class:`NSNumber`

    Other types cause a :class:`TypeError`.
    Nr`  F)r   )r  )ZforKeyzDon't know how to convert a r'  z to a Foundation object)&r   r   r   r   r7   r!  r4   ZstringWithUTF8String_rV  re  r,   ZdataWithBytesr   r  r  r-   ZdecimalNumberWithString_to_eng_stringr  r0   ZdictionaryWithCapacityrQ  Z	setObjectr   r/   ZarrayWithCapacityZ	addObjectr{  r1   ZnumberWithBool_intZnumberWithLong_floatZnumberWithDouble_r   r   r   r   )ZpyobjZdiktr  r  arrayrZ   rZ   r[   r>     sN   






r>   c                       sX   e Zd ZdZedd Zedd ZdZ	 d fdd		Zd
d Z	dd Z
dd Z  ZS )r9   z+Python wrapper for an Objective-C protocol.c                 C   s   t | dS )z-The name of this protocol, as a :class:`str`.r`  )r   Zprotocol_getNamer   r   rZ   rZ   r[   r]   S  s   zObjCProtocol.namec                    rA  )z)The protocols that this protocol extends.c                 3   rB  r   rC  rD  rF  rZ   r[   r   _  r   z)ObjCProtocol.protocols.<locals>.<genexpr>)r   r   Zprotocol_copyProtocolListr   r`   rG  r   rH  rZ   rF  r[   rI  Y  rJ  zObjCProtocol.protocolsFNc                    s  |du |du A rt d|du rX|du rXt|ttfr2t|}t|}|jdu r1td| dnt	|t
}|jdu r@tdt|dttt
gdsWtd| d	|jd
dn|}t|}t|jdur|so|du r| jrd}t|jdur|d7 }| d|  }t|jdusyntd|d|D ]}	t|	tst dt|	j dt|	j qt|}|du rtd|D ]}
t||
 q| D ]\}}t|dr||| qt| t | |S )a  The constructor accepts either the name of an Objective-C protocol to look up
        (as :class:`str` or :class:`bytes`), or a pointer to an existing protocol object
        (in any form accepted by :class:`ObjCInstance`).

        If given a pointer, it must refer to an Objective-C protocol; pointers
        to other objects are not accepted. (Use :class:`ObjCInstance` to wrap a
        pointer that might also refer to other kinds of objects.) Creating an
        :class:`ObjCProtocol` from a ``nil`` pointer returns ``None``.

        :class:`ObjCProtocol` can also be called like :class:`type`, with three
        arguments (name, bases list, namespace mapping). This form is called
        implicitly by Python's ``class`` syntax, and is used to create a new
        Objective-C protocol from Python (see
        :ref:`custom-classes-and-protocols`). The bases list can contain any
        number of :class:`ObjCProtocol` objects to be extended by the new
        protocol.

        If the name of the protocol has already registered with the Objective C
        runtime, the ``auto_rename`` option can be used to ensure that the
        Objective C name for the new protocol will be unique. A numeric suffix
        will be appended to the Objective C name to ensure uniqueness (for
        example, ``MyProtocol`` will be renamed to ``MyProtocol_2``,
        ``MyProtocol_3`` etc until a unique name is found). By default,
        protocols will *not* be renamed, unless
        :attr:`ObjCProtocol.auto_rename` is set at the class level.
        Nz5ObjCProtocol arguments 2 and 3 must be given togetherzObjective-C protocol r  z*Cannot create ObjCProtocol for nil pointerzisKindOfClass:r   rL  rM  r%  z) does not refer to a protocolr   rO   zAn Objective-C protocol named rO  zBAn Objective-C protocol can only extend ObjCProtocol objects, not r'  zProtocol allocation failedr   )r   r   re  r!  r   r   Zobjc_getProtocolr   r  r   r   r   r"   r:   r	   rU  rV  rW  r9   r   r   r   Zobjc_allocateProtocolZprotocol_addProtocolrQ  hasattrr   Zobjc_registerProtocolr   r  )r  rg  rY  nsrU  r]   r   rZ  r[  baser]  r   rR  r   rZ   r[   r  e  sj   








zObjCProtocol.__new__c                 C   ru  rv  rw  r   rZ   rZ   r[   r     rx  zObjCProtocol.__repr__c                 C   rz  )ac  Check whether the given object conforms to this protocol.

        If the given object is not an Objective-C object, ``False`` is returned.

        This method allows using :class:`ObjCProtocol`\s as the second argument
        of :func:`isinstance`: ``isinstance(obj, NSCopying)`` is equivalent to
        ``obj.conformsToProtocol(NSCopying)``.
        F)r   r7   r{  conformsToProtocolr}  rZ   rZ   r[   r    r  zObjCProtocol.__instancecheck__c                 C   sX   t |trt|| S t |trtt|| S td| dt|j	 dt|j
 )a  Check whether the given class or protocol conforms to this protocol.

        If the given object is not an Objective-C class or protocol,
        :class:`TypeError` is raised.

        This method allows using :class:`ObjCProtocol`\s as the second argument
        of :func:`issubclass`: ``issubclass(cls, NSCopying)`` is equivalent to
        ``cls.conformsToProtocol(NSCopying)``, and ``issubclass(proto,
        NSCopying)`` is equivalent to ``protocol_conformsToProtocol(proto,
        NSCopying))``.
        r  z2) arg 1 must be an ObjCClass or ObjCProtocol, not r'  )r   r6   r{  r  r9   r   Zprotocol_conformsToProtocolr   r   r   r   r  rZ   rZ   r[   r    s   

zObjCProtocol.__subclasscheck__)NNN)r   r   r   r   r?  r]   rI  rU  r  r   r  r  r   rZ   rZ   r   r[   r9   O  s    

\r9   r5  c                       sD   e Zd ZeeZedd Zed	ddZed	 fddZ	  Z
S )
r5  c                 C   sF   t | dtg d} | d ur t|t}|jt| j|jf< t| d| | jS )NrK   r   r)  )r"   r   r   r   r   r  r$   )rx   cmdr2  r3  rZ   rZ   r[   initWithObjectId_  s   
z!WrappedPyObject.initWithObjectId_rN   Nc                 C   s&   t | d}|jrt| j|jf= d S d S )Nr)  )r   r   r  rx   r  r2  rZ   rZ   r[   rP    s   
zWrappedPyObject.deallocc                    s4   t | d}|jrt| j|jf= t | dd g d d S )Nr)  finalizer   )r   r   r  r#   r  r   rZ   r[   r    s   
zWrappedPyObject.finalize)rN   N)r   r   r   rA   r   r)  rD   r  rP  r  r   rZ   rZ   r   r[   r5    s    
c                 C   s   t t| |S )aO  Create an :class:`ObjCInstance` from a global pointer variable in a
    :class:`~ctypes.CDLL`.

    This function is most commonly used to access constant object pointers defined by a
    library/framework, such as
    `NSCocoaErrorDomain <https://developer.apple.com/documentation/foundation/nscocoaerrordomain?language=objc>`__.
    )r7   r   in_dll)Zdllr]   rZ   rZ   r[   r@   #  s   	r@   c                   @   s.   e Zd ZdefdefdefdefdefgZdS )ObjCBlockStructisaflagsreservedinvoke
descriptorN)r   r   r   r   r   _cfunc_type_block_invoke_fields_rZ   rZ   rZ   r[   r  4      r  c                   @   s.   e Zd ZdefdefdefdefdefgZdS )BlockDescriptorr  sizecopy_helperdispose_helper	signatureN)r   r   r   r   _cfunc_type_block_copy_cfunc_type_block_disposer
   r  rZ   rZ   rZ   r[   r  >  r  r  c                   @   s.   e Zd ZdefdefdefdefdefgZdS )BlockLiteralr  r  r  r  r  N)r   r   r   r   r   r  rZ   rZ   rZ   r[   r  H  r  r  c                 C   sP   dt fdt fg}| r|dtfdtfg |r|dtfg tdtfd|iS )Nr  r  r  r  r  ZObjCBlockDescriptorr  )r   extendr  r  r
   r   r   )has_helpershas_signatureZdescriptor_fieldsrZ   rZ   r[   create_block_descriptor_structR  s   r  c                 C   s"   t | j| j}t| jjjt|S r   )r  r  r  r   structcontentsr  r   )r  Zdescriptor_structrZ   rZ   r[   cast_block_descriptorg  s   r  c                   @   s    e Zd ZdZdZdZdZdZdS )BlockConstsi   i   i   i    i   @N)r   r   r   HAS_COPY_DISPOSEZHAS_CTORZ	IS_GLOBAL	HAS_STRETHAS_SIGNATURErZ   rZ   rZ   r[   r  q  s    r  c                   @   s,   e Zd ZdZefddZdd Zdd ZdS )	r5   al  Python wrapper for an Objective-C block object.

    This class is used to manually wrap an Objective-C block so that it
    can be called from Python. Usually Rubicon will do this
    automatically, if the block object was returned from an Objective-C
    method whose return type is declared to be a block type. If this
    automatic detection fails, for example if the method's return type
    is generic ``id``, Rubicon has no way to tell that the object in
    question is a block rather than a regular Objective-C object. In
    that case, the object needs to be manually wrapped using
    :class:`ObjCBlock`.
    c                 G   s   t |tr|j}|| _t| jtt| _| jjj	t
j@ | _| jjj	t
j@ | _t| | _| jr3| jjjnd| _|tu rQ|r@td| jsGtdt| j^}}g }ntg}t|| _|dd |D  | _dS )a  The constructor takes a block object, which can be either an
        :class:`ObjCInstance`, or a raw :class:`~rubicon.objc.runtime.objc_id` pointer.

        .. note::

            :class:`~rubicon.objc.runtime.objc_block` is also accepted,
            because it is a subclass of :class:`~rubicon.objc.runtime.objc_id`).
            Normally you do not need to make use of this, because in most cases
            Rubicon will automatically convert
            :class:`~rubicon.objc.runtime.objc_block`\s to a callable object.

        In most cases, Rubicon can automatically determine the block's return
        type and parameter types. If a block object doesn't have return/parameter
        type information at runtime, Rubicon will raise an error when attempting
        to convert it. In that case, you need to explicitly pass the correct
        return type and parameter types to :class:`ObjCBlock` using the
        ``restype`` and ``argtypes`` parameters.
        Nz%Cannot use argtypes with restype AUTOz3Cannot use AUTO types for blocks without signaturesc                 S   r  rZ   r&   )r   Zarg_typerZ   rZ   r[   r    s    z&ObjCBlock.__init__.<locals>.<listcomp>)r   r7   r   pointerr   r   r  r  r  r  r  r  r  r  r  r  r  r  AUTOr   r'   r   r&   invoke_restypeinvoke_argtypes)rx   r  rv   r   Z	block_argrZ   rZ   r[   rz     s*   


zObjCBlock.__init__c                 C   sH   dt t| j }| jr|d7 }| jr|d| jd 7 }|d7 }|S )Nz<ObjCBlock@z,has_helpersz,has_signature:r`  r~   )hexr   r  r  r  r  r   )rx   ZrepresentationrZ   rZ   r[   r     s   zObjCBlock.__repr__c              
   G   s   t | jdd D ]N\}}t|| trWt|trWt|ddrWdd |jD }dd || jD }||krLtd| d	|d  d
t|| j	 d| t|| | j|d < q	| j
jj}| j|_| j|_|| jg|R  S )zInvoke the block object with the given arguments.

        The arguments and return value are converted from/to Python
        objects according to the default ``ctypes`` rules, based on the
        block's return and parameter types.
        r   NZ__anonymous__Fc                 S      g | ]}|d  qS r   rZ   r   rl   rZ   rZ   r[   r    r  z&ObjCBlock.__call__.<locals>.<listcomp>c                 S   r  r  rZ   r  rZ   rZ   r[   r    r  z$Expected structure with field types z for argument z; got z with field types )	enumerater  r   r   r   getattrr  r   r   r   r  r  r  r  rv   r   r  )rx   rj   rE  r   Zanon_fieldsZ
arg_fieldsr  rZ   rZ   r[   r     s2   

zObjCBlock.__call__N)r   r   r   r   r  rz   r   r   rZ   rZ   rZ   r[   r5   y  s
    6	r5   c                   @   s   e Zd Zdd ZdS )r  c                 G   s
   | j | S r   )r  )rx   rj   rZ   rZ   r[   r     r   zObjCBlockInstance.__call__N)r   r   r   r   rZ   rZ   rZ   r[   r    s    r      _NSConcreteStackBlockc                   @   s8   e Zd ZdZi ZefddZdd Zdd Zdd	 Z	d
S )r*   zA wrapper that exposes a Python callable object to Objective-C as a block.

    .. note::

        :class:`Block` instances are currently *not* callable from Python,
        unlike :class:`ObjCBlock`.
    c           
      G   s  t |std|| _|tu rs|rtdzt|}t|}W n ttfy4 } ztd|d}~ww z|d }W n t	yL } ztd|d}~ww g }|j
D ] }z	|||  W qR t	yr } z	td|d|d}~ww td	d
 |D }t|}t|tg|R  }t | _tt| j_tjtjB tjB | j_d| j_|| j}	t|	t| j_t | _d| j_t t| j_!t"| j#| _$t%| j&| _'| j$| j_#| j'| j_&t(|d d)dd
 |D  | j_tt*| jt| j_tt*| jt+| _,| j,| _-dS )a  The constructor accepts any Python callable object.

        If the callable has parameter and return type annotations, they are used
        as the block's parameter and return types. This allows using
        :class:`Block` as a decorator:

        .. code-block:: python

            @Block
            def the_block(arg: NSInteger) -> NSUInteger:
                return abs(arg)

        For callables without type annotations, the parameter and return types
        need to be passed to the :class:`Block` constructor in the ``restype``
        and ``argtypes`` arguments:

        .. code-block:: python

            the_block = Block(abs, NSUInteger, NSInteger)
        zBlocks must be callablez&Cannot pass argtypes without a restypezmCould not retrieve function signature information - please pass return and argument types directly into BlockNrN   znFunction has no return type annotation - please add one, or pass return and argument types directly into Blockz7Function has no argument type annotation for parameter zH - please add one, or pass return and argument types directly into Blockc                 s       | ]}t |V  qd S r   r  r   rZ   rZ   r[   r   J	      z!Block.__init__.<locals>.<genexpr>r   s   @?r   c                 s   r  r   )r(   )r   r   rZ   rZ   r[   r   f	  r  ).r   r   funcNOTHINGr   rg   rh   rd   r  r   
parametersrk   r`   r&   r   r   r  literalr   r  r  r  r  r  r  r  r  r:  r   r  r  r  r   r  r  r  Zcfunc_copy_helperr  r  Zcfunc_dispose_helperr(   r   r   r   r  r  )
rx   r  rv   r   rn   r  r\  r]   Z
cfunc_typeZcfunc_wrapperrZ   rZ   r[   rz   
	  s   




zBlock.__init__c                 G   s
   | j | S r   )r  )rx   r  rj   rZ   rZ   r[   r:  l	  s   
zBlock.wrapperc                 C   s   t j|d  d S r   )r*   _keep_alive_blocks_r  )rx   dstrZ   rZ   r[   r  r	  s   zBlock.dispose_helperc                 C   s   | t j|< d S r   )r*   r  )rx   r  srcrZ   rZ   r[   r  u	  s   	zBlock.copy_helperN)
r   r   r   r   r  r  rz   r:  r  r  rZ   rZ   rZ   r[   r*     s    br*   r  )qcollections.abcr   r  r   rd   r=  rg   r   ctypesr   r   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   Zruntimer   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r   r%   r&   r'   r(   r)   __all__r  rT   r!  r\   r`   rc   rq   rr   r   r   r   rB   r?   rA   rC   rD   r
  rG   rF   rH   r=   r<   r7   r   r6   r8   r2   rs  r1   r-   r4   r,   r+   r/   r.   r0   r:   rE   r>   r;   r9   r3   r5  r  r@   r  r  r  r  r  r  r  r  r   r  r  r5   r  r  r  r  r*   rZ   rZ   rZ   r[   <module>   s    PH%
 71( 1($
  f   u
(



>F  




{