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.2.tar.gz (4.9 kB view details)

Uploaded Source

Built Distribution

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

Uploaded Python 3

File details

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

File metadata

  • Download URL: exert-0.2.2.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.2.tar.gz
Algorithm Hash digest
SHA256 b05a10d4446f50a45d08b9672277cec3cfc356dbdd17e58cda5b818e10dbbca6
MD5 3aba6de592a30452126bb26d79f640f8
BLAKE2b-256 38e0bd1bc0df57fc2840a10b976696632762413c911a148ed3f94b00d924c578

See more details on using hashes here.

File details

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

File metadata

  • Download URL: exert-0.2.2-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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 25e4256c8ab0dcdc69632be84df87f3b79e8560d50bbae3b34e1c4142bfd7a9e
MD5 5d9cc4724b90747babc0db491436ceb2
BLAKE2b-256 7934b545b95050b2ec5e7423df415dd6b84de1db2432a2b1a7d25d2adfff6a78

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