dataspecs package#

class Path(*segments: str | PathLike[str])[source]#

Bases: PurePosixPath

Path for data specs.

It is based on PurePosixPath, however, the differences are a path must start with the root (/) and the match method full-matches a regular expression.

Parameters:

*segments (str | PathLike[str]) – Segments to create a path.

Raises:

ValueError – Raised if it does not start with the root.

Return type:

Self

property children: Self#

Return the regular expression that matches the child paths.

property descendants: Self#

Return the regular expression that matches the descendant paths.

property regex: Self#

Return the regular expression that matches the path itself.

match(pattern: str | PathLike[str], /) bool[source]#

Check if the path full-matches a regular expression.

Parameters:

pattern (str | PathLike[str])

Return type:

bool

class Spec(path: ~dataspecs.core.specs.Path, name: ~typing.Hashable, tags: tuple[~dataspecs.core.typing.TagBase, ...], type: ~typing.Any, data: ~dataspecs.core.typing.TAny, anns: tuple[~typing.Any, ...] = <factory>, meta: dict[str, ~typing.Any] = <factory>, orig: ~typing.Any | None = None)[source]#

Bases: Generic[TAny]

Data specification (data spec).

Parameters:
  • path (Path) – Path of the data spec.

  • name (Hashable) – Name of the data spec.

  • tags (tuple[TagBase, ...]) – Tags of the data spec.

  • type (Any) – Type hint (unannotated) of the data spec.

  • data (TAny) – Default or final data of the data spec.

  • anns (tuple[Any, ...]) – Type hint annotations of the data spec.

  • meta (dict[str, Any]) – Metadata of the data spec.

  • orig (Any | None) – Origin of the data spec.

path: Path#

Path of the data spec.

name: Hashable#

Name of the data spec.

tags: tuple[TagBase, ...]#

Tags of the data spec.

type: Any#

Type hint (unannotated) of the data spec.

data: TAny#

Default or final data of the data spec.

anns: tuple[Any, ...]#

Type hint annotations of the data spec.

meta: dict[str, Any]#

Metadata of the data spec.

orig: Any | None = None#

Origin of the data spec.

__call__(type: Callable[[...], UAny], /) Spec[UAny][source]#

Dynamically cast the data of the data spec.

Parameters:

type (Callable[[...], UAny])

Return type:

Spec[UAny]

__getitem__(type: Callable[[...], UAny], /) Spec[UAny][source]#

Statically cast the data of the data spec.

Parameters:

type (Callable[[...], UAny])

Return type:

Spec[UAny]

class Specs(initlist=None)[source]#

Bases: UserList[TSpec]

Data specifications (data specs).

property first: TSpec | None#

Return the first data spec if it exists (None otherwise).

property last: TSpec | None#

Return the last data spec if it exists (None otherwise).

property unique: TSpec | None#

Return the data spec if it is unique (None otherwise).

groupby(attr: Literal['path', 'name', 'tags', 'type', 'data', 'anns', 'meta', 'orig'], /, *, method: Literal['eq', 'equality', 'id', 'identity'] = 'equality') list[Self][source]#

Group the data specs by their attributes.

Parameters:
  • attr (Literal['path', 'name', 'tags', 'type', 'data', 'anns', 'meta', 'orig']) – Name of the data spec attribute for grouping. Either 'path', 'name', 'tags', 'type', 'data', 'anns', 'meta', or 'orig' is accepted.

  • method (Literal['eq', 'equality', 'id', 'identity']) – Grouping method. Either 'equality' (or 'eq'; hash-based grouping), or 'identity' (or 'id'; id-based grouping) is accepted.

Returns:

List of data specs grouped by the selected data spec attribute.

Return type:

list[Self]

replace(old: TSpec, new: TSpec, /) Self[source]#

Return data specs with old data spec replaced by new one.

Parameters:
  • old (TSpec)

  • new (TSpec)

Return type:

Self

__getitem__(index: None, /) Self[source]#
__getitem__(index: TagBase, /) Self
__getitem__(index: type[Any], /) Self
__getitem__(index: str | PathLike[str], /) Self
__getitem__(index: slice, /) Self
__getitem__(index: SupportsIndex, /) TSpec

Select data specs with given index.

In addition to a normal index (i.e. an object that has __index__ method), it also accepts the following extended index for the advanced selection: (1) a tag to select data specs that contain it, (2) a tag type to select data specs that contain its tags, (3) an any type to select data specs that contain it, (4) a string path to select data specs that match it, or (5) None to return all data specs (shallow copy).

Parameters:

index – Normal or extended index for the selection of the data specs.

Returns:

Selected data specs with given index.

class TagBase(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]#

Bases: Enum

Base enum of tag for data specs.

Since TagBase itself does not have any members, users should create their own tags by inheriting it:

from enum import auto
from dataspecs import TagBase

class Tag(TagBase):
    ATTR = auto()
    DATA = auto()
    NAME = auto()
from_dataclass(obj: ~dataspecs.core.typing.DataClassObject | type[~dataspecs.core.typing.DataClassObject], /, *, factory: ~typing.Any = <class 'dataspecs.core.specs.Spec'>, path: str | ~os.PathLike[str] = Path('/')) Any[source]#

Create data specs from a dataclass (object).

Parameters:
  • obj (DataClassObject | type[DataClassObject]) – Dataclass (object) to be parsed.

  • factory (Any) – Factory for creating each data spec.

  • path (str | PathLike[str]) – Path of the parent data spec.

Returns:

Data specs created from the dataclass (object).

Return type:

Any

Examples

from enum import auto
from dataclasses import dataclass
from dataspecs import TagBase, from_dataclass
from typing import Annotated as Ann

class Tag(TagBase):
    ATTR = auto()
    DATA = auto()
    DTYPE = auto()

@dataclass
class Weather:
    temp: Ann[list[Ann[float, Tag.DTYPE]], Tag.DATA]
    humid: Ann[list[Ann[float, Tag.DTYPE]], Tag.DATA]
    location: Ann[str, Tag.ATTR]

from_dataclass(Weather([20.0, 25.0], [50.0, 55.0], "Tokyo"))
Specs([
    Spec(
        path=Path('/temp'),
        tags=(<Tag.DATA: 2>,),
        type=list[float],
        data=[20.0, 25.0],
    ),
    Spec(
        path=Path('/temp/0'),
        tags=(<Tag.DTYPE: 3>,),
        type=<class 'float'>,
        data=None,
    ),
    Spec(
        path=Path('/humid'),
        tags=(<Tag.DATA: 2>,),
        type=list[float],
        data=[50.0, 55.0],
    ),
    Spec(
        path=Path('/humid/0'),
        tags=(<Tag.DTYPE: 3>,),
        type=<class 'float'>,
        data=None,
    ),
    Spec(
        path=Path('/location'),
        tags=(<Tag.ATTR: 1>,),
        type=<class 'str'>,
        data='Tokyo',
    ),
])
from_typehint(obj: ~typing.Any, /, *, factory: ~typing.Any = <class 'dataspecs.core.specs.Spec'>, path: str | ~os.PathLike[str] = Path('/'), data: ~typing.Any = None, meta: dict[str, ~typing.Any] | None = None, orig: ~typing.Any | None = None) Any[source]#

Create data specs from a type hint.

Parameters:
  • obj (Any) – Type hint to be parsed.

  • factory (Any) – Factory for creating each data spec.

  • path (str | PathLike[str]) – Path of the parent data spec.

  • data (Any) – Data of the parent data spec.

  • meta (dict[str, Any] | None) – Metadata of the parent data spec.

  • orig (Any | None) – Origin of the parent data spec.

Returns:

Data specs created from the type hint.

Return type:

Any

Examples

from enum import auto
from dataspecs import TagBase, from_typehint
from typing import Annotated as Ann

class Tag(TagBase):
    DATA = auto()
    DTYPE = auto()

from_typehint(Ann[list[Ann[float, Tag.DTYPE]], Tag.DATA])
Specs([
    Spec(
        path=Path('/'),
        tags=(<Tag.DATA: 1>,),
        type=list[float],
        data=None,
    ),
    Spec(
        path=Path('/0'),
        tags=(<Tag.DTYPE: 2>,),
        type=<class 'float'>,
        data=None,
    ),
])
class Format(_format_path: ~typing.Annotated[str | ~os.PathLike[str], <FormatTag.PATH: 2>], _format_attr: ~typing.Annotated[~typing.Literal['path', 'name', 'tags', 'type', 'data', 'anns', 'meta', 'orig'], <FormatTag.ATTR: 1>] = 'data', _format_skipif: ~typing.Annotated[~typing.Any, <FormatTag.SKIPIF: 3>] = None)[source]#

Bases: object

Annotation for formatter specs.

Parameters:
  • _format_path (Annotated[str | PathLike[str], <FormatTag.PATH: 2>]) – Path of data spec(s) to be formatted.

  • _format_attr (Annotated[Literal['path', 'name', 'tags', 'type', 'data', 'anns', 'meta', 'orig'], <FormatTag.ATTR: 1>]) – Name of data spec attribute to be formatted.

  • _format_skipif (Annotated[Any, <FormatTag.SKIPIF: 3>]) – Sentinel value for which formatting is skipped.

class Name(_name: ~typing.Annotated[~collections.abc.Hashable, <NameTag.NAME: 1>])[source]#

Bases: object

Annotation for namer specs.

Parameters:

_name (Annotated[Hashable, <NameTag.NAME: 1>]) – New name of the data spec to be replaced.

class Replace(_replace_path: ~typing.Annotated[str | ~os.PathLike[str], <ReplaceTag.PATH: 2>], _replace_attr: ~typing.Annotated[~typing.Literal['path', 'name', 'tags', 'type', 'data', 'anns', 'meta', 'orig'], <ReplaceTag.ATTR: 1>] = 'data', _replace_skipif: ~typing.Annotated[~typing.Any, <ReplaceTag.SKIPIF: 3>] = None)[source]#

Bases: object

Annotation for replacer specs.

Parameters:
  • _replace_path (Annotated[str | PathLike[str], <ReplaceTag.PATH: 2>]) – Path of data spec(s) to be replaced.

  • _replace_attr (Annotated[Literal['path', 'name', 'tags', 'type', 'data', 'anns', 'meta', 'orig'], <ReplaceTag.ATTR: 1>]) – Name of data spec attribute to be replaced.

  • _replace_skipif (Annotated[Any, <ReplaceTag.SKIPIF: 3>]) – Sentinel value for which replacing is skipped.

format(specs: Specs[TSpec], /, leave: bool = False) Specs[TSpec][source]#

Format data spec attributes by formatter specs.

Parameters:
  • specs (Specs[TSpec]) – Input data specs.

  • leave (bool) – Whether to leave the formatter specs.

Returns:

Data specs whose attributes are formatted.

Return type:

Specs[TSpec]

Examples

from enum import auto
from dataclasses import dataclass
from dataspecs import TagBase, Format, from_dataclass, format
from typing import Annotated as Ann

class Tag(TagBase):
    ATTR = auto()

@dataclass
class Attrs:
    name: Ann[str, Tag.ATTR]
    units: Ann[str, Tag.ATTR]

@dataclass
class Weather:
    temp: Ann[list[float], Attrs("Temperature ({0})", "{0}")]
    units: Ann[str, Format("/temp/(name|units)")] = "degC"

format(from_dataclass(Weather([20.0, 25.0], "K")))
Specs([
    Spec(
        path=Path('/temp'),
        name='temp',
        tags=(),
        type=list[float],
        data=[20.0, 25.0],
    ),
    Spec(
        path=Path('/temp/0'),
        name='0',
        tags=(),
        type=<class 'float'>,
        data=None,
    ),
    Spec(
        path=Path('/temp/name'),
        name='name',
        tags=(<Tag.ATTR: 1>,),
        type=<class 'str'>,
        data='Temperature (K)', # <- formatted
    ),
    Spec(
        path=Path('/temp/units'),
        name='units',
        tags=(<Tag.ATTR: 1>,),
        type=<class 'str'>, data='K', # <- formatted
    ),
    Spec(
        path=Path('/units'),
        name='units',
        tags=(),
        type=<class 'str'>,
        data='K',
    ),
])
name(specs: Specs[TSpec], /, leave: bool = False) Specs[TSpec][source]#

Replace data spec names by corresponding namer specs.

Parameters:
  • specs (Specs[TSpec]) – Input data specs.

  • leave (bool) – Whether to leave the namer specs.

Returns:

Data specs whose names are replaced.

Return type:

Specs[TSpec]

Examples

from dataclasses import dataclass
from dataspecs import Name, name, from_dataclass
from typing import Annotated as Ann

@dataclass
class Weather:
    temp: Ann[float, Name("Ground temperature")]
    humid: Ann[float, Name("Relative humidity")]

name(from_dataclass(Weather(20.0, 50.0)))
Specs([
    Spec(
        path=Path('/temp'),
        name='Ground temperature', # <- named
        tags=(),
        type=<class 'float'>,
        data=20.0,
    ),
    Spec(
        path=Path('/humid'), # <- named
        name='Relative humidity',
        tags=(),
        type=<class 'float'>,
        data=50.0,
    ),
])
replace(specs: Specs[TSpec], /, leave: bool = False) Specs[TSpec][source]#

Replace data spec attributes by replacer specs.

Parameters:
  • specs (Specs[TSpec]) – Input data specs.

  • leave (bool) – Whether to leave the replacer specs.

Returns:

Data specs whose attributes are replaced.

Return type:

Specs[TSpec]

Examples

from enum import auto
from dataclasses import dataclass
from dataspecs import Replace, TagBase, from_dataclass, replace
from typing import Annotated as Ann

class Tag(TagBase):
    ATTR = auto()
    DATA = auto()
    DTYPE = auto()

@dataclass
class Weather:
    temp: Ann[list[Ann[float, Tag.DTYPE]], Tag.DATA]
    humid: Ann[list[Ann[float, Tag.DTYPE]], Tag.DATA]
    dtype: Ann[type, Replace("/[a-z]+/0", "type")] = None

replace(from_dataclass(Weather([20.0, 25.0], [50.0, 55.0], int)))
Specs([
    Spec(
        path=Path('/temp'),
        name='temp',
        tags=(<Tag.DATA: 2>,),
        type=list[float],
        data=[20.0, 25.0],
    ),
    Spec(
        path=Path('/temp/0'),
        name='0',
        tags=(<Tag.DTYPE: 3>,),
        type=<class 'int'>, # <- replaced
        data=None,
    ),
    Spec(
        path=Path('/humid'),
        name='humid',
        tags=(<Tag.DATA: 2>,),
        type=list[float],
        data=[50.0, 55.0],
    ),
    Spec(
        path=Path('/humid/0'),
        name='0',
        tags=(<Tag.DTYPE: 3>,),
        type=<class 'int'>, # <- replaced
        data=None,
    ),
    Spec(
        path=Path('/dtype'),
        name='dtype',
        tags=(),
        type=<class 'type'>,
        data=<class 'int'>,
    ),
])

Subpackages#