Skip to main content

Type-Driven Development for Python

Project description

pytyped

pytyped is a Python package whose goal is to enable as much type-driven development as possible in Python. We believe in using types to automate mundane and repetitive tasks. Currently, given a type, JSON decoders/encoders and metric extractors can be automatically extracted for that type.

Installation

You can install pytyped from PyPI:

pip install pytyped

pytyped is checked on Python 3.6+.

Using pytyped to extract JSON decoders/encoders

First, define your type. For example, in the following we want to define an account that can either be a personal account or a business account with personal account having one owner and possibly a co-owner while a business account has the company name as the owner and a list of persons that can represent the company.

from dataclasses import dataclass
from datetime import datetime
from typing import List
from typing import Optional

@dataclass
class Person:
    first_name: str
    last_name: str


@dataclass
class Account:
    created_at: datetime


@dataclass
class PersonalAccount(Account):
    owner: Person
    co_owner: Optional[Person]


@dataclass
class BusinessAccount(Account):
    owner: str
    representatives: List[Person]

Second, use an instance of AutoJsonDecoder and AutoJsonEncoder to extract JSON decoders and encoders as below:

from pytyped.json.decoder import AutoJsonDecoder
from pytyped.json.decoder import JsonDecoder
from pytyped.json.encoder import AutoJsonEncoder
from pytyped.json.encoder import JsonEncoder

_auto_json_decoder = AutoJsonDecoder()
_auto_json_encoder = AutoJsonEncoder()

account_decoder: JsonDecoder[Account] = _auto_json_decoder.extract(Account)
account_encoder: JsonEncoder[Account] = _auto_json_encoder.extract(Account)

Third, define some instances of the Account class:

personal_account = PersonalAccount(
    created_at = datetime.now(),
    owner = Person(first_name = "John", last_name = "Doe"),
    co_owner = None
)

business_account = BusinessAccount(
    created_at = datetime.now(),
    owner = "Doe Ltd.",
    representatives = [Person(first_name = "John", last_name = "Doe"), Person(first_name = "Jane", last_name = "Doe")]
) 

Finally, use account_encoder and account_decoder to convert data in your instances to/from JSON as below:

>>> json = account_encoder.write(personal_account)
>>> json
{'created_at': '2020-08-24T20:00:18.205347', 'owner': {'first_name': 'John', 'last_name': 'Doe'}, 'co_owner': None, 'Account': 'PersonalAccount'}
>>> account_decoder.read(json)
PersonalAccount(created_at=datetime.datetime(2020, 8, 24, 20, 0, 18, 205347), owner=Person(first_name='John', last_name='Doe'), co_owner=None)


>>> json = account_encoder.write(business_account)
>>> json
{'created_at': '2020-08-24T20:00:40.057088', 'owner': 'Doe Ltd.', 'representatives': [{'first_name': 'John', 'last_name': 'Doe'}, {'first_name': 'Jane', 'last_name': 'Doe'}], 'Account': 'BusinessAccount'}
>>> account_decoder.read(json)
BusinessAccount(created_at=datetime.datetime(2020, 8, 24, 20, 0, 40, 57088), owner='Doe Ltd.', representatives=[Person(first_name='John', last_name='Doe'), Person(first_name='Jane', last_name='Doe')])

To illustrate the types of validation that JSON decoders enable for you, consider the following example invalid JSONs:

>>> account_decoder.read({'created_at': '2020-08-24T20:00:40.057088', 'owner': 'Doe Ltd.', 'representatives': [{'first_name': 'John', 'last_name': 'Doe'}, {'first_name': 'Jane', 'last_name': 'Doe'}], 'Account': 'NewAccount'})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "~/Repos/pytyped/pytyped/json/decoder.py", line 91, in read
    raise JsDecodeException(t_or_error)
pytyped.json.decoder.JsDecodeException: Found 1 errors while validating JSON: [
  Error when decoding JSON: /Account: Unknown tag value NewAccount (possible values are: PersonalAccount, BusinessAccount).]


>>> account_decoder.read({'created_at': '2020-08-24T20:00:40.057088', 'owner': 'Doe Ltd.', 'representatives': [{'first_name': 'John', 'last_name': 'Doe'}, {'first_name': 'Jane', 'last': 'Doe'}], 'Account': 'BusinessAccount'})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/shahab/Repos/pytyped/pytyped/json/decoder.py", line 91, in read
    raise JsDecodeException(t_or_error)
pytyped.json.decoder.JsDecodeException: Found 1 errors while validating JSON: [
  Error when decoding JSON: /representatives[1]/last_name: Non-optional field was not found]

Using pytyped to extract metrics

Similar to extracting JSON decoders/encoders except that pytyped.metrics.exporter.AutoMetricExporter is used. Further explanation is WIP.

Defining New Type Automations

You can follow the examples of JSON decoders, JSON encoders, and metric exporters to define new type-based automations. You just need to extend pytyped.macros.extractor.Extractor and implement the abstrtact methods there. Further explanation is WIP.

Issues

Please report any issues to the GitHub repository for this package.

Contributors

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

pytyped-0.0.4.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

pytyped-0.0.4-py3-none-any.whl (34.3 kB view details)

Uploaded Python 3

File details

Details for the file pytyped-0.0.4.tar.gz.

File metadata

  • Download URL: pytyped-0.0.4.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.6.9

File hashes

Hashes for pytyped-0.0.4.tar.gz
Algorithm Hash digest
SHA256 af1f56feb11b87a7a0506249af92affb5f600b1356898d98bf6d9f86957d279a
MD5 19775e2cf794d9c28a2ec605ec6e687a
BLAKE2b-256 8fb9931f0827887a86c6afa470046b729b163e8e52d1f90f024abee9f5111142

See more details on using hashes here.

File details

Details for the file pytyped-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: pytyped-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 34.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.6.9

File hashes

Hashes for pytyped-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 9463536ca561761e080d180ff9c694d64f481de030b5990e474666d7fd28df5e
MD5 9707ca6a9f4b73f9a011b4334f03387b
BLAKE2b-256 7710b7e8742857f47d86ab339822d4848e87539630e18bacc1a53a57d674c944

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