Skip to main content

Smart, pythonic, ad-hoc, typed polymorphism for Python

Project description

classes

classes logo


Build Status codecov Documentation Status Python Version wemake-python-styleguide Telegram chat


Smart, pythonic, ad-hoc, typed polymorphism for Python.

Features

  • Provides a bunch of primitives to write declarative business logic
  • Enforces better architecture
  • Fully typed with annotations and checked with mypy, PEP561 compatible
  • Allows to write a lot of simple code without inheritance or interfaces
  • Pythonic and pleasant to write and to read (!)
  • Easy to start: has lots of docs, tests, and tutorials

Installation

pip install classes

You also need to configure mypy correctly and install our plugin:

# In setup.cfg or mypy.ini:
[mypy]
plugins =
  classes.contrib.mypy.classes_plugin

Without this step, your project will report type-violations here and there.

We also recommend to use the same mypy settings we use.

Make sure you know how to get started, check out our docs!

Example

Imagine, that you want to bound implementation to some particular type. Like, strings behave like this, numbers behave like that, and so on.

The good realworld example is djangorestframework. It is build around the idea that different data types should be converted differently to and from json format.

What is the "traditional" (or outdated if you will!) approach? To create tons of classes for different data types and use them.

That's how we end up with classes like so:

class IntField(Field):
    def from_json(self, value):
        return value

    def to_json(self, value):
        return value

It literally has a lot of problems:

  • It is hard to type this code. How can I be sure that my json is parseable by the given schema?
  • It produces a lot of boilerplate
  • It has complex API: there are usually several methods to override, some fields to adjust. Moreover, we use a class, not a simple function
  • It is hard to extend the default library for new custom types you will have in your own project
  • It is hard to override

There should be a better way of solving this problem! And typeclasses are a better way!

How would new API look like with this concept?

>>> from typing import Union
>>> from classes import typeclass

>>> @typeclass
... def to_json(instance) -> str:
...     """This is a typeclass definition to convert things to json."""

>>> @to_json.instance(int)
... @to_json.instance(float)
... def _to_json_int(instance: Union[int, float]) -> str:
...     return str(instance)

>>> @to_json.instance(bool)
... def _to_json_bool(instance: bool) -> str:
...     return 'true' if instance else 'false'

>>> @to_json.instance(list)
... def _to_json_list(instance: list) -> str:
...     return '[{0}]'.format(
...         ', '.join(to_json(list_item) for list_item in instance),
...     )

See how easy it is to works with types and implementation?

Typeclass is represented as a regular function, so you can use it like one:

>>> to_json(True)
'true'
>>> to_json(1)
'1'
>>> to_json([False, 1, 2.5])
'[false, 1, 2.5]'

And it easy to extend this typeclass with your own classes as well:

# Pretending to import the existing library from somewhere:
# from to_json import to_json

>>> import datetime as dt

>>> @to_json.instance(dt.datetime)
... def _to_json_datetime(instance: dt.datetime) -> str:
...     return instance.isoformat()
...
>>> to_json(dt.datetime(2019, 10, 31, 12, 28, 00))
'2019-10-31T12:28:00'

That's how simple, safe, and powerful typeclasses are! Make sure to check out our full docs to learn more.

More!

Want more? Go to the docs!

— ⭐️ —

Drylabs maintains dry-python and helps those who want to use it inside their organizations.

Read more at drylabs.io

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

classes-0.3.0.tar.gz (23.8 kB view details)

Uploaded Source

Built Distribution

classes-0.3.0-py3-none-any.whl (28.5 kB view details)

Uploaded Python 3

File details

Details for the file classes-0.3.0.tar.gz.

File metadata

  • Download URL: classes-0.3.0.tar.gz
  • Upload date:
  • Size: 23.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.6 CPython/3.8.9 Darwin/18.7.0

File hashes

Hashes for classes-0.3.0.tar.gz
Algorithm Hash digest
SHA256 c7bad585ca957dd2cf1418df1978375bd33bf7d905213528e41ba1cdba261f70
MD5 916b529b3eb773b75fcc32bfc7044796
BLAKE2b-256 5afbd9f7c1da87ab91b06141a0d2726450b80a6451c5cac9093937f4d6b6cf86

See more details on using hashes here.

File details

Details for the file classes-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: classes-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 28.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.6 CPython/3.8.9 Darwin/18.7.0

File hashes

Hashes for classes-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7b7706de19e2fd2381b5b518e3cbcebf783912afef7caba3d050edc97489d7b8
MD5 206d4c8a074f2025aa6c494a1282c4ef
BLAKE2b-256 199a5d83ec6fd9b58b55d49f3201555b13a699ae409ad4bc098a784ef4b5ed8c

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