
    K:gp                         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 d dlm	Z	 d dl
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mZmZmZmZmZmZm Z  d dl!m"Z"m#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-m.Z. d d
l/m0Z0 d dl1m2Z2  G d d      Z3y)    N)cached_property)Path)	TYPE_CHECKINGAnyDictIterableIteratorListOptionalUnionoverload)
	FieldNameRecordDeletedDict
RecordDictRecordIdUpdateRecordDictUploadAttachmentResultDictUpsertResultDictWritableFieldsassert_typed_dictassert_typed_dicts)Formulato_formula_str)FieldSchemaTableSchemaparse_field_schema)Url
UrlBuilderis_table_id)ApiTimeoutTuple)Base)Retryc                      e Zd ZU dZded<   eed<   dZee   ed<    G d de	      Z
 ee
      Zeddd	d
dedededed   ded   defd       Zedddddefd       Zedddddefd       Zdedef   dedef   deeef   defdZdefdZedefd       ZedBdedefd       ZedCd       Zdededefd Zdedeee      fd!Zdedee   fd"Zdedee   fd#Z	 	 dDd%ed&ed'ee   defd(Z 	 	 dDd)e!e   d&ed'ee   dee   fd*Z"	 	 	 dEded%ed+ed&ed'ee   defd,Z#	 	 	 dEd)e!e$   d+ed&ed'ee   dee   f
d-Z%	 	 	 dEd)e!e&eef      d.ee'   d+ed&ed'ee   de(fd/Z)dede*fd0Z+d1e!e   dee*   fd2Z,deded3   fd4Z-ded5edd3fd6Z.d$d7d8edefd9Z/	 	 dFded:ed;ee   dee&eef      de0f
d<Z1	 	 dFded=ed>eee2f   d?eeee3f      d@ee   de4fdAZ5y)GTablez
    Represents an Airtable table.

    Usage:
        >>> api = Api(access_token)
        >>> table = api.table("base_id", "table_name")
        >>> records = table.all()
    r"   basenameN_schemac                   j    e Zd Z ed      Zedz  Z ed      ZdedefdZdedefdZ	dede
defd	Zy
)Table._urlsz{base.id}/{self.id_or_name}listRecordsz4meta/bases/{base.id}/tables/{self.id_or_name}/fields	record_idreturnc                      | j                   |z  S )zA
            URL for a specific record in the table.
            )recordsselfr,   s     Q/var/www/html/lionshead/venv/lib/python3.12/site-packages/pyairtable/api/table.pyrecordzTable._urls.recordG   s     <<)++    c                 *    | j                  |      dz  S )zM
            URL for comments on a specific record in the table.
            comments)r3   r0   s     r2   record_commentszTable._urls.record_commentsM   s     ;;y)J66r4   fieldc                 V    | j                  d| d| d      }|j                  d      S )zc
            URL for uploading an attachment to a specific field in a specific record.
            z
{base.id}//z/uploadAttachmentzcontent.airtable.com)netloc)	build_urlreplace_url)r1   r,   r8   urls       r2   upload_attachmentzTable._urls.upload_attachmentS   s4     ..<	{!E7BS!TUC??*@?AAr4   N)__name__
__module____qualname__r   r/   records_postfieldsr   r3   r7   strr?    r4   r2   _urlsr*   >   sh    34 .KL	,H 	, 	,	7X 	7# 	7	Bx 	B 	B 	Br4   rG   zhttps://api.airtable.com)timeoutretry_strategyendpoint_urlapi_keybase_id
table_namerH   r!   rI   r#   rJ   c                     y NrF   )r1   rK   rL   rM   rH   rI   rJ   s          r2   __init__zTable.__init__\   s     r4   c                      y rO   rF   r1   rK   rL   rM   s       r2   rP   zTable.__init__h        r4   c                      y rO   rF   rR   s       r2   rP   zTable.__init__p   rS   r4   kwargsc           
         t        |t              rmt        |t              r]t        j                  dt        d       t        j                  j                  j                  |fi |}|j                  |      | _        nj|8t        |x}t
        j                  j                  j                        r|| _        n0t        dt        |       dt        |       dt        |       d      t        |t              r|| _        yt        |x}t              r|| _        |j                  | _        yt        dt        |       dt        |       dt        |       d      )a  
        Old style constructor takes ``str`` arguments, and will create its own
        instance of :class:`Api`. This constructor can also be provided with
        keyword arguments to the :class:`Api` class.

        This approach is deprecated, and will likely be removed in the future.

            >>> Table("api_key", "base_id", "table_name", timeout=(1, 1))

        New style constructor has an odd signature to preserve backwards-compatibility
        with the old style (above), requiring ``None`` as the first argument, followed by
        an instance of :class:`Base`, followed by the table name.

            >>> Table(None, base, "table_name")

        These signatures may change in the future. Developers using this library are
        encouraged to not construct Table instances directly, and instead fetch tables
        via :meth:`Api.table() <pyairtable.Api.table>`.
        zPassing API keys or base IDs to pyairtable.Table is deprecated; use Api.table() or Base.table() instead. See https://pyairtable.rtfd.org/en/latest/migrations.html for details.   )category
stacklevelNz6Table() expects (None, Base, str | TableSchema); got (z, ))
isinstancerE   warningswarnDeprecationWarning
pyairtableapir    r&   r"   	TypeErrortyper'   r   r(   )r1   rK   rL   rM   rU   r`   r&   schemas           r2   rP   zTable.__init__x   s1   4 gs#
7C(@MMZ , ..$$((;F;C)DI_GODZ^^=P=P=U=U!VDIgr$w-4
;K:LAO 
 j#&"DI*,k:!DLDIgr$w-4
;K:LAO r4   r-   c                     | j                   rHd| j                  j                  d| j                   j                  d| j                   j                  dS d| j                  j                  d| j                  dS )Nz<Table base=z id=z name=>)r(   r&   idr'   r1   s    r2   __repr__zTable.__repr__   sd    <<!$)),,!1dlloo5Ht||O`O`Nccdeediill-VDII=BBr4   c                 x    t        | j                        r| j                  S | j                         j                  S )aP  
        Get the table's Airtable ID.

        If the instance was created with a name rather than an ID, this property will perform
        an API request to retrieve the base's schema. For example:

        .. code-block:: python

            # This will not create any network traffic
            >>> table = base.table('tbl00000000000123')
            >>> table.id
            'tbl00000000000123'

            # This will fetch schema for the base when `table.id` is called
            >>> table = base.table('Table Name')
            >>> table.id
            'tbl00000000000123'
        )r   r'   rc   rf   rg   s    r2   rf   zTable.id   s,    ( tyy!99{{}r4   quotedc                     | j                   r| j                   j                  n| j                  }|s|}|S t        j                  j                  |d      }|S )a  
        Return the table ID if it is known, otherwise the table name used for the constructor.
        This is the URL component used to identify the table in Airtable's API.

        Args:
            quoted: Whether to return a URL-encoded value.

        Usage:

            >>> table = base.table("Apartments")
            >>> table.id_or_name
            'Apartments'
            >>> table.schema()
            >>> table.id_or_name
            'tblXXXXXXXXXXXXXX'
         )safe)r(   rf   r'   urllibparsequote)r1   rj   values      r2   
id_or_namezTable.id_or_name   sI    $ $(<<TYY# *0););E);)Kr4   c                 .    | j                   j                  S )zS
        The API connection used by the table's :class:`~pyairtable.Base`.
        )r&   r`   rg   s    r2   r`   z	Table.api   s    
 yy}}r4   r,   optionsc                    | j                   j                  r&|j                  d| j                   j                         | j                   j                  | j                  j                  |      |      }t        t        |      S )a  
        Retrieve a record by its ID.

        >>> table.get('recwPQIfs4wKPyc9D')
        {'id': 'recwPQIfs4wKPyc9D', 'fields': {'First Name': 'John', 'Age': 21}}

        Args:
            record_id: |arg_record_id|

        Keyword Args:
            cell_format: |kwarg_cell_format|
            time_zone: |kwarg_time_zone|
            user_locale: |kwarg_user_locale|
            use_field_ids: |kwarg_use_field_ids|
        use_field_ids)rt   )r`   rv   
setdefaultgeturlsr3   r   r   )r1   r,   rt   r3   s       r2   rx   z	Table.get   s]      88!!0F0FGdii..y97K V44r4   c              +     K   t        |j                  d      x}t              rt        |      |d<   | j                  j
                  r&|j                  d| j                  j
                         | j                  j                  d| j                  j                  d| j                  j                  f|      D ]$  }t        t        |j                  dg              & yw)a  
        Iterate through each page of results from `List records <https://airtable.com/developers/web/api/list-records>`_.
        To get all records at once, use :meth:`all`.

        >>> it = table.iterate()
        >>> next(it)
        [{"id": ...}, {"id": ...}, {"id": ...}, ...]
        >>> next(it)
        [{"id": ...}, {"id": ...}, {"id": ...}, ...]
        >>> next(it)
        [{"id": ...}]
        >>> next(it)
        Traceback (most recent call last):
        StopIteration

        Keyword Args:
            view: |kwarg_view|
            page_size: |kwarg_page_size|
            max_records: |kwarg_max_records|
            fields: |kwarg_fields|
            sort: |kwarg_sort|
            formula: |kwarg_formula|
            cell_format: |kwarg_cell_format|
            user_locale: |kwarg_user_locale|
            time_zone: |kwarg_time_zone|
            use_field_ids: |kwarg_use_field_ids|
        formularv   rx   post)methodr>   fallbackrt   r/   N)r[   rx   r   r   r`   rv   rw   iterate_requestsry   r/   rC   r   r   )r1   rt   r{   pages       r2   iteratezTable.iterate   s     8 Y!77gA!/!8GI88!!0F0FGHH--		!!dii445	 . 
D %Z)R1HII
s   CCc                 `     | j                   di |D cg c]  }|D ]  }|  c}}S c c}}w )a  
        Retrieve all matching records in a single list.

        >>> table = api.table('base_id', 'table_name')
        >>> table.all(view='MyView', fields=['ColA', '-ColB'])
        [{'fields': ...}, ...]
        >>> table.all(max_records=50)
        [{'fields': ...}, ...]

        Keyword Args:
            view: |kwarg_view|
            page_size: |kwarg_page_size|
            max_records: |kwarg_max_records|
            fields: |kwarg_fields|
            sort: |kwarg_sort|
            formula: |kwarg_formula|
            cell_format: |kwarg_cell_format|
            user_locale: |kwarg_user_locale|
            time_zone: |kwarg_time_zone|
            use_field_ids: |kwarg_use_field_ids|
        rF   )r   r1   rt   r   r3   s       r2   allz	Table.all&  s4    , $04<<#:'#:N#:4v#:NNNs   *c                     |j                  t        dd              | j                  di |D ]  }|D ]  }|c c S   y)a9  
        Retrieve the first matching record.
        Returns ``None`` if no records are returned.

        This is similar to :meth:`~pyairtable.Table.all`, except
        it sets ``page_size`` and ``max_records`` to ``1``.

        Keyword Args:
            view: |kwarg_view|
            fields: |kwarg_fields|
            sort: |kwarg_sort|
            formula: |kwarg_formula|
            cell_format: |kwarg_cell_format|
            user_locale: |kwarg_user_locale|
            time_zone: |kwarg_time_zone|
            use_field_ids: |kwarg_use_field_ids|
           )	page_sizemax_recordsNrF   )updatedictr   r   s       r2   firstzTable.first>  sC    $ 	taQ78 DLL+7+D  , r4   FrD   typecastrv   c                     || j                   j                  }| j                   j                  | j                  j                  |||d      }t        t        |      S )aa  
        Create a new record

        >>> record = {'Name': 'John'}
        >>> table = api.table('base_id', 'table_name')
        >>> table.create(record)

        Args:
            fields: Fields to insert. Must be a dict with field names or IDs as keys.
            typecast: |kwarg_typecast|
            use_field_ids: |kwarg_use_field_ids|
        rD   r   returnFieldsByFieldIdr>   json)r`   rv   r|   ry   r/   r   r   )r1   rD   r   rv   createds        r2   createzTable.createV  sZ    $   HH22M((--		!! $)6   
 !W55r4   r/   c                 R   g }|| j                   j                  }t        |      }| j                   j                  |      D ]^  }|D cg c]  }d|i }}| j                   j	                  | j
                  j                  |||d      }|t        t        |d         z  }` |S c c}w )a  
        Create a number of new records in batches.

        >>> table.batch_create([{'Name': 'John'}, {'Name': 'Marc'}])
        [
            {
                'id': 'recW9e0c9w0er9gug',
                'createdTime': '2017-03-14T22:04:31.000Z',
                'fields': {'Name': 'John'}
            },
            {
                'id': 'recW9e0c9w0er9guh',
                'createdTime': '2017-03-14T22:04:31.000Z',
                'fields': {'Name': 'Marc'}
            }
        ]

        Args:
            records: Iterable of dicts representing records to be created.
            typecast: |kwarg_typecast|
            use_field_ids: |kwarg_use_field_ids|
        rD   r/   r   r   r   r/   )	r`   rv   listchunkedr|   ry   r/   r   r   )	r1   r/   r   rv   inserted_recordschunkrD   new_recordsresponses	            r2   batch_createzTable.batch_createt  s    8   HH22M w-XX%%g.E<ABE&Hf-EKBxx}}II%%* (-: % H  2:x	?R SS /   Cs   B$replacec                     || j                   j                  }|rdnd}| j                   j                  || j                  j	                  |      |||d      }t        t        |      S )aa  
        Update a particular record ID with the given fields.

        >>> table.update('recwPQIfs4wKPyc9D', {"Age": 21})
        {'id': 'recwPQIfs4wKPyc9D', 'fields': {'First Name': 'John', 'Age': 21}}
        >>> table.update('recwPQIfs4wKPyc9D', {"Age": 22}, replace=True)
        {'id': 'recwPQIfs4wKPyc9D', 'fields': {'Age': 22}}

        Args:
            record_id: |arg_record_id|
            fields: Fields to update. Must be a dict with column names or IDs as keys.
            replace: |kwarg_replace|
            typecast: |kwarg_typecast|
            use_field_ids: |kwarg_use_field_ids|
        putpatchr   r}   r>   r   )r`   rv   requestry   r3   r   r   )r1   r,   rD   r   r   rv   r}   updateds           r2   r   zTable.update  sm    .   HH22M!w((""		  + $)6 # 
 !W55r4   c           	      n   g }|rdnd}|| j                   j                  }t        |      }| j                   j                  |      D ]f  }|D cg c]  }|d   |d   d }	}| j                   j	                  || j
                  j                  |	||d      }
|t        t        |
d         z  }h |S c c}w )	a#  
        Update several records in batches.

        Args:
            records: Records to update.
            replace: |kwarg_replace|
            typecast: |kwarg_typecast|
            use_field_ids: |kwarg_use_field_ids|

        Returns:
            The list of updated records.
        r   r   rf   rD   rf   rD   r   r   r/   )	r`   rv   r   r   r   ry   r/   r   r   )r1   r/   r   r   rv   updated_recordsr}   r   xchunk_recordsr   s              r2   batch_updatezTable.batch_update  s    & !w  HH22M w-XX%%g.EMRSUAdGq{CUMSxx''II%%, (-: ( H 1*hy>QRRO /  Ts   B2
key_fieldsc                    || j                   j                  }t        |      }|D ]R  }d|v rt        |      t        |j	                  dg             z
  }|s2t        d|d|d   j                                |rdnd}g g g d}	| j                   j                  |      D ]  }
|
D cg c]+  }|j                         D ci c]  \  }}|dv s|| c}}- }}}}| j                   j                  || j                  j                  |||d	|id
      }|	d   j                  |d          |	d   j                  |d          |	d   j                  t        t        |d                 |	S c c}}w c c}}}w )a_  
        Update or create records in batches, either using ``id`` (if given) or using a set of
        fields (``key_fields``) to look for matches. For more information on how this operation
        behaves, see Airtable's API documentation for `Update multiple records <https://airtable.com/developers/web/api/update-multiple-records#request-performupsert-fieldstomergeon>`__.

        .. versionadded:: 1.5.0

        Args:
            records: Records to update.
            key_fields: List of field names that Airtable should use to match
                records in the input with existing records on the server.
            replace: |kwarg_replace|
            typecast: |kwarg_typecast|
            use_field_ids: |kwarg_use_field_ids|

        Returns:
            Lists of created/updated record IDs, along with the list of all records affected.
        rf   rD   zmissing z in r   r   )updatedRecordscreatedRecordsr/   r   fieldsToMergeOn)r/   r   r   performUpsertr   r   r   r/   )r`   rv   r   setrx   
ValueErrorkeysr   itemsr   ry   r/   extendr   r   )r1   r/   r   r   r   rv   r3   missingr}   resultr   kvformatted_recordsr   s                  r2   batch_upsertzTable.batch_upsert  s   4   HH22M w- Fv~*oFJJx,D(EEG 8G;d6(;K;P;P;R:U!VWW  "w  $
 XX%%g.E $!#F %+LLNLN&1aa;K6KANL#  ! xx''II%%0 (-:&7%D	 ( 	H #$++H5E,FG#$++H5E,FG9$$":x	/BC# /* ' M!s   +E5
E/E/E5
/E5
c                     t        t        | j                  j                  | j                  j                  |                  S )a  
        Delete the given record.

        >>> table.delete('recwPQIfs4wKPyc9D')
        {'id': 'recwPQIfs4wKPyc9D', 'deleted': True}

        Args:
            record_id: |arg_record_id|

        Returns:
            Confirmation that the record was deleted.
        )r   r   r`   deletery   r3   r0   s     r2   r   zTable.delete=  s3     !HHOODII,,Y78
 	
r4   
record_idsc                     g }t        |      }| j                  j                  |      D ]K  }| j                  j                  | j                  j
                  d|i      }|t        t        |d         z  }M |S )a  
        Delete the given records, operating in batches.

        >>> table.batch_delete(['recwPQIfs4wKPyc9D', 'recwDxIfs3wDPyc3F'])
        [
            {'id': 'recwPQIfs4wKPyc9D', 'deleted': True},
            {'id': 'recwDxIfs3wDPyc3F', 'deleted': True}
        ]

        Args:
            record_ids: Record IDs to delete

        Returns:
            Confirmation that the records were deleted.
        z	records[])paramsr/   )r   r`   r   r   ry   r/   r   r   )r1   r   deleted_recordsr   r   s        r2   batch_deletezTable.batch_deleteO  ss       *%
XX%%j1EXX__TYY%6%6U?S_TF12CVIEVWWO 2 r4   zpyairtable.models.Commentc           
      R   | j                   j                  |      }d| j                   j                  |      i}| j                  j	                  d|      D cg c]B  }|d   D ]8  }t
        j                  j                  j                  || j                  |      : D c}}S c c}}w )aD  
        Retrieve all comments on the given record.

        Usage:
            >>> table = Api.table("appNxslc6jG0XedVM", "tblslc6jG0XedVMNx")
            >>> table.comments("recMNxslc6jG0XedV")
            [
                Comment(
                    id='comdVMNxslc6jG0Xe',
                    text='Hello, @[usrVMNxslc6jG0Xed]!',
                    created_time=datetime.datetime(...),
                    last_updated_time=None,
                    mentioned={
                        'usrVMNxslc6jG0Xed': Mentioned(
                            display_name='Alice',
                            email='alice@example.com',
                            id='usrVMNxslc6jG0Xed',
                            type='user'
                        )
                    },
                    author=Collaborator(
                        id='usr0000pyairtable',
                        email='pyairtable@example.com',
                        name='Your pyairtable access token'
                    )
                )
            ]

        Args:
            record_id: |arg_record_id|
        
record_urlGETr6   context)	ry   r7   r3   r`   r   r_   modelsCommentfrom_api)r1   r,   r>   ctxr   comments         r2   r6   zTable.commentsj  s    @ ii''	2TYY--i89 11%=
=
+ %%..w#.N+ O=
 	
 
s   AB#textc                    | j                   j                  |      }| j                  j                  |d|i      }t        j
                  j                  j                  || j                  d| j                   j                  |      i      S )aI  
        Create a comment on a record.
        See `Create comment <https://airtable.com/developers/web/api/create-comment>`_ for details.

        Usage:
            >>> table = Api.table("appNxslc6jG0XedVM", "tblslc6jG0XedVMNx")
            >>> comment = table.add_comment("recMNxslc6jG0XedV", "Hello, @[usrVMNxslc6jG0Xed]!")
            >>> comment.text = "Never mind!"
            >>> comment.save()
            >>> comment.delete()

        Args:
            record_id: |arg_record_id|
            text: The text of the comment. Use ``@[usrIdentifier]`` to mention users.
        r   r   r   r   )	ry   r7   r`   r|   r_   r   r   r   r3   )r1   r,   r   r>   r   s        r2   add_commentzTable.add_comment  su    ( ii''	288==FD>=:  ((11dhhtyy7G7G	7R(S 2 
 	
r4   forcer   c                    |s| j                   s:| j                  j                  |      j                  | j                        | _         | j                   S )a  
        Retrieve the schema of the current table.

        Usage:
            >>> table.schema()
            TableSchema(
                id='tblslc6jG0XedVMNx',
                name='My Table',
                primary_field_id='fld6jG0XedVMNxFQW',
                fields=[...],
                views=[...]
            )

        Args:
            force: |kwarg_force_metadata|
        r   )r(   r&   rc   tabler'   )r1   r   s     r2   rc   zTable.schema  s?    " 99++%+8>>tyyIDL||r4   
field_typedescriptionc                 v   ||d}|r||d<   |r||d<   | j                   j                  | j                  j                  |      }t	        |      }|j                  | j                   | j                  | j                  xs | d       | j                  r%| j                  j                  j                  |       |S )aF  
        Create a field on the table.

        Usage:
            >>> table.create_field("Attachments", "multipleAttachment")
            FieldSchema(
                id='fldslc6jG0XedVMNx',
                name='Attachments',
                type='multipleAttachment',
                description=None,
                options=MultipleAttachmentsFieldOptions(is_reversed=False)
            )

        Args:
            name: The unique name of the field.
            field_type: One of the `Airtable field types <https://airtable.com/developers/web/api/model/field-type>`__.
            description: A long form description of the table.
            options: Only available for some field types. For more information, read about the
                `Airtable field model <https://airtable.com/developers/web/api/field-model>`__.
        )r'   rb   r   rt   r   )r&   table_schemar   )	r`   r|   ry   rD   r   _set_apir&   r(   append)r1   r'   r   r   rt   r   r   field_schemas           r2   create_fieldzTable.create_field  s    6 ,0"D%0GM"!(GI88==!1!1=@ *(3HH		 $ 4 	 	
 <<LL&&|4r4   r8   filenamecontentcontent_typec                 d   |:t        |d      5 }|j                         }ddd       | j                  |||||      S t        j                  j                  |      }|4t        j                  |      d   x}st        j                  d|       d}| j                  j                  ||      }t        |t              r|j                         n|}||t        j                  |      j!                  d      d}| j"                  j%                  ||      }	t'        t(        |	      S # 1 sw Y   xY w)	a*  
        Upload an attachment to the Airtable API, either by supplying the path to the file
        or by providing the content directly as a variable.

        See `Upload attachment <https://airtable.com/developers/web/api/upload-attachment>`__.

        Usage:
            >>> table.upload_attachment("recAdw9EjV90xbZ", "Attachments", "/tmp/example.jpg")
            {
                'id': 'recAdw9EjV90xbZ',
                'createdTime': '2023-05-22T21:24:15.333134Z',
                'fields': {
                    'Attachments': [
                        {
                            'id': 'attW8eG2x0ew1Af',
                            'url': 'https://content.airtable.com/...',
                            'filename': 'example.jpg'
                        }
                    ]
                }
            }

        Args:
            record_id: |arg_record_id|
            field: The ID or name of the ``multipleAttachments`` type field.
            filename: The path to the file to upload. If ``content`` is provided, this
                argument is still used to tell Airtable what name to give the file.
            content: The content of the file as a string or bytes object. If no value
                is provided, pyAirtable will attempt to read the contents of ``filename``.
            content_type: The MIME type of the file. If not provided, the library will attempt to
                guess the content type based on ``filename``.

        Returns:
            A full list of attachments in the given field, including the new attachment.
        Nrbr   z!Could not guess content-type for zapplication/octet-streamutf8)contentTyper   filer   )openreadr?   ospathbasename	mimetypes
guess_typer\   r]   ry   r[   rE   encodebase64encodebytesdecoder`   r|   r   r   )
r1   r,   r8   r   r   r   fpr>   payloadr   s
             r2   r?   zTable.upload_attachment  s   V ?h%'') &))5(G\  77##H-$-$8$8$B1$EELE A(NO9 ii)))U;&0#&>'.."G' &&w/66v>

 88==7=3 !;XFF+ &%s   D%%D/)T)r-   r    )FN)FFN)NN)6r@   rA   rB   __doc____annotations__rE   r(   r   r   r   rG   r   ry   r   rP   r   r   rh   propertyrf   boolrr   r`   r   r   rx   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r6   r   rc   r   r   r   bytesr   r?   rF   r4   r2   r%   r%   +   s    L I &*GXk")B
 B8 5!D -1,06		 	 		 .)	 !)	 	 	   	     	 5tSy!5 vs{#5 #{*+	5
 5nC# C
  C    .    *  5X 5# 5* 5*&J &J$z2B)C &JPOS OT*%5 O0s x
'; 6 (,	66 6  ~	6
 
6B (,	/ .)/  /   ~	/ 
 
j	/ j (,#6#6 #6 	#6
 #6  ~#6 
#6P (,(*+( ( 	(
  ~( 
j	(\ (,G$sCx.)G OG 	G
 G  ~G 
GR
 
-> 
$x'9 dCT>U 6&
( &
t4O/P &
P

 
 
%	
4 ', t  2 &*,0-- - c]	-
 $sCx.)- 
-h 04&*AGAG AG T	"	AG
 %U
+,AG smAG 
$AGr4   r%   )4r   r   r   urllib.parsern   r\   	functoolsr   pathlibr   typingr   r   r   r   r	   r
   r   r   r   pyairtable.modelsr_   pyairtable.api.typesr   r   r   r   r   r   r   r   r   r   pyairtable.formulasr   r   pyairtable.models.schemar   r   r   pyairtable.utilsr   r   r   pyairtable.api.apir    r!   pyairtable.api.baser"   pyairtable.api.retryingr#   r%   rF   r4   r2   <module>r     sh      	   % 
 
 
    8 Q Q 9 94(-FG FGr4   