Metadata-Version: 2.1
Name: pytyped
Version: 0.1.0
Summary: Type-Driven Development for Python
Home-page: https://github.com/stasharrofi/pytyped
Author: Shahab Tasharrofi
Author-email: shahab.tasharrofi@gmail.com
License: UNKNOWN
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](https://pypi.org/):
        
        ```
        pip install pytyped
        ```
        
        `pytyped` is checked on `Python 3.6+`.
        
        ### Why `pytyped`?
        
        To our knowledge, `pytyped` is the only Python package that supports type-based automation for all typing constructs
        including even recursive types that, up to this day, is not even fully supported by Python itself yet. Additionally,
        `pytyped` is designed to be extensible. That is, despite the fact that JSON encoding/decoding provided by `pytyped`
        is a very nice feature, it's only one the use cases of `pytyped`. In the past, we have successfully used `pytyped` in
        different scenarios such as automating report generation based on data types as well as automating DynamoDB interactions
        based on the type of the data that is being stored/retrieved.
        
        In order to see how you can automate your own workflow on top of `pytyped`, see how JSON decoding/encoding and metric
        extractions use `pytyped.macros` to achieve type-driven meta-programming.
        
        Currently, `pytyped` supports the following type classes:
        - Basic types such as `int`, `bool`, `date`, `datetime`, `str`, and `Decimal`.
        - Simple usual combinators such as `List[T]` and `Dict[A, B]`.
        - Named product types such as `NamedTuple`s or `dataclass`es.
        - Anonymous product types such as `Tuple[T1, T2, ...]`.
        - Anonymous union types such as `Optional[T]`, `Union[T1, T2, ...]`, etc.
        - Named union types such as class hierarchies.
        - Generic types and type variables.
        - Recursive types.
        
        ### 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.
        
        ```python
        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:
        
        ```python
        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:
        
        ```python
        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:
        
        ```python
        >>> 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:
        
        ```python
        >>> 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](https://github.com/stasharrofi/pytyped).
        
        ### Contributors
        
        - [Shahab Tasharrofi](mailto:shahab.tasharrofi@gmail.com)
        - [Ilyess Bachiri](mailto:bachiri.ilyess@gmail.com)
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
