Skip to main content

Extensions for primitives to add validation constraints

Project description

Constrained Types

Statement: Nothing should ever really be modelled as any String or any integer.

Example

A user wants to order a number of books. Can it be zero? Can it be negative?

@add_constraint(lambda x: x > 0, "Order must be at least 1")
class OrderQuantity(ConstrainedInt):
    pass

now:

quantity = OrderQuantity(5)

# works exactly like an int
total_price = quantity * 5

# but you can't create sneaky discount books
quantity = OrderQuantity(-1)
# !! raises ValueError

Multiple constraints

@add_constraint(lambda x: x > 0, "Order must be at least 1")
@add_constraint(lambda x: x < 200, "Our shipping system can't send more then 200")
class OrderQuantity(ConstrainedInt):
    pass

In addition the constraints are guaranteed to execute in order so any expensive checks to run can be listed further down.

Cache results

If you expect the same value multiple times you can add caching for the validation. The actual caching is passed to functools.lru_cache.

@add_constraint(lambda x: len(x) > 0, "The order id must be set")
@add_constraint(lambda x: len(x) < 10, "Order ids are under 10 chars")
@add_constraint(some_really_complicated_checksum, "The order number was invalid")
@cache_constraint_results(maxsize=100)
class OrderId(ConstrainedString):
    pass

Works well with mypy (or other static type checkers)

# The following will type check fine. OrderId is a real type
def retrieve_order(order_id: OrderId):
    ...

maybe something further down only accepts strings:

def _fetch_item_from_db(table_name: str, item_id: str):
    ...

def retrieve_order(order_id: OrderId):
    # The following will type check fine. OrderId extends str
    return _fetch_item_from_db("orders", order_id)

Integrates with pydantic

@add_constraint(lambda x: x > 0, "Order must be at least 1")
class OrderQuantity(ConstrainedInt):
    pass


@add_constraint(lambda x: len(x) == 4, "Invalid order id")
class BookId(ConstrainedString):
    pass


class Order(BaseModel):
    book_quantity: OrderQuantity
    book_id: BookId

Why not use the pydantic version of these constrained types?

The pydantic types only really work with pydantic. Invalid instances can be created by constructing directly. Since constraint checking is triggered by the constructor the constraints will always be true for any instance of the class.

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

constrained_types-0.4.0.tar.gz (13.5 kB view details)

Uploaded Source

Built Distribution

constrained_types-0.4.0-py2.py3-none-any.whl (5.3 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file constrained_types-0.4.0.tar.gz.

File metadata

  • Download URL: constrained_types-0.4.0.tar.gz
  • Upload date:
  • Size: 13.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.24.0

File hashes

Hashes for constrained_types-0.4.0.tar.gz
Algorithm Hash digest
SHA256 3b6c3ffa01e1fa42fa947939c6259dd330cd639bb3977e7c2f66114cc5310653
MD5 66cde26a4fd8af913602890de1bf34ef
BLAKE2b-256 ac8ab872e798da6844b23eacbba5aefee5dd47ed2d0041c785754760c5554c59

See more details on using hashes here.

File details

Details for the file constrained_types-0.4.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for constrained_types-0.4.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 cd0d00d0b3c55155e9661b7549e354a0350fe7b17f4c9fbb441d1a8d83bd6139
MD5 7171ae1031b12872e73587f027a91a27
BLAKE2b-256 8a7a376ea4cde519d68310919bcda06065919f64609b534b21185515b0d5c043

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