
    K:gD              	          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 d dl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 d dlZd dlmZmZmZ d dlmZm Z m!Z! erd dl"m#Z#  ed      Z$ ed	d
      Z% ed      Z& edd
      Z' ededef         Z(dede)fdZ*de)defdZ+deeef   de)fdZ,de)defdZ-dAde)de)de fdZ.dee&   de/deee&      fdZ0dAdede)de1fdZ2 e	e2d !      Z3 e	e2d"!      Z4 e	e2d#!      Z5 e	e2d$!      Z6 e	e2d%!      Z7dBd&e1d'e(de(fd(Z8d
d)d*ed+e)d,e1ddfd-Z9d
d)d*ed+e)d,e1ddfd.Z:dAd*ed/e)dee(ge(f   fd0Z; G d1 d2eee'e%f         Z<d3ee'ge%f   de<e'e%f   fd4Z=dedee)   fd5Z>deee)ee)   f      dee)   fd6Z?d7d8d9e)d:ee1ee)   f   deegef   fd;Z@ G d< d=e)      ZA G d> d?      ZBg d@ZCy)C    N)datedatetime)partialwraps)TYPE_CHECKINGAnyCallableDictGenericIterableIteratorListOptionalSequenceTypeVarUnioncast)	ParamSpecProtocolSelf)AnyRecordDictCreateAttachmentByUrl
FieldValueApiPRT)	covariantTC)contravariantF.)boundvaluereturnc                 F    | j                  d      j                  dd      S )z
    Convert ``datetime`` object into Airtable compatible ISO 8601 string
    e.g. "2014-09-05T12:34:56.000Z"

    Args:
        value: datetime object
    milliseconds)timespec+00:00Z)	isoformatreplacer$   s    M/var/www/html/lionshead/venv/lib/python3.12/site-packages/pyairtable/utils.pydatetime_to_iso_strr/   (   s"     ??N?3;;HcJJ    c                 ^    | j                  d      r| dd dz   } t        j                  |       S )z
    Convert an ISO 8601 datetime string into a ``datetime`` object.

    Args:
        value: datetime string, e.g. "2014-09-05T07:00:00.000Z"
    r*   Nr)   )endswithr   fromisoformatr-   s    r.   datetime_from_iso_strr5   3   s1     ~~ccr
X%!!%((r0   c                 $    | j                  d      S )z
    Convert a ``date`` or ``datetime`` into an Airtable-compatible ISO 8601 string

    Args:
        value: date or datetime object, e.g. "2014-09-05"
    %Y-%m-%d)strftimer-   s    r.   date_to_iso_strr9   ?   s     >>*%%r0   c                 J    t        j                  | d      j                         S )zw
    Convert ISO 8601 date string into a ``date`` object.

    Args:
        value: date string, e.g. "2014-09-05"
    r7   )r   strptimer   r-   s    r.   date_from_iso_strr<   I   s      UJ/4466r0   urlfilenamec                 P    t        j                  dt        d       |sd| iS | |dS )a  
    Build a ``dict`` in the expected format for creating attachments.

    When creating an attachment, ``url`` is required, and ``filename`` is optional.
    Airtable will download the file at the given url and keep its own copy of it.
    All other attachment object properties will be generated server-side soon afterward.

    Note:
        Attachment field values **must** be an array of
        :class:`~pyairtable.api.types.AttachmentDict` or
        :class:`~pyairtable.api.types.CreateAttachmentByUrl`;
        it is not valid to pass a single item to the API.

    Usage:
        >>> table = Table(...)
        >>> profile_url = "https://example.com/profile.jpg"
        >>> rec = table.create({"Profile Photo": [attachment(profile_url)]})
        {
            'id': 'recZXOZ5gT9vVGHfL',
            'fields': {
                'attachment': [
                    {
                        'id': 'attu6kbaST3wUuNTA',
                        'url': 'https://content.airtable.com/...',
                        'filename': 'profile.jpg'
                    }
                ]
            },
            'createdTime': '2021-08-21T22:28:36.000Z'
        }


    zXattachment(url, filename) is deprecated; use {'url': url, 'filename': filename} instead.   )
stacklevelr=   r=   r>   )warningswarnDeprecationWarningrB   s     r.   
attachmentrF   S   s2    D MMb
  (E3<OSh-OOr0   iterable
chunk_sizec              #   V   K   t        dt        |       |      D ]  }| |||z      yw)z
    Break a sequence into chunks.

    Args:
        iterable: Any sequence.
        chunk_size: Maximum items to yield per chunk.
    r   N)rangelen)rG   rH   is      r.   chunkedrM   }   s0      1c(mZ0q1z>** 1s   ')prefixc                 h    t        | t              sy|r| j                  |      syt        |       dk(  S )z
    Check whether the given value is an Airtable ID.

    Args:
        value: The value to check.
        prefix: If provided, the ID must have the given prefix.
    F   )
isinstancestr
startswithrK   )r$   rN   s     r.   is_airtable_idrT      s3     eS!e&&v.u:r0   rec)rN   apptblfldusrmodify_docstringwrappedc                T    |rt         d       t        j                         r]t               j	                         D ]1  \  }}t        j
                  |      st         |t        |             3 t        t               S t               dt        dt        dt        f fd       }|S )z
    Wrap a function or method so that if Airtable returns a 404,
    we will annotate the error with a helpful note to the user.
    z|enterprise_only|argskwargsr%   c                      	  | i |S # t         j                  j                  $ rP}|j                  =|j                  j                  dk(  r$g |j
                  dj                   d|_        |d }~ww xY w)Ni  zNOTE: z'() requires an enterprise billing plan.)requests
exceptions	HTTPErrorresponsestatus_coder]   __qualname__)r]   r^   excr[   s      r.   
_decoratedz#enterprise_only.<locals>._decorated   s    	D+F++"",, 	||'CLL,D,D,KXXW1122YZ I	s    A8AA33A8)_prepend_docstring_textinspectisclassvarsitems
isfunctionsetattrenterprise_onlyr   r"   r   r   )r[   rZ   nameobjrg   s   `    r.   ro   ro      s     )<= wg,,.ID#!!#&s';< / Aw
7^	# 	 	 	 	 r0   
skip_emptyrq   textrs   c                    | j                   xs d}|r|sy |j                  d      }t        j                  d|      x}rt	        j
                  ||d         }| d| | _         y N 
z^\s+r   z

)__doc__lstriprematchtextwrapindentrq   rt   rs   dochas_leading_spacess        r.   rh   rh      se    
++
C#
**T
CXXgs333t%7%:;F$se$CKr0   c                    | j                   xs d}|r|sy |j                  d      }t        j                  d|      x}rt	        j
                  ||d         }| d| | _         y rv   )ry   rstripr{   r|   r}   r~   r   s        r.   _append_docstring_textr      se    
++
C#
**T
CXXgs333t%7%:;EdV$CKr0   appendc                 0     dt         dt         f fd}|S )Nfuncr%   c                 F    j                   | _         rt        |        | S N)ry   r   )r   r   rq   s    r.   _wrapperz docstring_from.<locals>._wrapper   s     {{"40r0   )r"   )rq   r   r   s   `` r.   docstring_fromr      s    q Q  Or0   c                   D    e Zd Zdedededef   fdZddded	edefd
Z	y)_FetchMethodinstanceownerr%   .c                      y r    )selfr   r   s      r.   __get__z_FetchMethod.__get__   s    Cr0   Fforcer   r   c                     y r   r   )self_r   r   s      r.   __call__z_FetchMethod.__call__   s    sr0   N)
__name__
__module__re   r    r   r	   r   r   boolr   r   r0   r.   r   r      s2    GG#G(362BG27BaB4BABr0   r   r   c           
      F    d j                    j                  d      rdj                  d      z   t               dddt        dt
        dt        d	t        f fd
       }t
        |j                  d<   t        |d       t        t        t        t        f   |      S )z
    Wrap a method (e.g. ``Base.shares()``) in a decorator that will save
    a memoized version of the return value for future reuse, but will also
    allow callers to pass ``force=True`` to recompute the memoized version.
    ____cached_Fr   r   r   r^   r%   c          	      ~    |st        | d       t        |  | fi |       t        t        t        |             S r   )getattrrn   r   r   )r   r   r^   attrr   s      r.   _innerz#cache_unless_forced.<locals>._inner   s>    GD$-5D$T 4V 45AwtT*++r0   z$Args:
	force: |kwarg_force_metadata|)r   rS   rz   r   r    r   r   r   __annotations__r   r   r   )r   r   r   s   ` @r.   cache_unless_forcedr      s     t}}oDtDKK,,
4[). ,Q ,$ ,# ,! , ,
 '+F7#6#KLQT"F++r0   c                     | | S t        | t              rt        j                  |        | S t        | t        t        f      r| j                         S t        dt        |        d      )z
    Given an input that might be a date or datetime, or an ISO 8601 formatted str,
    convert the value into an ISO 8601 formatted str.
    zcannot coerce z into ISO 8601 str)rQ   rR   r   r4   r   r+   	TypeErrortyper-   s    r.   coerce_iso_strr      s`    
 }%u%%$)*  
nT%[M1CD
EEr0   c                 F    | g S t        | t              r| gS t        |       S )zS
    Given an input that is either a str or an iterable of str, return a list.
    )rQ   rR   listr-   s    r.   coerce_list_strr     s)     }	%w;r0   F)requiredfieldsr   c                 
    t         t              r h n" du rt               n du rg  nt                dt        dt        dt        f fdt              dk(  rt        d   	      S dt        dt        ffd
}|S )a  
    Create a function that extracts ID, created time, or field values from a record.
    Intended to be used in similar situations as
    `operator.itemgetter <https://docs.python.org/3/library/operator.html#operator.itemgetter>`_.

    >>> record = {"id": "rec001", "fields": {"Name": "Alice"}}
    >>> fieldgetter("Name")(record)
    'Alice'
    >>> fieldgetter("id")(record)
    'rec001'
    >>> fieldgetter("id", "Name", "Missing")(record)
    ('rec001', 'Alice', None)

    Args:
        fields: The field names to extract from the record. The values
            ``"id"`` and ``"createdTime"`` are special cased; all other
            values are interpreted as field names.
        required: If True, will raise KeyError if a value is missing.
            If False, missing values will return as None.
            If a sequence of field names is provided, only those names
            will be required.
    TFrecordfieldr%   c                 b    |dv r| n| d   }|v r||vrt        |      |j                  |      S )N)idcreatedTimer   )KeyErrorget)r   r   srcr   s      r.   
_get_fieldzfieldgetter.<locals>._get_field6  s>    !66fF8<LHc!15/!wwu~r0      r   )r   c                 0     t         fdD              S )Nc              3   0   K   | ]  } |        y wr   r   ).0r   r   r   s     r.   	<genexpr>z/fieldgetter.<locals>._getter.<locals>.<genexpr>@  s     CF5Z.Fs   )tuple)r   r   r   s   `r.   _getterzfieldgetter.<locals>._getter?  s    CFCCCr0   )rQ   rR   setr   r   rK   r   r   )r   r   r   r   s   `` @r.   fieldgetterr     s    4 (C :	T	v;	U	x==    6{az33D D# D Nr0   c                        e Zd ZdZdej
                  j                  fdZdef fdZ	de
defdZdee
   defdZd	eee
f   defd
Zdee
   defdZ	 dd	eeee
f      de
defdZde
defdZ xZS )Urlah  
    Wrapper for ``str`` that adds Path-like syntax for extending
    URL components and adding query params.

    >>> url = Url('http://example.com')
    >>> url
    Url('http://example.com')
    >>> url / 'foo' & {'a': 1, 'b': [2, 3, 4]}
    Url('http://example.com/foo?a=1&b=2&b=3&b=4')
    >>> url // [1, 2, 3, 4]
    Url('http://example.com/1/2/3/4')
    r%   c                 @    t         j                  j                  |       S )z
        Shortcut for `urllib.parse.urlparse <https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlparse>`_.
        )urllibparseurlparse)r   s    r.   _parsez
Url._parseS  s     ||$$T**r0   c                 T    | j                   j                   dt        |           dS )N())	__class__r   super__repr__)r   r   s    r.   r   zUrl.__repr__Y  s*    ..))*!EG,<,>+?qAAr0   otherc                 $    | j                  |      S r   add_path)r   r   s     r.   __truediv__zUrl.__truediv__\  s    }}U##r0   othersc                       | j                   | S r   r   )r   r   s     r.   __floordiv__zUrl.__floordiv___  s    t}}f%%r0   paramsc                 $    | j                  |      S r   )add_qs)r   r   s     r.   __and__zUrl.__and__b  s    {{6""r0   c                 T   |st        d      | j                         }|j                  rt        d      |D cg c]  }t	        |       }}|j
                  r+|j                  d|j
                  j                  d             | j                  dj                  |            S c c}w )a  
        Build a copy of this URL with additional path segments.

        >>> url = Url('http://example.com')
        >>> url.add_path("a", "b", "c")
        Url('http://example.com/a/b/c')

        The shorthand ``/`` has the same effect and can be used with a single path segment.
        The shorthand ``//`` can be used with an iterable of path segments.

        >>> url / "a" / "b" / "c"
        Url('http://example.com/a/b/c')
        >>> url // ["a", "b", "c"]
        Url('http://example.com/a/b/c')
        z)add_path() requires at least one argumentz%cannot add path segments after paramsr   /)path)
r   r   query
ValueErrorrR   r   insertr   replace_urljoin)r   r   parsedr   partss        r.   r   zUrl.add_pathe  s      GHH<<DEE)/0U0;;LLFKK..s34SXXe_55 1s   B%other_paramsc                 D   |s|st        d      |i n|}|j                  |       | j                         }t        j                  j                  |j                        }|j                  |       | j                  t        j                  j                  |d            S )ag  
        Build a copy of this URL with additional query parameters.
        The shorthand ``&`` has the same effect.

        >>> url = Url('http://example.com')
        >>> url.add_qs({"a": 1}, b=[2, 3, 4])
        Url('http://example.com?a=1&b=2&b=3&b=4')
        >>> url & {"a": 1, "b": [2, 3, 4]}
        Url('http://example.com?a=1&b=2&b=3&b=4')
        z'add_qs() requires at least one argumentT)doseq)r   )	r   updater   r   r   parse_qsr   r   	urlencode)r   r   r   r   qss        r.   r   z
Url.add_qs  s     ,EFF~6l#\\""6<<0
		&fll&<&<Rt&<&LMMr0   r^   c           	          | j                  t        j                  j                   | j	                         j
                  di |            S )z
        Build a copy of this URL with the given components replaced.

        >>> url = Url('http://example.com')
        >>> url.replace(scheme='https', path='/foo')
        Url('https://example.com/foo')
        r   )r   r   r   
urlunparser   _replace)r   r^   s     r.   r   zUrl.replace_url  s9     ~~fll556Ldkkm6L6L6Vv6VWXXr0   r   )r   r   re   ry   r   r   ParseResultr   rR   r   r   r   r   r   r   r
   r   r   r   r   r   __classcell__r   s   @r.   r   r   E  s    +00 +B# B$ $ $&8C= &T &#d38n # #6 6$ 68 ,0Nc3h(N N 
	N0YC YD Yr0   r   c                   ~     e Zd ZU dZeed<   ded<   ddefdZdeded	efd
Z	ded	df fdZ
eded	dfd       Z xZS )
UrlBuildera|  
    Utility for defining URL patterns within an Airtable API class.
    Each instance of UrlBuilder will inspect its own class attributes
    and modify them to reflect the actual URL that should be used
    based on the context (Table, Base, etc.) provided.

    The pattern for use in pyAirtable is:

    .. code-block:: python

        from functools import cached_property
        from pyairtable.utils import UrlBuilder

        class SomeObject:
            attr1: str
            attr2: int

            class _urls(UrlBuilder):
                url1 = "/path/to/{attr1}"
                url2 = "/path/to/{attr2}"

            urls = cached_property(_urls)

    ...which ensures the URLs are built only once and are accessible via ``.urls``,
    and have the ``SomeObject`` instance available as context, and build
    readable docstrings for the ``SomeObject`` class documentation.

    .. warning::

        This class is intended for use within pyAirtable only, and is tailored
        to the type of documentation this library produces. Its behavior may
        change in the future in ways that are not suitable for other projects.
    contextr   apiNc                    || _         | j                  |      | _        t        | j                        j                         D ]C  \  }}|j                  d      st        |t              s(t        | || j                  |             E y )Nr   )r   	_find_apir   rk   r   rl   rS   rQ   rR   rn   	build_url)r   r   r   r$   s       r.   __init__zUrlBuilder.__init__  sf    >>'*/557KD%s#:eS+AD$u 56 8r0   r$   r^   r%   c                     d|v r8i t        | j                        |d| j                  i}|j                  |      }| j                  j	                  |      S )N{r   )rk   r   
format_mapr   r   )r   r$   r^   r   s       r.   r   zUrlBuilder.build_url  sQ    %<Ldll+LvLvt||LG$$W-Exx!!%((r0   c                    d| j                   vs|j                  dd      rt        
|   di |S 	 t	        d t        |       j                         D              }| j                   j                  dd      d   }| j                  }|j                         j                  dd      }d| d| d	| d
| d| d| d}t        |       j                         D ]H  \  }}| d| j                    d| }	t        |t              r
|d|	 dz  }4t        |      s@|d|	 dz  }J t        | |d       y # t        $ r t        
|   di |cY S w xY w)N.skip_docstringFc              3   H   K   | ]  \  }}t        |t              s|  y wr   )rQ   r   )r   kvs      r.   r   z/UrlBuilder.__init_subclass__.<locals>.<genexpr>  s!     V.?FQ:aQTCUa.?s   ""r   r   r   zURLs associated with :class:`~zf` can be accessed via ``.urls`` using the following syntax:

.. code-block:: python


            >>> z = z(...)
            >>> z.urls.z
            Url('https://api.airtable.com/...')
            

These properties are all instances of :class:`~pyairtable.utils.Url`.z::z

.. autoattribute:: z
    :noindex:z

.. automethod:: rr   r   )re   popr   __init_subclass__nextrk   rl   StopIterationrsplitr   lowerr,   rQ   r   callabler   )clsr^   
sample_urlparent_clsnameparent_modnameparent_varname	docstringrp   rq   qualnamer   s             r.   r  zUrlBuilder.__init_subclass__  s    c&&&&**5Eu*M7,6v66	7Vd3ioo.?VVJ
 ))00a8;'--/77SA,^,<An=M N   N#3 4 zl 3XX 	 c*ID#()C,<,<+=QtfEH#s#6xjPP	#3H:_MM	 + 	sI%@5  	77,6v66	7s   )D. .E	E	c                 v    ddl m} t        ||      r|S t        t        |dd       x}|      r|S t	        d      )Nr   r   r   z=context must be an instance of Api or have an 'api' attribute)pyairtable.api.apir   rQ   r   r   )r   r   r   r   s       r.   r   zUrlBuilder._find_api  s=    *gs#NWWeT::cC@JWXXr0   r   )r   r   re   ry   r   r   r   rR   r   r   r  classmethodr   r   r   s   @r.   r   r     sx     D L	J7 7)s )c )c )&A &A &AP Y Y Y Yr0   r   )rF   r   rM   r   r   r<   r9   r5   r/   r   ro   r   rT   
is_base_idis_field_idis_record_idis_table_id
is_user_idr   r   )rw   )T)Dri   r{   r}   urllib.parser   rC   r   r   	functoolsr   r   typingr   r   r	   r
   r   r   r   r   r   r   r   r   r   r`   typing_extensionsr   r   r   pyairtable.api.typesr   r   r   r  r   r   r   r   r    r"   rR   r/   r5   r9   r<   rF   intrM   r   rT   r  r  r  r  r  ro   rh   r   r   r   r   r   r   r   r   r   __all__r   r0   r.   <module>r      s    	    # $      7 7 Q Q& cNC4 CLCt$CxS)*Kx KC K	) 	) 	)&5x0 &S &7S 7T 7'PC 'P3 'P0E 'PT	+hqk 	+s 	+x7L 	+# s D  ~e4^E2
nU3nU3^E2
T Q Q > HL % %C % %PT % GK % %3 %t %t % S (A362B C8WQT] C,hsAv. ,<13E ,.F# F(3- F8E#x}*<$=> 49  ,1//D(3-'(/ }os"#/dZY# ZYzdY dYNr0   