
    >i                    v    d Z ddlmZ ddlmZmZ ddlmZmZ ddl	m
Z
 ddlmZmZ  G d de      Z	 	 	 	 dd	Zy
)z;ExtractionModel base class for declarative data extraction.    )annotations)ClassVarOptional)	BaseModel
ConfigDict)InvalidExtractionModel)ExtractionMetadatapop_field_metadatac                  D    e Zd ZU dZdZded<    ed      Zedd       Z	y)	ExtractionModela~  Base class for declarative extraction models.

    Inherits from pydantic.BaseModel, gaining automatic validation,
    type coercion, serialization (model_dump, model_dump_json), and
    JSON Schema generation (model_json_schema).

    Subclasses define fields using Field() descriptors with selectors
    and/or semantic descriptions. The extraction engine uses this
    metadata to extract structured data from web pages.

    Example::

        class Article(ExtractionModel):
            title: str = Field(selector='h1', description='Article title')
            author: str = Field(selector='.author', description='Author name')
    Nz1ClassVar[Optional[dict[str, ExtractionMetadata]]]_extraction_fields_cacheT)arbitrary_types_allowedc                h    | j                   j                  d      }||S t        |       }|| _        |S )a  Get extraction metadata for all fields, collecting lazily on first access.

        Each subclass gets its own cache, even if a parent class has already
        been collected. This ensures inherited fields are included correctly.

        Returns:
            Dictionary mapping field name to ExtractionMetadata.

        Raises:
            InvalidExtractionModel: If a field has metadata but lacks
                both selector and description.
        r   )__dict__get_collect_extraction_metadatar   )cls	own_cacheresults      \/var/www/python/tenders/Scrapper/venv/lib/python3.12/site-packages/pydoll/extractor/model.pyget_extraction_fieldsz%ExtractionModel.get_extraction_fields#   s<     LL$$%?@	 -c2'-$    )returndict[str, ExtractionMetadata])
__name__
__module____qualname____doc__r   __annotations__r   model_configclassmethodr    r   r   r   r      s3    " SWOVd;L r   r   c                @   i }| j                   j                         D ]~  \  }}|j                  }t        |t              s#|j                  d      }t        |t              sEt        |      }|S|j                  s|j                  st        d| d      |||<    |S )a  Read ExtractionMetadata from pydantic FieldInfo objects via registry.

    For each field, checks if json_schema_extra contains an _extraction_key
    that maps to a registered ExtractionMetadata. Validates that each
    extraction field has at least a selector or a description.

    Args:
        cls: ExtractionModel subclass to inspect.

    Returns:
        Dictionary mapping field name to ExtractionMetadata.

    Raises:
        InvalidExtractionModel: If a field has metadata but lacks
            both selector and description.
    _extraction_keyzField "z0" must have at least a selector or a description)model_fieldsitemsjson_schema_extra
isinstancedictr   intr
   has_selectordescriptionr   )r   r   name
field_infoextrakeymetadatas          r   r   r   ;   s    & -/F,,224  j,,%&ii)*#s#%c*$$Z-C-C($OP   t% & Mr   N)r   ztype[ExtractionModel]r   r   )r   
__future__r   typingr   r   pydanticr   r   pydoll.extractor.exceptionsr   pydoll.extractor.fieldr	   r
   r   r   r"   r   r   <module>r7      s9    A " % * > I+i +\'	'"'r   