Skip to main content

Type-containing enumeration

Project description

Enumetyped

This package provide a way to create typed enumerations.

Install

  • pip install enumetyped
  • pip install enumetyped[pydantic] - install with pydantic >=2.9

Quickstart

Without pydantic

from enumetyped import Enumetyped, Empty, Content


class SimpleEnum(Enumetyped[Content]):
    A: type["SimpleEnum[Empty]"]
    Int: type["SimpleEnum[int]"]


# isinstance checking
assert isinstance(SimpleEnum.A(), SimpleEnum)
assert isinstance(SimpleEnum.Int(123), SimpleEnum.Int)
assert not isinstance(SimpleEnum.Int(123), SimpleEnum.A)

# fully pattern-matching
match SimpleEnum.Int(1):
    case SimpleEnum.Int(2):
        a = False
    case SimpleEnum.Int(1):
        a = True
    case SimpleEnum.Int():
        a = True
    case _:
        a = False

assert a

With pydantic

import typing
from dataclasses import dataclass

from pydantic import BaseModel

from enumetyped import Enumetyped, Content, Empty
from enumetyped.pydantic import EnumetypedPydantic, FieldMetadata, Rename
from typing_extensions import Annotated, TypedDict


class Enum(Enumetyped[Empty]):
    V1: type["Enum"]
    V2: type["Enum"]


@dataclass
class TestDataClass:
    a: int


class TestModel(BaseModel):
    b: str


class TestTypedDict(TypedDict):
    tm: TestModel


class SimpleEnum(EnumetypedPydantic[Empty]):
    V1: type["SimpleEnum"]
    V2: type["SimpleEnum"]


class OtherEnum(EnumetypedPydantic[Content]):
    Int: type["OtherEnum[int]"]
    Int: type["OtherEnum[str]"]


# class MyEnum(EnumetypedPydantic[Content], variant="key", content="value"):  # <- adjacently
# class MyEnum(EnumetypedPydantic[Content], variant="key"):  # <- internally
class MyEnum(EnumetypedPydantic[Content]):  # <- externally, default
    # MyEnum.Int(123)
    Int: type["MyEnum[int]"]

    # MyEnum.Str(123)
    Str: type["MyEnum[str]"]

    # MyEnum.Str(OtherEnum.Int(1))
    Other: type["MyEnum[OtherEnum[Any]]"]  # any from OtherEnum variants

    # MyEnum.Str(MyEnum.Int(1)) | MyEnum.Str(MyEnum.Str(1))
    Self: type["MyEnum[MyEnum[Any]]"]  # any from self variants

    # MyEnum.OnlySelf(...) - any parameters skipped, serialized just by name
    NoValue: type["MyEnum[NoValue]"]

    # MyEnum.OnlySelf2(None)
    Optional: type["MyEnum[Optional[bool]]"]

    # MyEnum.List(["1", "2", "3"])
    List: type["MyEnum[list[str]]"]

    # MyEnum.Dict({"key": "value"})
    Dict: type["MyEnum[dict[str, str]]"]
    # TypedDict: type["MyEnum[{"b": str}]"]
    TypedDict: type["MyEnum[TestD]"]  # python doesn`t have inline TypedDict now

    # MyEnum.DC(TestDataClass(a=1))
    DataClass: type["MyEnum[TestDataClass]"]

    # MyEnum.Model(TestModel(b="2"))
    Model: type["MyEnum[TestModel]"]

    # MyEnum.StrTuple(("1", "2")))
    StringTuple: Annotated[type["MyEnum[tuple[str, str]]"], FieldMetadata(rename="just_str_tuple")]
    # or use enumetyped.pydantic.Rename
    # StrTuple: Annotated[type["MyEnum[tuple[str, str]]"], Rename("some_other_name")]

    # MyEnum.DeepAndDeeper([{"a": [(1, MyEnum.Int(2))]}])
    DeepAndDeeper: type["MyEnum[list[dict[str, list[tuple[int, MyEnum]]]]]"]

class FinModel(BaseModel):
    enum: MyEnum


def dump_and_load(e: MyEnum):
    # Can use in other model
    #
    # model = FinModel(enum=e)
    # json_ = model.model_dump_json()
    # print(json_)
    # restored = FinModel.model_validate_json(json_)
    # assert model == restored
    
    json_ = e.model_dump_json()
    print(json_)
    restored = MyEnum.model_validate_json(json_)
    assert e == restored


# externally -> {"enum":{"Int":1}} 
# adjacently -> {"enum":{"key":"Int","value":1}}
# internally -> not supported
dump_and_load(MyEnum.Int(1))

# externally -> {"enum":{"Str":"str"}}
# adjacently -> {"enum":{"key":"Str","value":"str"}}
# internally -> not supported
dump_and_load(MyEnum.Str("str"))

# externally -> {"enum":{"List":["list"]}}
# adjacently -> {"enum":{"key":"List","value":["list"]}}
# internally -> not supported
dump_and_load(MyEnum.List(["list"]))

# externally -> {"enum":{"just_str_tuple":["str","str2"]}} 
# adjacently -> {"enum":{"key":"just_str_tuple","value":["str","str2"]}}
# internally -> not supported
dump_and_load(MyEnum.StringTuple(("str", "str2")))

# externally -> {"enum":{"Self":{"Int":1}}} 
# adjacently -> {"enum":{"key":"Self","value":{"key":"Int","value":1}}}
# internally -> not supported
dump_and_load(MyEnum.Self(MyEnum.Int(1)))

# externally -> {"enum":{"DC":{"a":1}}} 
# adjacently -> {"enum":{"key":"DC","value":{"a":1}}}
# internally -> {"enum":{"key":"DC","a":1}}}
# internally -> may fall with "was never filled on some pydantic versions"
dump_and_load(MyEnum.DataClass(TestDataClass(a=1)))

# externally -> {"enum":{"Model":{"b":"test_model"}}} 
# adjacently -> {"enum":{"key":"Model","value":{"b":"test_model"}}}
# internally -> {"enum":{"key":"Model", "b":"test_model"}}
dump_and_load(MyEnum.Model(TestModel(b="test_model")))

# externally -> {"enum":{"TypedDict":{"tm":{"b":"test_model"}}}} 
# adjacently -> {"enum":{"key":"TypedDict","value":{"tm":{"b":"test_model"}}}}
# internally -> {"enum":{"key":"TypedDict","tm":{"b":"test_model"}}}
# internally -> may fall with "was never filled on some pydantic versions"
dump_and_load(MyEnum.TypedDict(TestTypedDict(tm=TestModel(b="test_model"))))

# externally -> {"enum":{"Dict":{"a":"1","b":"2"}}} 
# adjacently -> {"enum":{"key":"Dict","value":{"a":"1","b":"2"}}}
# internally -> not supported
dump_and_load(MyEnum.Dict({"a": "1", "b": "2"}))

# externally -> {"enum":"NoValue"}
# adjacently -> {"enum":{"key":"NoValue"}}
# internally -> {"enum":{"key":"NoValue"}}
dump_and_load(MyEnum.NoValue())

# externally -> {"enum":{"Optional":null}} 
# adjacently -> {"enum":{"key":"Optional","value":null}}
# internally -> not supported
dump_and_load(MyEnum.Optional(None))

# externally -> {"enum":{"DeepAndDeeper":[{"a":[[1,{"Int":2}]]}]}}
# adjacently -> {"enum":{"key":"DeepAndDeeper","value":[{"a":[[1,{"key":"Int","value":2}]]}]}}
# internally -> not supported
dump_and_load(MyEnum.DeepAndDeeper([{"a": [(1, MyEnum.Int(2))]}]))

Other

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

enumetyped-0.4.2.tar.gz (11.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

enumetyped-0.4.2-py3-none-any.whl (15.3 kB view details)

Uploaded Python 3

File details

Details for the file enumetyped-0.4.2.tar.gz.

File metadata

  • Download URL: enumetyped-0.4.2.tar.gz
  • Upload date:
  • Size: 11.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 colorama/0.4.4 importlib-metadata/8.5.0 keyring/24.3.1 pkginfo/1.11.2 readme-renderer/34.0 requests-toolbelt/1.0.0 requests/2.32.3 rfc3986/1.5.0 tqdm/4.57.0 urllib3/2.2.0 CPython/3.10.12

File hashes

Hashes for enumetyped-0.4.2.tar.gz
Algorithm Hash digest
SHA256 b1cce57e9f39d4aefca06c995504366c1b7eadcdf305ab8d100f2a1e12586da2
MD5 61b7290343aafd4baab8c59498b9b9b9
BLAKE2b-256 f4fb4ec317b6fe9de50a62c502032b812e6a49dfbf4b397e0b30ee146ec5f81e

See more details on using hashes here.

File details

Details for the file enumetyped-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: enumetyped-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 15.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 colorama/0.4.4 importlib-metadata/8.5.0 keyring/24.3.1 pkginfo/1.11.2 readme-renderer/34.0 requests-toolbelt/1.0.0 requests/2.32.3 rfc3986/1.5.0 tqdm/4.57.0 urllib3/2.2.0 CPython/3.10.12

File hashes

Hashes for enumetyped-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4de1d4d24c2a3b5781058525a996f29130f08cbbde3f7494cdc67b6ed4e93702
MD5 e43b82e86648a199f7e494a828f1550c
BLAKE2b-256 b52cd7307231cf16845a2c4e6d40db01b180751b4b0fc3bc0e8d388825d607c5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page