o
    dB                     @  s   d dl mZ d dlmZmZ d dlZd dlZd dlmZm	Z	m
Z
 d dlZd dlmZ d dlmZmZ d dlZd dlmZ d3ddZ			 	d4d5ddZd6ddZd7dd Z	d8d9d$d%Z					&		d:d;d1d2ZdS )<    )annotations)abcdefaultdictN)AnyDefaultDictIterableconvert_json_to_lines)IgnoreRaiseScalar)	DataFramesstrreturnc                 C  s0   | d dks| d dkr| S | dd } t | S )zJ
    Helper function that converts JSON lists to line delimited JSON.
    r   []   r   )r    r   M/app/.heroku/python/lib/python3.10/site-packages/pandas/io/json/_normalize.pyconvert_to_line_delimits   s   r    .prefixseplevelint	max_level
int | Nonec              
   C  s   d}t | tr| g} d}g }| D ]X}t|}| D ]G\}	}
t |	ts(t|	}	|dkr/|	}n|| |	 }t |
trB|durP||krP|dkrO||	}
|
||< q||	}
|t|
|||d | q|	| q|ro|d S |S )a  
    A simplified json_normalize

    Converts a nested dict into a flat dict ("record"), unlike json_normalize,
    it does not attempt to extract a subset of the data.

    Parameters
    ----------
    ds : dict or list of dicts
    prefix: the prefix, optional, default: ""
    sep : str, default '.'
        Nested records will generate names separated by sep,
        e.g., for sep='.', { 'foo' : { 'bar' : 0 } } -> foo.bar
    level: int, optional, default: 0
        The number of levels in the json string.

    max_level: int, optional, default: None
        The max depth to normalize.

    Returns
    -------
    d - dict or list of dicts, matching `ds`

    Examples
    --------
    >>> nested_to_record(
    ...     dict(flat1=1, dict1=dict(c=1, d=2), nested=dict(e=dict(c=1, d=2), d=2))
    ... )
    {'flat1': 1, 'dict1.c': 1, 'dict1.d': 2, 'nested.e.c': 1, 'nested.e.d': 2, 'nested.d': 2}
    FTr   Nr   )

isinstancedictcopydeepcopyitemsr   popupdatenested_to_recordappend)dsr   r   r   r   Z	singletonZnew_dsdZnew_dkvZnewkeyr   r   r   r&   *   s8   ,





r&   datar   
key_stringnormalized_dictdict[str, Any]	separatorc                 C  s|   t | tr8|  D ],\}}| | | }|s-tjdk r(ddlm} |||}n||}t||||d q	|S | ||< |S )a3  
    Main recursive function
    Designed for the most basic use case of pd.json_normalize(data)
    intended as a performance improvement, see #15621

    Parameters
    ----------
    data : Any
        Type dependent on types contained within nested Json
    key_string : str
        New key (with separator(s) in) for data
    normalized_dict : dict
        The new normalized/flattened Json dict
    separator : str, default '.'
        Nested records will generate names separated by sep,
        e.g., for sep='.', { 'foo' : { 'bar' : 0 } } -> foo.bar
    )   	   r   )removeprefixr,   r-   r.   r0   )r   r    r#   sysversion_infoZpandas.util._str_methodsr3   _normalise_json)r,   r-   r.   r0   keyvalueZnew_keyr3   r   r   r   r7   {   s"   


r7   c                 C  s<   dd |   D }tdd |   D di |d}i ||S )aw  
    Order the top level keys and then recursively go to depth

    Parameters
    ----------
    data : dict or list of dicts
    separator : str, default '.'
        Nested records will generate names separated by sep,
        e.g., for sep='.', { 'foo' : { 'bar' : 0 } } -> foo.bar

    Returns
    -------
    dict or list of dicts, matching `normalised_json_object`
    c                 S  s    i | ]\}}t |ts||qS r   r   r    .0r*   r+   r   r   r   
<dictcomp>        z+_normalise_json_ordered.<locals>.<dictcomp>c                 S  s    i | ]\}}t |tr||qS r   r:   r;   r   r   r   r=      r>   r   r4   )r#   r7   )r,   r0   Z	top_dict_Znested_dict_r   r   r   _normalise_json_ordered   s   r?   r(   dict | list[dict]dict | list[dict] | Anyc                   sB   i }t | trt|  d}|S t | tr fdd| D }|S |S )a  
    A optimized basic json_normalize

    Converts a nested dict into a flat dict ("record"), unlike
    json_normalize and nested_to_record it doesn't do anything clever.
    But for the most basic use cases it enhances performance.
    E.g. pd.json_normalize(data)

    Parameters
    ----------
    ds : dict or list of dicts
    sep : str, default '.'
        Nested records will generate names separated by sep,
        e.g., for sep='.', { 'foo' : { 'bar' : 0 } } -> foo.bar

    Returns
    -------
    frame : DataFrame
    d - dict or list of dicts, matching `normalised_json_object`

    Examples
    --------
    >>> _simple_json_normalize(
    ...     {
    ...         "flat1": 1,
    ...         "dict1": {"c": 1, "d": 2},
    ...         "nested": {"e": {"c": 1, "d": 2}, "d": 2},
    ...     }
    ... )
    {'flat1': 1, 'dict1.c': 1, 'dict1.d': 2, 'nested.e.c': 1, 'nested.e.d': 2, 'nested.d': 2}

    )r,   r0   c                   s   g | ]}t | d qS )r   )_simple_json_normalize)r<   rowrB   r   r   
<listcomp>   s    z*_simple_json_normalize.<locals>.<listcomp>)r   r    r?   list)r(   r   Znormalised_json_objectZnormalised_json_listr   rB   r   rC      s   +

rC   raiserecord_pathstr | list | Nonemeta"str | list[str | list[str]] | Nonemeta_prefix
str | Nonerecord_prefixerrorsr
   r   c                   s  	d$d%fd
dd&fddt | tr| st S t | tr#| g} nt | tjr3t | ts3t| } nt|du rQ|du rQ|du rQ	du rQdu rQtt| dS |du rit	dd | D ret
| d} t| S t |tsq|g}|du rxg }nt |ts|g}dd |D  g 
g ttfdd D d'd( 
f
dd| |i dd t
}	dur|j	fddd } D ]$\}	}
|dur||	 }	|	|v rtd!|	 d"tj|
td#||	< q|S ))a  
    Normalize semi-structured JSON data into a flat table.

    Parameters
    ----------
    data : dict or list of dicts
        Unserialized JSON objects.
    record_path : str or list of str, default None
        Path in each object to list of records. If not passed, data will be
        assumed to be an array of records.
    meta : list of paths (str or list of str), default None
        Fields to use as metadata for each record in resulting table.
    meta_prefix : str, default None
        If True, prefix records with dotted (?) path, e.g. foo.bar.field if
        meta is ['foo', 'bar'].
    record_prefix : str, default None
        If True, prefix records with dotted (?) path, e.g. foo.bar.field if
        path to records is ['foo', 'bar'].
    errors : {'raise', 'ignore'}, default 'raise'
        Configures error handling.

        * 'ignore' : will ignore KeyError if keys listed in meta are not
          always present.
        * 'raise' : will raise KeyError if keys listed in meta are not
          always present.
    sep : str, default '.'
        Nested records will generate names separated by sep.
        e.g., for sep='.', {'foo': {'bar': 0}} -> foo.bar.
    max_level : int, default None
        Max number of levels(depth of dict) to normalize.
        if None, normalizes all levels.

    Returns
    -------
    frame : DataFrame
    Normalize semi-structured JSON data into a flat table.

    Examples
    --------
    >>> data = [
    ...     {"id": 1, "name": {"first": "Coleen", "last": "Volk"}},
    ...     {"name": {"given": "Mark", "family": "Regner"}},
    ...     {"id": 2, "name": "Faye Raker"},
    ... ]
    >>> pd.json_normalize(data)
        id name.first name.last name.given name.family        name
    0  1.0     Coleen      Volk        NaN         NaN         NaN
    1  NaN        NaN       NaN       Mark      Regner         NaN
    2  2.0        NaN       NaN        NaN         NaN  Faye Raker

    >>> data = [
    ...     {
    ...         "id": 1,
    ...         "name": "Cole Volk",
    ...         "fitness": {"height": 130, "weight": 60},
    ...     },
    ...     {"name": "Mark Reg", "fitness": {"height": 130, "weight": 60}},
    ...     {
    ...         "id": 2,
    ...         "name": "Faye Raker",
    ...         "fitness": {"height": 130, "weight": 60},
    ...     },
    ... ]
    >>> pd.json_normalize(data, max_level=0)
        id        name                        fitness
    0  1.0   Cole Volk  {'height': 130, 'weight': 60}
    1  NaN    Mark Reg  {'height': 130, 'weight': 60}
    2  2.0  Faye Raker  {'height': 130, 'weight': 60}

    Normalizes nested data up to level 1.

    >>> data = [
    ...     {
    ...         "id": 1,
    ...         "name": "Cole Volk",
    ...         "fitness": {"height": 130, "weight": 60},
    ...     },
    ...     {"name": "Mark Reg", "fitness": {"height": 130, "weight": 60}},
    ...     {
    ...         "id": 2,
    ...         "name": "Faye Raker",
    ...         "fitness": {"height": 130, "weight": 60},
    ...     },
    ... ]
    >>> pd.json_normalize(data, max_level=1)
        id        name  fitness.height  fitness.weight
    0  1.0   Cole Volk             130              60
    1  NaN    Mark Reg             130              60
    2  2.0  Faye Raker             130              60

    >>> data = [
    ...     {
    ...         "state": "Florida",
    ...         "shortname": "FL",
    ...         "info": {"governor": "Rick Scott"},
    ...         "counties": [
    ...             {"name": "Dade", "population": 12345},
    ...             {"name": "Broward", "population": 40000},
    ...             {"name": "Palm Beach", "population": 60000},
    ...         ],
    ...     },
    ...     {
    ...         "state": "Ohio",
    ...         "shortname": "OH",
    ...         "info": {"governor": "John Kasich"},
    ...         "counties": [
    ...             {"name": "Summit", "population": 1234},
    ...             {"name": "Cuyahoga", "population": 1337},
    ...         ],
    ...     },
    ... ]
    >>> result = pd.json_normalize(
    ...     data, "counties", ["state", "shortname", ["info", "governor"]]
    ... )
    >>> result
             name  population    state shortname info.governor
    0        Dade       12345   Florida    FL    Rick Scott
    1     Broward       40000   Florida    FL    Rick Scott
    2  Palm Beach       60000   Florida    FL    Rick Scott
    3      Summit        1234   Ohio       OH    John Kasich
    4    Cuyahoga        1337   Ohio       OH    John Kasich

    >>> data = {"A": [1, 2]}
    >>> pd.json_normalize(data, "A", record_prefix="Prefix.")
        Prefix.0
    0          1
    1          2

    Returns normalized data with columns prefixed with the given string.
    Fjsr/   spec
list | strextract_recordboolr   Scalar | Iterablec              
     s   | }z t |tr|D ]}|du rt||| }q
W |S || }W |S  tyR } z$|r5td| d| dkrBtjW  Y d}~S td| d| d|d}~ww )zInternal function to pull fieldNzKey zS not found. If specifying a record_path, all elements of data should have the path.ignorez) not found. To replace missing values of z% with np.nan, pass in errors='ignore')r   rF   KeyErrornpnan)rP   rQ   rS   resultfielde)rO   r   r   _pull_field  s6   



z#json_normalize.<locals>._pull_fieldrF   c                   sH    | |dd}t |ts"t|rg }|S t|  d| d| d|S )z
        Internal function to pull field for records, and similar to
        _pull_field, but require to return list. And will raise error
        if has non iterable value.
        T)rS   z has non list value z
 for path z. Must be list or null.)r   rF   pdZisnull	TypeError)rP   rQ   rZ   )r]   r   r   _pull_records  s   

z%json_normalize.<locals>._pull_recordsNrB   c                 s  s"    | ]}d d |  D V  qdS )c                 S  s   g | ]}t |tqS r   r:   )r<   xr   r   r   rE         z,json_normalize.<locals>.<genexpr>.<listcomp>N)values)r<   yr   r   r   	<genexpr>  s     z!json_normalize.<locals>.<genexpr>r   r   c                 S  s    g | ]}t |tr|n|gqS r   )r   rF   )r<   mr   r   r   rE     r>   z"json_normalize.<locals>.<listcomp>c                   s   g | ]}  |qS r   )join)r<   valrB   r   r   rE     rb   r   r   r   Nonec           	        s  t | tr| g} t|dkrB| D ]/}t D ]\}}|d t|kr,||d ||< q||d  |dd  ||d d qd S | D ]F}||d }	fdd|D }t| t D ]!\}}|d t|krt|| }n	|||d  }| | qc| qDd S )Nr   r   r   r   c                   s(   g | ]}t |trt| d n|qS )rf   )r   r    r&   )r<   r)r   r   r   r   rE     s    z>json_normalize.<locals>._recursive_extract.<locals>.<listcomp>)r   r    lenzipr'   extend)	r,   pathZ	seen_metar   objri   r8   ZrecsZmeta_val)
_metar]   r`   _recursive_extractlengthsr   	meta_keys	meta_valsrecordsr   r   r   rs     s.   
&
z*json_normalize.<locals>._recursive_extractrk   c                   s     |  S )Nr   )ra   )rN   r   r   <lambda>  s    z json_normalize.<locals>.<lambda>)columnszConflicting metadata name z, need distinguishing prefix )Zdtype)F)rP   r/   rQ   rR   rS   rT   r   rU   )rP   r/   rQ   rR   r   rF   )r   )r   r   r   rj   )r   rF   r   r    r   r   r   NotImplementedErrorrC   anyr&   r   renamer#   
ValueErrorrX   arrayobjectrepeat)r,   rH   rJ   rL   rN   rO   r   r   rZ   r*   r+   r   )rr   r]   r`   rs   rO   rt   r   ru   rv   rN   rw   r   r   json_normalize   sf    



"
r   )r   r   r   r   )r   r   r   N)r   r   r   r   r   r   r   r   )
r,   r   r-   r   r.   r/   r0   r   r   r/   )r,   r/   r0   r   r   r/   )r   )r(   r@   r   r   r   rA   )NNNNrG   r   N)r,   r@   rH   rI   rJ   rK   rL   rM   rN   rM   rO   r
   r   r   r   r   r   r   )
__future__r   collectionsr   r   r!   r5   typingr   r   r   numpyrX   Zpandas._libs.writersr	   Zpandas._typingr
   r   Zpandasr^   r   r   r&   r7   r?   rC   r   r   r   r   r   <module>   s8   

Q
.7