Skip to main content

Represent type-checked specifications as Python classes and incrementally build them.

Project description

Spec Classes Logo

PyPI - Version Conda Forge - Version PyPI - Python Version PyPI - Status build codecov Code Style

Introduction

spec_classes is a stand-alone (but largely interoperable) generalization of the standard library's dataclass decorator. It adds, among other things: type-checking, rich field preparation, and convenient copy-on-write mutation wrappers. Spec-class definitions are Pythonic, simple, and concise.

This library is especially useful in contexts where run-time validation and instant feedback is desirable, and/or where correctness is valued over performance. With that said, we do try to keep spec-classes performant (see performance details).

Philosophy

It should be hard for users to do the wrong thing. spec_classes is designed to help end-users interact with, mutate, and assemble (especially in ad hoc contexts like notebooks) potentially large libraries of data classes without fear of breaking things. Operations on data classes should be atomic (operations should never be partially committed), validated (types should match, etc.), and provide instant helpful feedback when the user makes a mistake.

We don't own your class. spec_classes never overrides local pre-existing methods, and doesn't add any metaclasses or parents. If you decorate a class with @spec_class, spec classes will add (if you have not already) some dunder magic methods (like __init__,__setattr__, etc.), and some helper methods... but that's it. Spec classes are, at the end of the day, just regular classes pre-loaded with useful methods that you didn't have to write yourself.

Copy-on-write by default. One of the dangers with using class instances as specification is that if they are mutated in one context, they are mutated for all contexts. Spec classes does not prevent (by default) local mutations of class instances (you can still do my_spec.foo = 'bar'); but all helper methods return a mutated copy by default. For example, my_spec.with_foo('bar') will not be the same instance as my_spec, and so these methods are always safe to use.

Be consistent. All helper methods added by spec_classes exist within well defined namespaces; that is: with_<attr>, transform_<attr>, etc.; and each class of methods has the same naming conventions for arguments and provides complete inline documentation. This makes it easy for users to figure out how to use the methods, to override these methods and/or to add new methods that do not collide.

Minimize Surprise. The behavior of spec classes almost always matches that of base Python classes where functionality overlaps, and should always be intuitive otherwise (e.g. when type-checking is violated).

Performance is important. Although performance is not the primary goal of spec_classes, given the targeted feature-set, the overhead introduced should be as small as possible.

Example

from spec_classes import spec_class

@spec_class
class Rectangle:
    width: float
    height: float
    color: str

    @property
    def area(self):
        return self.width * self.height

rect = Rectangle()
rect  # Rectangle(width=MISSING, height=MISSING, color=MISSING)
rect.update(width=10., height=12.).with_color("red")  # Rectangle(width=10.0, height=12.0, color='red')

Rectangle(width=10., height=10.).area  # 100.0

rect.with_width('invalid')  # TypeError: Attempt to set `Rectangle.width` with an invalid type [got `'invalid'`; expecting `float`].

For more details on usage, refer to the documentation.

Installation

Spec classes can be installed via pip or conda.

To install via pip you can use:

pip install spec-classes

To install via conda you can use:

conda install spec-classes

You can verify that the installation was successful by printing the version of spec-classes that was installed:

python -c "import spec_classes; print(spec_classes.__version__)"

Related projects and prior art

spec_classes takes a more opinionated stance than most libraries in this space on exactly how data-classes should be built and mutated. Nevertheless, there are excellent pre-existing alternatives to spec-classes for those looking for something lighter-weight. In particular, you could consider:

  • typeguard: A utility library for run-time type-checking functions, methods and classes.
  • pytypes: Another utility library for run-time type-checking functions, methods and classes.
  • pydantic: A light-weight data parsing and validation library that also uses type hints.
  • attrs: A library that provides a super-set of the functionality of Python's data-class, but still adds no run-time overhead (no type-checking, extra helper-methods, etc).

There are many other libraries in the business of mapping and validating transformations from JSON to Python classes, but these are somewhat orthogonal to the aims of this project (which is to make Python classes themselves pleasant to use), and so they are not included here.

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

spec_classes-1.5.11.tar.gz (317.4 kB view details)

Uploaded Source

Built Distribution

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

spec_classes-1.5.11-py3-none-any.whl (66.5 kB view details)

Uploaded Python 3

File details

Details for the file spec_classes-1.5.11.tar.gz.

File metadata

  • Download URL: spec_classes-1.5.11.tar.gz
  • Upload date:
  • Size: 317.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.16.2 cpython/3.10.19 HTTPX/0.28.1

File hashes

Hashes for spec_classes-1.5.11.tar.gz
Algorithm Hash digest
SHA256 68f906e99ea606b6a12068ff7267b1b08dce3d1403d4e27d4293637ff8e72621
MD5 6da94e068abe24267a72bef36c08a4ac
BLAKE2b-256 befc0df5a5e4fa3301971bd6e4c3b5b23a1eef3996bb3a4ab74b9e9dd2acb421

See more details on using hashes here.

File details

Details for the file spec_classes-1.5.11-py3-none-any.whl.

File metadata

  • Download URL: spec_classes-1.5.11-py3-none-any.whl
  • Upload date:
  • Size: 66.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.16.2 cpython/3.10.19 HTTPX/0.28.1

File hashes

Hashes for spec_classes-1.5.11-py3-none-any.whl
Algorithm Hash digest
SHA256 1a0b2efd28202b8805a299fdff92f0b611b222cc4201bf9292f31fb406f2e118
MD5 6e7879fa9aa0dc4a07c76acfb9cd5930
BLAKE2b-256 312b6fef4484e3403140f776262b2e42a0024c4a1d101d778a7ce64e018605b3

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