Parsers¶
Pipeline¶
A parser pipeline is a sequence of parser steps that process type annotations to produce Narwhals dtypes.
anyschema.parsers.ParserPipeline
¶
A pipeline of parser steps that tries each parser in sequence.
This allows for composable parsing where multiple parsers can be tried until one successfully handles the type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
steps
|
IntoParserPipeline
|
Control how parser steps are configured:
|
'auto'
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If the steps are not a sequence of |
from_auto(steps: ParserStep | Sequence[ParserStep], *more_steps: ParserStep, at_position: int | Literal['auto'] = 'auto') -> Self
classmethod
¶
Create an auto pipeline with custom steps efficiently (no copying needed).
Tip
This is the most efficient way to create a pipeline with custom steps when starting from the auto configuration, as it doesn't need to copy the auto pipeline's steps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
steps
|
ParserStep | Sequence[ParserStep]
|
|
required |
*more_steps
|
ParserStep
|
Additional |
()
|
at_position
|
int | Literal['auto']
|
Position where to insert the step(s). Options:
|
'auto'
|
Returns:
| Type | Description |
|---|---|
Self
|
A new |
Examples:
>>> from anyschema.parsers import ParserPipeline, ParserStep
>>> import narwhals as nw
>>> from anyschema.typing import FieldConstraints, FieldMetadata, FieldType
>>>
>>> class CustomType: ...
>>>
>>> class CustomParserStep(ParserStep):
... def parse(
... self, input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata
... ) -> nw.DType | None:
... return nw.String() if input_type is CustomType else None
>>>
>>> pipeline = ParserPipeline.from_auto(CustomParserStep())
>>>
>>> # Add multiple custom steps
>>> pipeline = ParserPipeline.from_auto(CustomParserStep(), CustomParserStep())
>>>
>>> pipeline.parse(CustomType, constraints=(), metadata={})
String
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata, *, strict: bool = True) -> DType | None
¶
Try each parser in sequence until one succeeds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse. |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type. |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary. |
required |
strict
|
bool
|
Whether or not to raise if unable to parse |
True
|
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType from the first successful parser, or None if no parser succeeded and |
parse_into_field(name: str, input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> AnyField
¶
Parse a field specification into a AnyField object.
This is the recommended method for parsing field specifications at the top level. It wraps the DType parsing with additional field-level information like nullability, uniqueness, and custom metadata.
The metadata dictionary is populated during parsing (e.g., UnionTypeStep sets
{"anyschema": {"nullable": True}} for Optional[T] types), ensuring that forward references
are properly evaluated and avoiding code duplication.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The name of the field. |
required |
input_type
|
FieldType
|
The type to parse. |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type. |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary. This dictionary may be modified during
parsing to add field-level metadata like |
required |
Returns:
| Type | Description |
|---|---|
AnyField
|
A |
Examples:
>>> from anyschema.parsers import make_pipeline
>>> pipeline = make_pipeline()
>>> field = pipeline.parse_into_field("age", int, (), {})
>>> field
AnyField(name='age', dtype=Int64, nullable=False, unique=False, description=None, metadata={})
With nullable=True metadata:
>>> field = pipeline.parse_into_field("email", str, (), {"anyschema": {"nullable": True}})
>>> field.nullable
True
With Optional type (auto-detected as nullable):
with_steps(steps: ParserStep | Sequence[ParserStep], *more_steps: ParserStep, at_position: int | Literal['auto'] = 'auto') -> Self
¶
Create a new pipeline with additional parser step(s) inserted at the specified position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
steps
|
ParserStep | Sequence[ParserStep]
|
|
required |
*more_steps
|
ParserStep
|
Additional |
()
|
at_position
|
int | Literal['auto']
|
Position where to insert the step(s). Options:
|
'auto'
|
Returns:
| Type | Description |
|---|---|
Self
|
A new |
Examples:
>>> from anyschema.parsers import ParserPipeline, ParserStep
>>> import narwhals as nw
>>> from anyschema.typing import FieldConstraints, FieldMetadata, FieldType
>>>
>>> class CustomType: ...
>>>
>>> class CustomParserStep(ParserStep):
... def parse(
... self, input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata
... ) -> nw.DType | None:
... if input_type is CustomType:
... return nw.String()
... return None
>>>
>>> pipeline = ParserPipeline("auto") # Start with auto pipeline
>>>
>>> # Add single custom step
>>> custom_pipeline = pipeline.with_steps(CustomParserStep())
>>>
>>> # Add multiple custom steps at once
>>> custom_pipeline = pipeline.with_steps([CustomParserStep(), CustomParserStep()])
>>>
>>> # Or add at specific position
>>> custom_pipeline = pipeline.with_steps(CustomParserStep(), at_position=0)
>>>
>>> custom_pipeline.parse(CustomType, constraints=(), metadata={})
String
anyschema.parsers.make_pipeline(steps: IntoParserPipeline = 'auto') -> ParserPipeline
¶
Create a ParserPipeline with the specified steps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
steps
|
IntoParserPipeline
|
Control how parser steps are configured:
|
'auto'
|
Returns:
| Type | Description |
|---|---|
ParserPipeline
|
A |
Examples:
>>> from anyschema.parsers import make_pipeline
>>> from anyschema.parsers import PyTypeStep, UnionTypeStep, AnnotatedStep
>>>
>>> pipeline = make_pipeline(steps=[UnionTypeStep(), AnnotatedStep(), PyTypeStep()])
>>> print(pipeline.steps)
(UnionTypeStep, AnnotatedStep, PyTypeStep)
>>> pipeline = make_pipeline(steps="auto")
>>> print(pipeline.steps)
(ForwardRefStep, UnionTypeStep, ..., PydanticTypeStep, SQLAlchemyTypeStep, PyTypeStep)
Raises:
| Type | Description |
|---|---|
TypeError
|
If the steps are not a sequence of |
Parser Steps¶
Parser steps are the building blocks of the type parsing pipeline. Each step handles specific type patterns.
For more details on how these work together, see the parser steps section in the Architecture guide.
anyschema.parsers.ParserStep
¶
Bases: ABC
Abstract base class for parser steps that convert type annotations to Narwhals dtypes.
This class provides a framework for parsing different types of type annotations and converting them into appropriate Narwhals data types. Each concrete parser implementation handles specific type patterns or annotation styles.
Attributes:
| Name | Type | Description |
|---|---|---|
pipeline |
ParserPipeline
|
Property to access the |
Raises:
| Type | Description |
|---|---|
UnavailablePipelineError
|
When accessing pipeline before it's been set. |
TypeError
|
When setting pipeline with an object that's not a ParserPipeline instance. |
Note
Subclasses must implement the parse method to define their specific parsing logic.
Examples:
>>> from typing import get_origin, get_args
>>> import narwhals as nw
>>> from anyschema.parsers import ParserPipeline, ParserStep, PyTypeStep
>>> from anyschema.typing import FieldConstraints, FieldMetadata, FieldType
>>>
>>> class CustomType: ...
>>> class CustomList[T]: ...
>>>
>>> class CustomParserStep(ParserStep):
... def parse(
... self, input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata
... ) -> DType | None:
... if input_type is CustomType:
... return nw.String()
...
... if get_origin(input_type) is CustomList:
... inner = get_args(input_type)[0]
... # Delegate to pipeline for recursion
... inner_dtype = self.pipeline.parse(inner, constraints=constraints, metadata=metadata)
... return nw.List(inner_dtype)
...
... # Return None if we can't handle it
... return None
>>>
>>> pipeline = ParserPipeline(steps=[CustomParserStep(), PyTypeStep()])
>>> pipeline.parse(CustomType, constraints=(), metadata={})
String
>>> pipeline.parse(CustomList[int], constraints=(), metadata={})
List(Int64)
>>> pipeline.parse(CustomList[str], constraints=(), metadata={})
List(String)
pipeline: ParserPipeline
property
writable
¶
Property that returns the parser chain instance.
Returns:
| Name | Type | Description |
|---|---|---|
ParserPipeline |
ParserPipeline
|
The parser chain object used for parsing operations. |
Raises:
| Type | Description |
|---|---|
UnavailablePipelineError
|
If the parser chain has not been initialized
(i.e., |
clone() -> Self
¶
Create a clone of this parser step without a pipeline reference.
This method creates a shallow copy of the step, preserving any internal state (such as configuration parameters) but resetting the pipeline reference to None. This allows the cloned step to be added to a different pipeline without violating the "pipeline can only be set once" constraint.
Returns:
| Type | Description |
|---|---|
Self
|
A new instance of the same parser step class with the same configuration |
Self
|
but without a pipeline reference. |
Examples:
>>> from anyschema.parsers import ParserPipeline, PyTypeStep
>>>
>>> # Create a step and assign it to a pipeline
>>> step = PyTypeStep()
>>> pipeline1 = ParserPipeline([step])
>>>
>>> # Clone the step to use in another pipeline
>>> cloned_step = step.clone()
>>> pipeline2 = ParserPipeline([cloned_step])
>>>
>>> # Both pipelines work independently
>>> pipeline1.parse(int, (), {})
Int64
>>> pipeline2.parse(int, (), {})
Int64
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> DType | None
abstractmethod
¶
Parse a type annotation into a Narwhals dtype.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse (e.g., int, str, list[int], etc.) |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type (e.g., Gt, Le from annotated-types) |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary |
required |
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType if the parser can handle this type, None otherwise. |
The following steps are built-in and come dependency-free.
anyschema.parsers.ForwardRefStep
¶
Bases: ParserStep
Parser for ForwardRef types (string annotations and forward references).
This parser handles type annotations that are forward references (ForwardRef), which occur when using string annotations or referencing types before they're defined.
The parser resolves the ForwardRef to the actual type and delegates to the parser chain.
Initialization can be customized by providing a global and local namespace that will be used to evaluate the forward references when resolving the type. The default namespace is built with common types, yet you can override it with your own types.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
globalns
|
dict[str, Any] | None
|
Global namespace for evaluating forward references. Defaults to a namespace with common types. |
None
|
localns
|
Mapping[str, Any] | None
|
Local namespace for evaluating forward references. Defaults to an empty namespace. |
None
|
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> DType | None
¶
Parse ForwardRef types by resolving them and delegating to the chain.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse (may be a ForwardRef). |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type. |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary. |
required |
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType if this is a ForwardRef that can be resolved, None otherwise. |
anyschema.parsers.UnionTypeStep
¶
Bases: ParserStep
Parser for Union types including Optional.
Handles:
Union[T, None],T | None,Optional[T]- Extracts the non-None type and its metadata for further parsing
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> DType | None
¶
Parse Union types, particularly Optional types.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse. |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type (will be preserved and passed through). |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary (will be preserved and passed through). |
required |
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType by extracting the non-None type and delegating to the chain. |
anyschema.parsers.AnnotatedStep
¶
Bases: ParserStep
Parser for typing.Annotated types.
Handles:
Annotated[T, metadata...]- extracts the type and metadata for further parsing
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> DType | None
¶
Parse Annotated types by extracting the base type and constraints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse. |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type. |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary. |
required |
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType by extracting the base type and delegating to the chain. |
anyschema.parsers.PyTypeStep
¶
Bases: ParserStep
Parser for Python builtin types.
Handles:
int,float,decimal,str,bytes,bool,date,datetime,timedelta,time,object,Enum,Literal- generics:
list[T],Sequence[T],Iterable[T],tuple[T, ...] dict,Mapping[K, V], and typed dictionaries (TypedDict)
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> DType | None
¶
Parse Python type annotations into Narwhals dtypes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse. |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type. |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary. |
required |
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType if this parser can handle the type, None otherwise. |
anyschema.parsers.annotated_types.AnnotatedTypesStep
¶
Bases: ParserStep
Parser for types with annotated_types metadata.
Handles:
- Integer constraints (
Gt,Ge,Lt,Le,Interval) - Type refinement based on metadata
Warning
It requires annotated-types to be installed.
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> DType | None
¶
Parse types with annotated constraints into refined Narwhals dtypes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse. |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type (e.g., Gt, Ge, Lt, Le). |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary (not used in this parser). |
required |
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType if this parser can refine the type based on constraints, None otherwise. |
anyschema.parsers.attrs.AttrsTypeStep
¶
Bases: ParserStep
Parser for attrs-specific types.
Handles:
- attrs classes (Struct types)
Warning
It requires attrs to be installed.
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> DType | None
¶
Parse attrs-specific types into Narwhals dtypes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse. |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type. |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary. |
required |
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType if this parser can handle the type, None otherwise. |
anyschema.parsers.pydantic.PydanticTypeStep
¶
Bases: ParserStep
Parser for Pydantic-specific types.
Handles:
- Pydantic datetime types (
AwareDatetime,NaiveDatetime, etc.) - Pydantic date types (
PastDate,FutureDate) - Pydantic
BaseModel(Struct types)
Warning
It requires pydantic to be installed.
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> DType | None
¶
Parse Pydantic-specific types into Narwhals dtypes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse. |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type. |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary. |
required |
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType if this parser can handle the type, None otherwise. |
anyschema.parsers.sqlalchemy.SQLAlchemyTypeStep
¶
Bases: ParserStep
Parser for SQLAlchemy-specific types.
Handles:
- SQLAlchemy column types (Integer, String, DateTime, etc.)
- SQLAlchemy relationship types
- SQLAlchemy custom types
Warning
It requires sqlalchemy to be installed.
parse(input_type: FieldType, constraints: FieldConstraints, metadata: FieldMetadata) -> DType | None
¶
Parse SQLAlchemy-specific types into Narwhals dtypes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_type
|
FieldType
|
The type to parse. |
required |
constraints
|
FieldConstraints
|
Constraints associated with the type. |
required |
metadata
|
FieldMetadata
|
Custom metadata dictionary. |
required |
Returns:
| Type | Description |
|---|---|
DType | None
|
A Narwhals DType if this parser can handle the type, None otherwise. |