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

packages = \
['py2puml', 'py2puml.domain', 'py2puml.inspection', 'py2puml.parsing']

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

entry_points = \
{'console_scripts': ['py2puml = py2puml.cli:run']}

setup_kwargs = {
    'name': 'py2puml',
    'version': '0.5.0',
    'description': 'Generate PlantUML class diagrams to document your Python application.',
    'long_description': '<div align="center">\n  <a href="https://www.python.org/psf-landing/" target="_blank">\n    <img width="350px" alt="Python logo"\n      src="https://www.python.org/static/community_logos/python-logo-generic.svg" />\n  </a>\n  <a href="http://plantuml.com/" target="_blank">\n    <img width="116px" height="112px" alt="PlantUML logo" src="http://s.plantuml.com/logoc.png" style="margin-bottom: 40px" vspace="40px" />\n  </a>\n  <h1>Python to PlantUML</h1>\n</div>\n\nGenerate PlantUML class diagrams to document your Python application.\n\n# How it works\n\n`py2puml` produces a class diagram [PlantUML script](https://plantuml.com/en/class-diagram) representing classes properties (static and instance attributes) and their relations (composition and inheritance relationships).\n\n`py2puml` internally uses code [inspection](https://docs.python.org/3/library/inspect.html) (also called *reflexion* in other programming languages) and [abstract tree parsing](https://docs.python.org/3/library/ast.html) to retrieve relevant information.\n\n## Features\n\nFrom a given path corresponding to a folder containing Python code, `py2puml` processes each file as a module and generates a [PlantUML script](https://plantuml.com/en/class-diagram) of its classe-like definitions using:\n\n* **[inspection](https://docs.python.org/3/library/inspect.html)** and [type annotations](https://docs.python.org/3/library/typing.html) to detect:\n  * static class attributes and [dataclass](https://docs.python.org/3/library/dataclasses.html) fields\n  * fields of [namedtuples](https://docs.python.org/3/library/collections.html#collections.namedtuple)\n  * members of [enumerations](https://docs.python.org/3/library/enum.html)\n  * composition and inheritance relationships (between your domain classes only, for documentation sake)\n\n* parsing [abstract syntax trees](https://docs.python.org/3/library/ast.html#ast.NodeVisitor) to detect the instance attributes defined in `__init__` constructors\n\n`py2puml` outputs diagrams in PlantUML syntax, which can be:\n* versioned along your code with a unit-test ensuring its consistency (see the [test_py2puml.py\'s test_py2puml_model_on_py2uml_domain](tests/py2puml/test_py2puml.py) example)\n* generated and hosted along other code documentation (better option: generated documentation should not be versioned with the codebase)\n\nTo generate image files, use the PlantUML runtime, a docker image of the runtime (see [think/plantuml](https://hub.docker.com/r/think/plantuml)) or of a server (see the CLI documentation below)\n\nIf you like tools related with PlantUML, you may also be interested in this [lucsorel/plantuml-file-loader](https://github.com/lucsorel/plantuml-file-loader) project:\na webpack loader which converts PlantUML files into images during the webpack processing (useful to [include PlantUML diagrams in your slides](https://github.com/lucsorel/markdown-image-loader/blob/master/README.md#web-based-slideshows) with RevealJS or RemarkJS).\n\n# Install\n\nInstall from [PyPI](https://pypi.org/project/py2puml/):\n\n* with `pip`:\n\n```sh\npip install py2puml\n```\n\n* with [poetry](https://python-poetry.org/docs/):\n\n```sh\npoetry add py2puml\n```\n\n* with [pipenv](https://pipenv.readthedocs.io/en/latest/):\n\n```sh\npipenv install py2puml\n```\n\n# Usage\n\n## CLI\n\nOnce `py2puml` is installed at the system level, an eponymous command is available in your environment shell.\n\nFor example, to create the diagram of the classes used by `py2puml`, run:\n\n```sh\npy2puml py2puml/domain py2puml.domain\n```\n\nThis outputs the following PlantUML script:\n\n```plantuml\n@startuml\nclass py2puml.domain.umlclass.UmlAttribute {\n  name: str\n  type: str\n  static: bool\n}\nclass py2puml.domain.umlclass.UmlClass {\n  attributes: List[UmlAttribute]\n}\nclass py2puml.domain.umlitem.UmlItem {\n  name: str\n  fqn: str\n}\nclass py2puml.domain.umlenum.Member {\n  name: str\n  value: str\n}\nclass py2puml.domain.umlenum.UmlEnum {\n  members: List[Member]\n}\nenum py2puml.domain.umlrelation.RelType {\n  COMPOSITION: * {static}\n  INHERITANCE: <| {static}\n}\nclass py2puml.domain.umlrelation.UmlRelation {\n  source_fqn: str\n  target_fqn: str\n  type: RelType\n}\npy2puml.domain.umlclass.UmlClass *-- py2puml.domain.umlclass.UmlAttribute\npy2puml.domain.umlitem.UmlItem <|-- py2puml.domain.umlclass.UmlClass\npy2puml.domain.umlenum.UmlEnum *-- py2puml.domain.umlenum.Member\npy2puml.domain.umlitem.UmlItem <|-- py2puml.domain.umlenum.UmlEnum\npy2puml.domain.umlrelation.UmlRelation *-- py2puml.domain.umlrelation.RelType\n@enduml\n```\n\nUsing PlantUML, this script renders this diagram:\n\n![py2puml UML Diagram](http://www.plantuml.com/plantuml/png/ZPB1Qy8m5CRl-IlUMR277Oi7HOGLfXrTTnfZfFLj59AqIru7elxlUuqQ1ewcftmcvlTzUL-NZgIbNYjHA-aST8U7Zdyb-rRBnYGi_NxogjMAo3PLJmX70M2anXGSMTPqw89c7ZLr2bNRAd6EKzU3y4HvuxiKdXf7RtyztqTO3Q4UK1clTza-lusN8_VHz3hPegxGtbt_aQh7IG0EiE7L4xI7tTvnGGyl6FxuptsBYeVMcgH0LV8iFMETRv_pbwpCybqACpXU1dlcasptk2coShLRRr9OdC9HI3ZYm2cBg_OkhkrjZHzXIW0axHTIs0drNhEnIRJDsNm-wKCIaIuN9mR5t4Ia3muptlca5ECcOjh4VPPu_MA9Pi_xlm00)\n\nFor a full overview of the CLI, run:\n\n```sh\npy2puml --help\n```\n\nThe CLI can also be launched as a python module:\n\n```sh\npython -m py2puml py2puml/domain py2puml.domain\n```\n\nPipe the result of the CLI with a PlantUML server for instantaneous documentation (rendered by ImageMagick):\n\n```sh\n# runs a local PlantUML server from a docker container:\ndocker run -d --rm -p 1234:8080 --name plantumlserver plantuml/plantuml-server:jetty \n\npy2puml py2puml/domain py2puml.domain | curl -X POST --data-binary @- http://localhost:1234/svg/ --output - | display\n\n# stops the container when you don\'t need it anymore, restarts it later\ndocker stop plantumlserver\ndocker start plantumlserver\n```\n\n## Python API\n\nFor example, to create the diagram of the classes used by `py2puml`:\n\n* import the py2puml function in your script (see [py2puml/example.py](py2puml/example.py)):\n\n```python\nfrom py2puml.py2puml import py2puml\n\n# outputs the PlantUML content in the terminal\nprint(\'\'.join(py2puml(\'py2puml/domain\', \'py2puml.domain\')))\n\n# writes the PlantUML content in a file\nwith open(\'py2puml/domain.puml\', \'w\') as puml_file:\n    puml_file.writelines(py2puml(\'py2puml/domain\', \'py2puml.domain\'))\n```\n\n* running it (`python3 -m py2puml.example`) will output the previous PlantUML diagram in the terminal and write it in a file.\n\n\n# Tests\n\n```sh\n# directly with poetry\npoetry run python -m pytest -v\n\n# in a virtual environment\npython3 -m pytest -v\n```\n\nCode coverage (with missed [branch statements](https://pytest-cov.readthedocs.io/en/latest/config.html?highlight=--cov-branch)):\n\n```sh\npoetry run python -m pytest -v --cov=py2puml --cov-branch --cov-report term-missing --cov-fail-under 90\n```\n\n# Changelog\n\n* `0.5.0`: handle instance attributes in class constructors, add code coverage of unit tests\n* `0.4.0`: add a simple CLI\n* `0.3.1`: inspect sub-folders recursively\n* `0.3.0`: handle classes derived from namedtuples (attribute types are `Any`)\n* `0.2.0`: handle inheritance relationships and enums\n* `0.1.3`: first release, handle all modules of a folder and compositions of domain classes\n\n# Licence\n\nUnless stated otherwise all works are licensed under the [MIT license](http://spdx.org/licenses/MIT.html), a copy of which is included [here](LICENSE).\n\n# Contributions\n\n* [Luc Sorel-Giffo](https://github.com/lucsorel)\n* [Doyou Jung](https://github.com/doyou89)\n* [Julien Jerphanion](https://github.com/jjerphan)\n\nPull-requests are welcome and will be processed on a best-effort basis.\n\n# Current limitations\n\n* regarding **inspection**\n\n  * type hinting is optional when writing Python code and discarded when it is executed, as mentionned in the [typing official documentation](https://docs.python.org/3/library/typing.html). The quality of the diagram output by `py2puml` depends on the reliability with which the type annotations were written\n\n  > The Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc.\n\n  * complex type hints with more than one level of genericity are not properly handled for the moment: `List[MyClass]` or `Dict[str, MyClass]` are handled properly, `Dict[str, List[MyClass]]` is not.\n  If your domain classes (also called business objects or DTOs) have attributes with complex type hints, it may be a code smell indicating that you should write a class which would better represent the business logic.\n  But I may improve this part of the library as well 😀\n\n* regarding the detection of instance attributes with **AST parsing**:\n  * only constructors are visited, attributes assigned in other functions won\'t be documented\n  * attribute types are inferred from type annotations:\n    * of the attribute itself\n    * of the variable assigned to the attribute: a signature parameter or a locale variable\n    * to avoid side-effects, no code is executed nor interpreted\n\n# Alternatives\n\nIf `py2puml` does not meet your needs (suggestions and pull-requests are **welcome**), you can have a look at these projects which follow other approaches (AST, linting, modeling):\n\n* [cb109/pyplantuml](https://github.com/cb109/pyplantuml)\n* [deadbok/py-puml-tools](https://github.com/deadbok/py-puml-tools)\n* [caballero/genUML](https://github.com/jose-caballero/genUML)\n',
    'author': 'Luc Sorel-Giffo',
    'author_email': None,
    'maintainer': 'Luc Sorel-Giffo',
    'maintainer_email': None,
    'url': 'https://github.com/lucsorel/py2puml',
    'packages': packages,
    'package_data': package_data,
    'entry_points': entry_points,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
