# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['plato', 'plato.providers']

package_data = \
{'': ['*']}

install_requires = \
['Faker>=6.4.1,<7.0.0', 'typing-extensions>=3.7.4,<4.0.0']

setup_kwargs = {
    'name': 'plato',
    'version': '0.1.1',
    'description': 'A dataclasses-inspired approach to test data.',
    'long_description': '.. image:: https://raw.githubusercontent.com/py-plato/plato/main/logo/logo.svg\n  :alt: Plato logo\n  :width: 150px\n  :align: center\n\n.. image:: https://github.com/py-plato/plato/actions/workflows/workflow.yml/badge.svg?branch=main\n  :target: https://github.com/py-plato/plato/actions/workflows/workflow.yml\n  :alt: Build and release pipeline\n  \n\n.. image:: https://codecov.io/gh/py-plato/plato/branch/main/graph/badge.svg?token=UEVIAHO33E\n  :target: https://codecov.io/gh/py-plato/plato\n  :alt: Code coverage  \n\n.. image:: https://img.shields.io/pypi/v/plato\n  :target: https://pypi.org/project/plato\n  :alt: Latest PyPI version\n\n.. image:: https://img.shields.io/pypi/pyversions/plato\n  :target: https://pypi.org/project/plato\n  :alt: Python versions\n  \n.. image:: https://img.shields.io/pypi/l/plato\n  :target: https://github.com/py-plato/plato/blob/main/LICENSE\n  :alt: PyPI - License\n\nPlato\n=====\n\nPlato makes it easy\nto generate complex,\nbut consistent and realistic data\nfor tests\nwith a declarative syntax\ninspired by dataclasses.\n\n.. code-block:: python\n\n    fake = FromFaker()\n\n\n    @formclass\n    class Address:\n        street: str = fake.street_address()\n        postal_code: str = fake.postcode()\n        city: str = fake.city()\n        country: str = "USA"\n\n\n    @formclass\n    class Customer:\n        first_name: str = fake.first_name()\n        last_name: str = fake.last_name()\n        billing_address: Address = Address()\n\n        @property\n        def fullname(self) -> str:\n            return f"{self.first_name} {self.last_name}"\n\n        @derivedfield\n        def email(self) -> str:\n            return f"{self.first_name}.{self.last_name}@example.com"\n            \n\n    pprint(asdict(sample(Customer())))\n    # Prints:\n    # {\'billing_address\': {\'city\': \'North Reginaburgh\',\n    #                  \'country\': \'USA\',\n    #                  \'postal_code\': \'03314\',\n    #                  \'street\': \'310 Edwin Shore Suite 986\'},\n    #  \'email\': \'Denise.Wright@example.com\',\n    #  \'first_name\': \'Denise\',\n    #  \'last_name\': \'Wright\'}\n    \n\nVision and Guiding Priniciples\n------------------------------\n\n* Generating consistent and realistic test data should be **easy**. The more\n  effort it is to produce releastic or consistent test data, the more likely\n  developers take short cuts. This tends to couple tests to the implementation\n  (e.g., because only the fields required for a specific implementation are set,\n  or certain fields are inconsistent with the values of other fields). It also\n  makes it harder to understand, based on the tests, what the expected\n  production data will look like, or can be outright confusing.\n* The code should be **declarative**. When creating test data one should not be\n  concerned with *how* it is created, but with *what* the structure of that\n  data.\n* Try **minimize boilerplate** to reduce the effort of producing consistent and\n  realistic test data (see above).\n* To be able to easily create complex and varied test data, things should be\n  **composable**.\n* Test results should be **reproducible**. Thus, all test data will be generated\n  based on a fixed (but changeable) seed. Plato even tries to keep produced\n  values reproducible when fields are added or deleted from a class.\n* One should have **flexibility** in how the generated data is used. Therefore,\n  Plato produces dataclasses as output, that can be easily converted into\n  dictionaries and other sorts of objects.\n* **No collisions** of field names in the test data with Plato\'s API. This is\n  achieved similar to dataclasses by not defining Plato\'s API as member methods\n  on the formclasses, but as separate functions processing a formclass.\n\n\nProject Status and Roadmap\n--------------------------\n\nThe project is currently in a very early stage where I still explore the design\nspace of the API. Thus, breaking changes have to be expected at any time.\n\nThe current focus is on finishing the core API together with documentation and\nexamples to test out whether the API would work in real world scenarios.\n\nTo get something useful working quickly, Plato currently relies heavily on\n`Faker <https://faker.readthedocs.io/en/master/>`_. In the future, it is intended\nthat Plato also offers certain Providers, but implementing these is not yet the\nfocus.\n\nHere is a very roughly sorted list of additional features and to-dos to consider:\n\n* Setup CI, static typechecking, linting, auto-formatting\n* Setup website\n* Design a logo\n* Constructor parameters that do not appear as field in the dataclass.\n* Express relations between objects (apart from the composition already\n  possible), especially with respect to relational databases.\n* A standard set of providers\n* Documentation\n* Examples\n\n  * Usage with pytest\n  * Usage as builder\n  * Usage with ORM\n\n* A command line interface to generate data (i.e. in JSON format that than can\n  be used for web requests with some other tool)\n* ORM integration\n\n  * With possibility of cleaning up generated data\n\n* pytest integration\n\n\nAlternatives\n------------\n\n* `Faker <https://faker.readthedocs.io/en/master/>`_ is excellent for generating\n  individual pieces of information such as a realistic name, a bank account\n  number, a street address etc. However, it does not provide a convenient way\n  to generate more complex objects.\n* `Factory Boy <https://factoryboy.readthedocs.io/en/stable/>`_ has a very\n  similar aim and scope. As it has been around longer and it is stable, opposed\n  to Plato, you should prefer it for testing production code. However, Plato\n  will have some advantages, such as:\n\n  * Syntax with less boilerplate.\n  * It is easier to compose from fields of other sampled objects.\n  * API that avoids name collisions, whereas in Factory Boy one has to work\n    around it with renames.\n  * By producing data classes conversion into other data formats such as dicts,\n    JSON, etc. is easy and does not require to declare a model class duplicating\n    a lot of information.\n  * Reproducible test data even when deleting or adding fields on an object.\n\nInspirations\n------------\n\nPlato was inspired by:\n\n* Company-internal talks at\n  `TNG Technology Consulting GmbH <https://www.tngtech.com/>`_ (my employer).\n* `Strawberry <https://github.com/strawberry-graphql/strawberry>`_ which gave\n  me the idea to apply the dataclasses approach to other problems.\n* `Nengo <https://www.nengo.ai/>`_ which gave me the idea to seed random number\n  generator in a way robust against field removal and additions.\n* `Factory Boy <https://factoryboy.readthedocs.io/en/stable/>`_\n\nContributing\n------------\n\nContributions are welcome in general.\n\nFor bugs, feel free to open issues or pull requests.\n\nIf you have an ideas, feedback, or feature requests, also open an issue.\n\nGiven the early stage of the project, if you want to implement a feature,\nI suggest that you open an issue first to discuss the details and ensure that\nit aligns with the general direction the project is moving into.\n\nNote that it might take me a bit to react as I am working on Plato in my free\ntime besides other projects.\n\nThe name\n--------\n\nThe ancient greek philosopher Plato is well known for his *theory of\nforms*. It proposes that, the objects existing in reality are imitations of more\npure “Ideas” or “Forms” which are the non-physical essence of things.\n\nIn analogy, the library Plato allows you to define the essence or “Form“ of your\ntest data from which the concrete objects used in the tests are derived.',
    'author': 'Jan Gosmann',
    'author_email': 'jan@hyper-world.de',
    'maintainer': 'Jan Gosmann',
    'maintainer_email': 'jan@hyper-world.de',
    'url': 'https://github.com/py-plato/plato',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
