o
    ˳iF                     @   sh
  d Z ddlZddlZddlmZ ddlmZmZmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZ dd	lmZmZ dd
lmZmZmZmZmZ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/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7 ddl8m9Z9m:Z: edZ;edZ<edZ=edZ>edZ?dedefddZ@ededeAdeBeCB eAB ejDB eEB e	B fddZFeFGee@dedeAdeBeCB eAB ejDB fddZHeFGeeFGeeFGeeFGe#eFGe eFGeeFGe"eFGe!e@dedeAdeBfddZHeFGeeFGee@dedeAdeCfddZHeFGee@dedeAdeAfddZHeFGe%e@de%deAdejDfddZHeFGeeFGee@dedeAdeEfd dZHeFGee@dedeAde	fd!dZHeFGe$e@d"e$deAddfd#dZHededeIeEB e	B eB eB eCB eBB eAB eB ejDB deEfd$d%ZJeJGeded&eIdeEfd'dZHeJGeded&eBdeEfd(dZHeJGeded&eBdeEfd)dZHeJGe eJGe"ded&eeBB deEfd*dZHeJGeeJGe!ded&eeBB deEfd+dZHeJGeded&eeBB deEfd,dZHeJGe#de#d&eeBB deEfd-dZHeJGeded&eCdeEfd.dZHeJGeded&eCdeEfd/dZHeJGeded&eAdeEfd0dZHeJGe%de%d&ejDeEB deEfd1dZHeJGeeJGeded&eEdeEfd2dZHeJGeded&e	deEfd3dZHeded4eEdefd5d6ZKeKGeded4eEdeIfd7dZHeKGeeKGeded4eEdeBfd8dZHeKGeeKGe#eKGe eKGe"eKGeeKGe!ded4eEdeBfd9dZHeKGeded4eEdeCfd:dZHeKGeded4eEdeCfd;dZHeKGeded4eEdeAfd<dZHeKGeeKGeeKGe%ded4eEdeEfd=dZHeKGeded>eEde	fd?dZHeKGe$d"e$d>eEddfd@dZHededAedefdBdCZLeLGededAeIdeIfdDdZHeLGeeLGedeeB dAeBdeBfdEdZHeLGededAeeBB deAfdFdZHeLGe#de#dAeBeB deAfdGdZHeLGe dedAeBeB deAfdHdZHeLGe"de"dAeBeB deAfdIdZHeLGeeLGedeeB dAeCdeCfdJdZHeLGededAeAdeAfdKdZHeLGedLed4eEdeAfdMdZHeLGeded4eEdeAfdNdZHeLGededAe	deAfdOdZHeLGe%de%dAejDdeAfdPdZHededAedefdQdRZMeMGededAeIdeIfdSdZHeMGeeMGedeeB dAeBdeBfdTdZHeMGededAeAeBB eB defdUdZHeMGe#de#dAeAeBB eB defdVdZHeMGe dedAeAeBB eB defdWdZHeMGe"de"dAeAeBB eB defdXdZHeMGeeMGedeeB dAeCdeCfdYdZHeMGededAeAdeAfdZdZHeMGedLedAeAeEB deEfd[dZHeMGededAeEeAB deEfd\dZHeMGededAeAde	fd]dZHeMGe%de%dAeAeEB ejDB dejDfd^dZHdS )_a  Utility module for various conversions around PrimitiveType implementations.

This module enables:
    - Converting partition strings to built-in python objects.
    - Converting a value to a byte buffer.
    - Converting a byte buffer to a value.
    - Converting a json-single field serialized field

Note:
    Conversion logic varies based on the PrimitiveType implementation. Therefore conversion functions
    are defined here as generic functions using the @singledispatch decorator. For each PrimitiveType
    implementation, a concrete function is registered for each generic conversion function. For PrimitiveType
    implementations that share the same conversion logic, registrations can be stacked.
    N)Callable)datedatetimetimeDecimal)singledispatch)Struct)Any)UTF8L)
BinaryTypeBooleanTypeDateTypeDecimalType
DoubleType	FixedType	FloatTypeIntegerTypeLongTypePrimitiveType
StringTypeTimestampNanoTypeTimestampTypeTimestamptzNanoTypeTimestamptzTypeTimeTypeUnknownTypeUUIDType	strtobool)date_str_to_daysdate_to_daysdatetime_to_microsdatetime_to_nanosdays_to_datemicros_to_timemicros_to_timestampmicros_to_timestamptztime_str_to_microstime_to_microstimestamp_to_microstimestamptz_to_microsto_human_dayto_human_timeto_human_timestampto_human_timestamptz)decimal_to_bytesunscaled_to_decimalz<?z<iz<qz<fz<dfuncreturnc                    s"   dt dtdB dtf fdd}|S )zHandle cases where partition values are `None` or "__HIVE_DEFAULT_PARTITION__".

    Args:
        func (Callable): A function registered to the singledispatch function `partition_to_py`.
    primitive_type	value_strNr3   c                    s"   |d u rd S |dkrd S  | |S )N__HIVE_DEFAULT_PARTITION__ r4   r5   r2   r7   I/home/ubuntu/.local/lib/python3.10/site-packages/pyiceberg/conversions.pywrapperc   s
   
zhandle_none.<locals>.wrapper)r   strr
   )r2   r;   r7   r9   r:   handle_none\   s   r=   r4   r5   c                 C   s   t d| d|  )zConvert a partition string to a python built-in.

    Args:
        primitive_type (PrimitiveType): An implementation of the PrimitiveType base class.
        value_str (str): A string representation of a partition value.
    zCannot convert 'z' to unsupported type: 	TypeErrorr8   r7   r7   r:   partition_to_pym      r@   c                 C      t |S N)r   r8   r7   r7   r:   _x      rD   c                 C   s6   t | \}}}|dkrtd|  dtt|S )zkConvert a string to an integer value.

    Raises:
        ValueError: If the scale/exponent is not 0.
    r   zHCannot convert partition value, value cannot have fractional digits for z
 partition)r   as_tuple
ValueErrorintfloat)r4   r5   rD   exponentr7   r7   r:   rD   ~   s   c                 C   rB   rC   )rI   rD   r5   r7   r7   r:   rD      s   c                 C      |S rC   r7   rK   r7   r7   r:   rD         c                 C   
   t |S rC   )uuidUUIDrK   r7   r7   r:   rD      s   
c                 C   s
   t |tS rC   )bytesr   rK   r7   r7   r:   rD      s   
c                 C   rB   rC   r   rK   r7   r7   r:   rD      rE   type_c                 C      d S rC   r7   )rR   rD   r7   r7   r:   rD      rM   c                 C   s   t d|  )a2  Convert a built-in python value to bytes.

    This conversion follows the serialization scheme for storing single values as individual binary values
    defined in the Iceberg specification that can be found at
    https://iceberg.apache.org/spec/#appendix-d-single-value-serialization

    Args:
        primitive_type (PrimitiveType): An implementation of the PrimitiveType base class.
        _: The value to convert to bytes (The type of this value depends on which dispatched function is
            used--check dispatchable functions for type hints).
    zscale does not match r>   )r4   rD   r7   r7   r:   to_bytes   s   rT   valuec                 C   s   t |rdS dS )N   r   )_BOOL_STRUCTpackrD   rU   r7   r7   r:   rD      s   c                 C   rN   rC   )_INT_STRUCTrX   rY   r7   r7   r:   rD         
c                 C   rN   rC   )_LONG_STRUCTrX   rY   r7   r7   r:   rD      r[   c                 C      t |tr	t|}t|S rC   )
isinstancer   r"   r\   rX   rY   r7   r7   r:   rD         

c                 C   r]   rC   )r^   r   r#   r\   rX   rY   r7   r7   r:   rD      r_   c                 C   r]   rC   )r^   r   r!   rZ   rX   rY   r7   r7   r:   rD         

c                 C   r]   rC   )r^   r   r)   r\   rX   rY   r7   r7   r:   rD      r`   c                 C   rN   )zConvert a float value into bytes.

    Note: float in python is implemented using a double in C. Therefore this involves a conversion of a 32-bit (single precision)
    float to a 64-bit (double precision) float which introduces some imprecision.
    )_FLOAT_STRUCTrX   rY   r7   r7   r:   rD      s   
c                 C   rN   rC   )_DOUBLE_STRUCTrX   rY   r7   r7   r:   rD     r[   c                 C   s
   | tS rC   )encoder   rY   r7   r7   r:   rD     r[   c                 C   s   t |tr|S |jS rC   )r^   rQ   rY   r7   r7   r:   rD     s   
c                 C   rL   rC   r7   rY   r7   r7   r:   rD     rM   c                 C   sf   |  \}}}tt|}|| jkrtd|  d| t|| jkr/td|  dt| t|S )a  Convert a Decimal value to bytes given a DecimalType instance with defined precision and scale.

    Args:
        primitive_type (DecimalType): A DecimalType instance with precision and scale.
        value (Decimal): A Decimal instance.

    Raises:
        ValueError: If either the precision or scale of `value` does not match that defined in the DecimalType instance.


    Returns:
        bytes: The byte representation of `value`.
    z;Cannot serialize value, scale of value does not match type z: zMCannot serialize value, precision of value is greater than precision of type )rF   absrH   scalerG   len	precisionr0   )r4   rU   rD   digitsrJ   r7   r7   r:   rD     s   
bc                 C   s   t d|  d|)zConvert bytes to a built-in python value.

    Args:
        primitive_type (PrimitiveType): An implementation of the PrimitiveType base class.
        b (bytes): The bytes to convert.
    Cannot deserialize bytes, type  not supported: r>   )r4   ri   r7   r7   r:   
from_bytes4  rA   rl   c                 C   s   t |d dkS Nr   )rW   unpackrD   ri   r7   r7   r:   rD   ?  s   c                 C      t |d S rm   )rZ   rn   ro   r7   r7   r:   rD   D  s   c                 C   rp   rm   )r\   rn   ro   r7   r7   r:   rD   J  s   c                 C   rp   rm   )ra   rn   ro   r7   r7   r:   rD   T     c                 C   rp   rm   )rb   rn   ro   r7   r7   r:   rD   Y  rq   c                 C   s   t |tS rC   )rQ   decoder   ro   r7   r7   r:   rD   ^  rq   c                 C   rL   rC   r7   ro   r7   r7   r:   rD   c     bufc                 C   s   t j|ddd}t|| jS )NbigT)signed)rH   rl   r1   re   )r4   rt   unscaledr7   r7   r:   rD   j  s   c                 C   rS   rC   r7   )rR   rt   r7   r7   r:   rD   p  s   valc                 C   s   t d|  d| )a5  Convert built-in python values into JSON value types.

    https://iceberg.apache.org/spec/#json-single-value-serialization

    Args:
        primitive_type (PrimitiveType): An implementation of the PrimitiveType base class.
        val (Any): The arbitrary built-in value to convert into the right form
    rj   rk   r>   r4   rx   r7   r7   r:   to_jsonu  s   
rz   c                 C   rL   )z4Python bool automatically converts into a JSON bool.r7   rD   rx   r7   r7   r:   rD     rM   c                 C   rL   )z0Python int automatically converts to a JSON int.r7   r{   r7   r7   r:   rD     rs   c                 C      t |tr	t|}t|S zJSON date is string encoded.)r^   r   r!   r,   r{   r7   r7   r:   rD        
c                 C   r|   )zHPython time or microseconds since epoch serializes into an ISO8601 time.)r^   r   r)   r-   r{   r7   r7   r:   rD     r~   c                 C   r|   )zdPython datetime (without timezone) or microseconds since epoch serializes into an ISO8601 timestamp.)r^   r   r"   r.   r{   r7   r7   r:   rD     s   
c                 C   r|   )zaPython datetime (with timezone) or microseconds since epoch serializes into an ISO8601 timestamp.)r^   r   r"   r/   r{   r7   r7   r:   rD     r~   c                 C   rL   )z!Float serializes into JSON float.r7   r{   r7   r7   r:   rD     rs   c                 C   rL   )z*Python string serializes into JSON string.r7   r{   r7   r7   r:   rD     rM   tc                 C   s>   t | t |krtdt |  dt | t|dtS )8Python bytes serializes into hexadecimal encoded string.FixedType has length %, which is different from the value: hex)rf   rG   codecsrc   rr   r   )r   ri   r7   r7   r:   rD     s   c                 C   s   t |dtS )r   r   )r   rc   rr   r   ro   r7   r7   r:   rD     s   c                 C   rB   )af  Python decimal serializes into string.

    Stores the string representation of the decimal value, specifically, for
    values with a positive scale, the number of digits to the right of the
    decimal point is used to indicate scale, for values with a negative scale,
    the scientific notation is used and the exponent must equal the negated scale.
    r<   r{   r7   r7   r:   rD     s   	c                 C   rB   )zSerialize into a JSON string.r   r{   r7   r7   r:   rD     rE   c                 C   s   t d|  dt| )a1  Convert JSON value types into built-in python values.

    https://iceberg.apache.org/spec/#json-single-value-serialization

    Args:
        primitive_type (PrimitiveType): An implementation of the PrimitiveType base class.
        val (Any): The arbitrary JSON value to convert into the right form
    rj   rk   )r?   r<   ry   r7   r7   r:   	from_json  s   
r   c                 C   rL   )z4JSON bool automatically converts into a Python bool.r7   r{   r7   r7   r:   rD     rM   c                 C   rL   )z0JSON int automatically converts to a Python int.r7   r{   r7   r7   r:   rD     rs   c                 C   (   t |tr	t|}t |trt|S |S r}   )r^   r<   r    rH   r$   r{   r7   r7   r:   rD     
   

c                 C   r   )z%JSON ISO8601 string into Python time.)r^   r<   r(   rH   r%   r{   r7   r7   r:   rD     r   c                 C   r   z)JSON ISO8601 string into Python datetime.)r^   r<   r*   rH   r&   r{   r7   r7   r:   rD     r   c                 C   r   r   )r^   r<   r+   rH   r'   r{   r7   r7   r:   rD     r   c                 C   rL   )z,JSON float deserializes into a Python float.r7   r{   r7   r7   r:   rD   $  rs   c                 C   rL   )z,JSON string serializes into a Python string.r7   r{   r7   r7   r:   rD   +  rM   c                 C   sL   t |trt|td}t| t|kr$tdt|  dt| |S )+JSON hexadecimal encoded string into bytes.r   r   r   )r^   r<   r   rr   rc   r   rf   rG   )r   rx   r7   r7   r:   rD   1  s
   
c                 C   s    t |trt|tdS |S )r   r   )r^   r<   r   rr   rc   r   r{   r7   r7   r:   rD   =  s   
c                 C   rB   )z*Convert JSON string into a Python Decimal.r   r{   r7   r7   r:   rD   F  rE   c                 C   s.   t |tr
t|S t |trtj|dS |S )z%Convert JSON string into Python UUID.)rQ   )r^   r<   rO   rP   rQ   r{   r7   r7   r:   rD   L  s
   


)N__doc__r   rO   collections.abcr   r   r   r   decimalr   	functoolsr   structr	   typingr
   pyiceberg.typedefr   r   pyiceberg.typesr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   pyiceberg.utils.datetimer    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   pyiceberg.utils.decimalr0   r1   rW   rZ   r\   ra   rb   r=   r<   rH   rI   rP   rQ   r@   registerrD   boolrT   rl   rz   r   r7   r7   r7   r:   <module>   s^  TH.
(((	
" 
 
 
 
(