Skip to main content

Declarively apply converter functions to class attributes.

Project description

Exert

Declaratively apply converter functions to class attributes.

Installation

Install via pip:

pip install exert

Usage

Use this to declaratively apply arbitrary converter functions to the attributes of a class. For example:

from __future__ import annotations

from typing import Annotated
from exert import exert


@exert
class Foo:
    a: Annotated[int, lambda x: x**2]
    b: Annotated[float, lambda x: x / 2]

    def __init__(self, a: int, b: float) -> None:
        self.a = a
        self.b = b


foo = Foo(2, 42.0)

print(foo.a) # prints 4
print(foo.b) # prints 21.0

Here, the lambda function inside the Annotated tag is the converter.

Using with dataclasses

Dataclasses can also be used to avoid writing the initializer by hand. For example:

...
from dataclasses import dataclass


@exert
@datclasses
class Foo:
    a: Annotated[int, lambda x: x**2]
    b: Annotated[float, lambda x: x / 2]


foo = Foo(2, 42.0)

print(foo.a) # prints 4
print(foo.b) # prints 21.0

Apply multiple converters sequentially

Multiple converters are allowed. For example:

...

@exert
@dataclass
class Foo:
    a: Annotated[int, lambda x: x**2, lambda x: x**3]
    b: Annotated[float, lambda x: x / 2, lambda x: x / 3]


foo = Foo(2, 42.0)

print(foo.a) # prints 64  [2**2=4, 4**3=64]
print(foo.b) # prints 7.0 [42.0/2=21.0, 21.0/3=7.0]

Excluding tagged fields

If you want to exclude a field that's tagged with Annotated, you can do so using the tagged_exclude parameter:

...

@exert(tagged_exclude=("b",))
@dataclass
class Foo:
    a: Annotated[int, lambda x: x**2, lambda x: x**3]
    b: Annotated[float, lambda x: x / 2, lambda x: x / 3]


foo = Foo(2, 42.0)

print(foo.a)  # prints 64  [2**2=4, 4**3=64]
print(foo.b)  # prints 42.0 [This field was ignored]

Including untagged fields

By default, exert will ignore fields that aren't tagged with Annotated. But you can still apply converters to those fields. You'll need to use converters and untagged_include together:

...

@exert(converters=(lambda x: x**2, lambda x: x**3), untagged_include=("b",))
@dataclass
class Foo:
    a: int
    b: float


foo = Foo(2, 42.0)

print(foo.a)  # prints 2            [This field remains untouched]
print(foo.b)  # prints 5489031744.0 [42.0**2=1764, 1764**3=5489031744.0]

Apply common converters without repetition

Common converters can be applied to multiple fields without introducing any repetition. The the previous section already shows how to do it:

...

@exert(converters=(lambda x: x**2, ), untagged_include=("a", "b"))
@dataclass
class Foo:
    a: int
    b: float


foo = Foo(2, 42.0)

print(foo.a)  # prints 2      [This field remains untouched]
print(foo.b)  # prints 1764.0 [42.0**2=1764.0]

Apply common and tagged converters together

You can apply a sequence of common converters and tagged converters together. By default, the common converters are applied first and then the tagged converters are applied sequentially:

...

@exert(converters=(lambda x: x**2, lambda x: x**3), untagged_include=("b",))
@dataclass
class Foo:
    a: Annotated[int, lambda x: x / 100]
    b: float


foo = Foo(2, 42.0)

print(foo.a)  # prints 0.64         [2**2=4, 4**3=64, 64/100=0.64]
print(foo.b)  # prints 5489031744.0 [42.0**2=1764, 1764**3=5489031744.0]

You can also, choose to apply the common converters after the tagged ones. For this, you'll need to set the apply_last parameter to True:

...
@exert(
    converters=(lambda x: x**2, lambda x: x**3),
    untagged_include=("b",),
    apply_last=True,
)
@dataclass
class Foo:
    a: Annotated[int, lambda x: x / 100]
    b: float


foo = Foo(2, 42.0)

print(foo.a)  # prints 6.401e-11 [2/100=0.02, 0.02**2=0.004, 0.0004**3=6.401e-11]
print(foo.b)  # prints 5489031744.0 [42.0**2=1764, 1764**3=5489031744.0]

Include all untagged fields

To apply converters to all the untagged fields, use untagged_include="__all__":

...
@exert(
    converters=(lambda x: x**2, lambda x: x**3),
    untagged_include="__all__",
)
@dataclass
class Foo:
    a: int
    b: float


foo = Foo(2, 42.0)

print(foo.a)  # prints 64   [2**2=4, 4**4=64]
print(foo.b)  # prints 5489031744.0 [42.0**2=1764, 1764**3=5489031744.0]

Exclude all tagged fields

To ignore all the fields tagged with Annotated, use tagged_exclude="__all__":

...
@exert(
    converters=(lambda x: x**2, lambda x: x**3),
    tagged_exclude="__all__",
)
@dataclass
class Foo:
    a: Annotated[int, lambda x: x**2]
    b: Annotated[float, lambda x: x**3]


foo = Foo(2, 42.0)

print(foo.a)  # prints 2   [Untouched]
print(foo.b)  # prints 42.0 [Untouched]

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

exert-0.2.1.tar.gz (4.9 kB view details)

Uploaded Source

Built Distribution

exert-0.2.1-py3-none-any.whl (4.8 kB view details)

Uploaded Python 3

File details

Details for the file exert-0.2.1.tar.gz.

File metadata

  • Download URL: exert-0.2.1.tar.gz
  • Upload date:
  • Size: 4.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.10.4

File hashes

Hashes for exert-0.2.1.tar.gz
Algorithm Hash digest
SHA256 fc0ab0f413deb8a896424954fb745252cd46fb295159b9ab8f0f09b5b929033e
MD5 25a13c74f1b3c8837080cb4aa7989d25
BLAKE2b-256 9579c9d53fba996044d1af56abb500c13547af1ee97af12809f1c81bed8e28f7

See more details on using hashes here.

File details

Details for the file exert-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: exert-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 4.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.10.4

File hashes

Hashes for exert-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 366fc7bde7fddef99051e73e766afda91d9434ba1b789c7cc5d8ce2165a2be84
MD5 4e8ac161a5ddd97d319185bf66e61dc0
BLAKE2b-256 08f170a7afde334c66725963d44db86405209d8326fdeb84eb6de03bde9ae713

See more details on using hashes here.

Supported by

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