call_report.core.FileMetadata#

class call_report.core.FileMetadata(*, name: str, periods: tuple[PeriodRange, ...], file_schema: FieldSchema)[source]#

Bases: object

Cross-time metadata for a single call report file (schedule).

Unlike a per-period layout, this describes a file across its whole known history, including whether its column schema ever changed.

Attributes:
namestr

The file’s identifier, in the source’s own vocabulary (e.g. FCA’s schedule root such as "RCB").

periodstuple[PeriodRange, …]

One or more chronologically ordered, non-overlapping, non-adjacent spans describing when this file was published. More than one span means the file was retired and later reintroduced.

file_schemaFieldSchema

The file’s fields, keyed by name.

Raises:
SchemaError

If periods is empty, or its spans are out of order, overlapping, or adjacent.

Examples

>>> import narwhals as nw
>>> from call_report.core import (
...     FieldAttributes,
...     FieldSchema,
...     FieldVersion,
...     FileMetadata,
...     PeriodRange,
... )
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> uninum = FieldAttributes(
...     name="UNINUM",
...     versions=(FieldVersion(dtype=nw.Int64(), definition="", periods=span),),
... )
>>> metadata = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[uninum])
... )
>>> metadata.changed
False
property first_period: ReportingPeriod[source]#

Return the earliest period this file was published in.

This is the start of the earliest of this file’s periods spans.

Returns:
ReportingPeriod

The first period of this file’s earliest span.

Examples

>>> from call_report.core import FieldSchema, FileMetadata, PeriodRange
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> metadata = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[])
... )
>>> metadata.first_period.label
'2000Q1'
property last_period: ReportingPeriod[source]#

Return the latest period this file was published in.

This is the end of the latest of this file’s periods spans.

Returns:
ReportingPeriod

The last period of this file’s latest span.

Examples

>>> from call_report.core import FieldSchema, FileMetadata, PeriodRange
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> metadata = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[])
... )
>>> metadata.last_period.label
'2026Q1'
property changed: bool[source]#

Return whether any field’s presence differs from this file’s own.

A field whose overall presence (its versions’ periods, merged across any in-place redefinitions) does not exactly match this file’s periods was added after the file’s first period, dropped before its last, or has a gap the file itself does not have. In every one of those cases the file’s column schema was not identical across its whole history. A field that was purely redefined in place, meaning its dtype or definition changed but it was always present, does not count as changed on its own.

Returns:
bool

True if any field’s presence differs from the file’s own.

Examples

>>> import narwhals as nw
>>> from call_report.core import (
...     FieldAttributes,
...     FieldSchema,
...     FieldVersion,
...     FileMetadata,
...     PeriodRange,
... )
>>> full = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> partial = PeriodRange(start="2010-03-31", end="2026-03-31")
>>> added_later = FieldAttributes(
...     name="RSSD",
...     versions=(
...         FieldVersion(dtype=nw.Int64(), definition="", periods=partial),
...     ),
... )
>>> schema = FieldSchema(fields=[added_later])
>>> FileMetadata(name="RCB", periods=(full,), file_schema=schema).changed
True
as_of(*, period: str | date | ReportingPeriod) FileMetadata[source]#

Return a new FileMetadata snapshot as of period.

Delegates field selection to FieldSchema.as_of. The result’s own periods is likewise narrowed to the single quarter period.

Parameters:
periodstr, datetime.date, or ReportingPeriod

The quarter-end to take the snapshot at.

Returns:
FileMetadata

A new instance describing only period.

Raises:
PeriodNotAvailableError

If this file was not published as of period.

Examples

>>> import narwhals as nw
>>> from call_report.core import (
...     FieldAttributes,
...     FieldSchema,
...     FieldVersion,
...     FileMetadata,
...     PeriodRange,
... )
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> field = FieldAttributes(
...     name="UNINUM",
...     versions=(FieldVersion(dtype=nw.Int64(), definition="", periods=span),),
... )
>>> metadata = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[field])
... )
>>> metadata.as_of(period="2010-03-31").file_schema.names
('UNINUM',)
is_equal(*, other: FileMetadata, check_order: bool = False) bool[source]#

Return whether other describes the same file: name, periods, and fields.

Field comparison is delegated entirely to FieldSchema.is_equal, so this doesn’t duplicate that logic.

Parameters:
otherFileMetadata

The file metadata to compare against.

check_orderbool, default False

Passed through to FieldSchema.is_equal for the field comparison.

Returns:
bool

True if name, periods, and file_schema (per FieldSchema.is_equal) all match.

Examples

>>> import narwhals as nw
>>> from call_report.core import (
...     FieldAttributes,
...     FieldSchema,
...     FieldVersion,
...     FileMetadata,
...     PeriodRange,
... )
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> field = FieldAttributes(
...     name="UNINUM",
...     versions=(FieldVersion(dtype=nw.Int64(), definition="", periods=span),),
... )
>>> a = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[field])
... )
>>> b = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[field])
... )
>>> a.is_equal(other=b)
True
compare(*, other: FileMetadata, check_order: bool = False) FileMetadataDiff[source]#

Compare this file’s metadata against other.

name and periods are compared directly. The field-level comparison is delegated entirely to FieldSchema.compare.

Parameters:
otherFileMetadata

The file metadata to compare against.

check_orderbool, default False

Passed through to FieldSchema.compare.

Returns:
FileMetadataDiff

The name/periods/field-level differences between the two.

Examples

>>> import narwhals as nw
>>> from call_report.core import (
...     FieldAttributes,
...     FieldSchema,
...     FieldVersion,
...     FileMetadata,
...     PeriodRange,
... )
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> old_field = FieldAttributes(
...     name="UNINUM",
...     versions=(
...         FieldVersion(dtype=nw.Int64(), definition="old", periods=span),
...     ),
... )
>>> new_field = FieldAttributes(
...     name="UNINUM",
...     versions=(
...         FieldVersion(dtype=nw.Int64(), definition="new", periods=span),
...     ),
... )
>>> before = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[old_field])
... )
>>> after = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[new_field])
... )
>>> diff = before.compare(other=after)
>>> diff.is_empty
False
>>> [change.name for change in diff.file_schema_diff.changed]
['UNINUM']
to_dataframe(*, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: None = None) NativeDataFrame[source]#
to_dataframe(*, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: Literal['pandas']) pandas.DataFrame
to_dataframe(*, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: Literal['pyarrow_table']) pyarrow.Table
to_dataframe(*, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: Literal['polars_dataframe']) polars.DataFrame
to_dataframe(*, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: Literal['polars_lazyframe']) polars.LazyFrame

Return this file’s metadata as a native dataframe.

Built from FieldSchema.to_dataframe, with a file_name column added and one extra row per file-level period span (identifiable by an empty field_name), so this file’s own periods round-trip through from_dataframe alongside its fields.

Parameters:
backend{“pandas”, “polars”, “pyarrow”}, optional

The dataframe library used to build the frame (passed through to FieldSchema.to_dataframe). If omitted, uses whatever backend is currently configured via call_report.config.get_config. Most users can leave this at its default.

dataframe_type{“pandas”, “pyarrow_table”, “polars_lazyframe”, “polars_dataframe”}, optional

The dataframe type to convert the result to as a final step, regardless of backend. Leave this None (the default) to get back whatever backend produced. Set it when the code that consumes this result needs a specific type, for example a pandas DataFrame while the package is configured to use polars. The conversion is zero-copy when the requested type already matches.

Returns:
NativeDataFrame

A native dataframe with columns file_name, field_name, dtype, definition, period_start, and period_end.

Examples

>>> import narwhals as nw
>>> from call_report.core import (
...     FieldAttributes,
...     FieldSchema,
...     FieldVersion,
...     FileMetadata,
...     PeriodRange,
... )
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> field = FieldAttributes(
...     name="UNINUM",
...     versions=(FieldVersion(dtype=nw.Int64(), definition="", periods=span),),
... )
>>> metadata = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[field])
... )
>>> frame = metadata.to_dataframe()
>>> list(frame.columns)
['file_name', 'field_name', 'dtype', 'definition', 'period_start', 'period_end']
classmethod from_dataframe(*, data: Any) FileMetadata[source]#

Reconstruct a FileMetadata from a dataframe built by to_dataframe.

Rows with an empty field_name are this file’s own period spans. Every other row is delegated to FieldSchema.from_dataframe.

Parameters:
dataAny

A native dataframe with the columns to_dataframe produces.

Returns:
FileMetadata

The reconstructed file metadata.

Raises:
SchemaError

If data has no file-level period rows, or rows naming more than one distinct file_name.

Examples

>>> import narwhals as nw
>>> from call_report.core import (
...     FieldAttributes,
...     FieldSchema,
...     FieldVersion,
...     FileMetadata,
...     PeriodRange,
... )
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> field = FieldAttributes(
...     name="UNINUM",
...     versions=(FieldVersion(dtype=nw.Int64(), definition="", periods=span),),
... )
>>> metadata = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[field])
... )
>>> frame = metadata.to_dataframe()
>>> FileMetadata.from_dataframe(data=frame).name
'RCB'
to_json(*, indent: int | None = 2) str[source]#

Return this file’s metadata as a JSON string.

This is the format shipped, canonical FCA schedule metadata is stored in (see call_report.fca.get_fca_file_metadata).

Parameters:
indentint, optional

Passed through to json.dumps. See FieldSchema.to_json.

Returns:
str

A JSON object with name, periods, and fields keys. fields uses the same shape FieldSchema.to_json produces.

Examples

>>> import narwhals as nw
>>> from call_report.core import (
...     FieldAttributes,
...     FieldSchema,
...     FieldVersion,
...     FileMetadata,
...     PeriodRange,
... )
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> field = FieldAttributes(
...     name="UNINUM",
...     versions=(FieldVersion(dtype=nw.Int64(), definition="", periods=span),),
... )
>>> metadata = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[field])
... )
>>> FileMetadata.from_json(text=metadata.to_json()) == metadata
True
classmethod from_json(*, text: str) FileMetadata[source]#

Reconstruct a FileMetadata from JSON built by to_json.

The inverse of to_json. Round-tripping metadata through both reconstructs an equal FileMetadata.

Parameters:
textstr

A JSON string in the shape to_json produces.

Returns:
FileMetadata

The reconstructed file metadata.

Raises:
SchemaError

If text is not valid JSON, is valid JSON that isn’t a JSON object, or doesn’t otherwise match the shape to_json produces.

Examples

>>> import narwhals as nw
>>> from call_report.core import (
...     FieldAttributes,
...     FieldSchema,
...     FieldVersion,
...     FileMetadata,
...     PeriodRange,
... )
>>> span = PeriodRange(start="2000-03-31", end="2026-03-31")
>>> field = FieldAttributes(
...     name="UNINUM",
...     versions=(FieldVersion(dtype=nw.Int64(), definition="", periods=span),),
... )
>>> metadata = FileMetadata(
...     name="RCB", periods=(span,), file_schema=FieldSchema(fields=[field])
... )
>>> FileMetadata.from_json(text=metadata.to_json()).name
'RCB'