GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - dry-python/classes: Smart, pythonic, ad-hoc, typed polymorphism for Python

BranchesTags
Open more actions menu

Latest commit

 

History

376 Commits
376 Commits

Folders and files

NameName
Last commit message
Last commit date
.github
.github
 
 
classes
classes
 
 
docs
docs
 
 
tests
tests
 
 
typesafety
typesafety
 
 
.editorconfig
.editorconfig
 
 
.gitignore
.gitignore
 
 
.readthedocs.yml
.readthedocs.yml
 
 
CHANGELOG.md
CHANGELOG.md
 
 
CONTRIBUTING.md
CONTRIBUTING.md
 
 
LICENSE
LICENSE
 
 
README.md
README.md
 
 
poetry.lock
poetry.lock
 
 
pyproject.toml
pyproject.toml
 
 
setup.cfg
setup.cfg
 
 

Repository files navigation

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 bind 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 built 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 work 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 is 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! Or read these articles:

  • Typeclasses in Python

— ⭐️ —

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

Read more in our Telegram group

About

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

classes.rtfd.io

Topics

fpmypymypy-pluginsmypy-stubspep561pythonpython3typeclassestypesafety

Resources

Readme
BSD-2-Clause license

Code of conduct

Code of conduct

Contributing

Contributing
Activity
Custom properties

Stars

733 stars

Watchers

12 watching

Forks

30 forks
Report repository

Releases

Sponsor this project

Packages

Used by

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.