# -*- 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.3',
    '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.\nSome parsing features are available only since Python 3.8 (like [ast.get_source_segment](https://docs.python.org/3/library/ast.html#ast.get_source_segment)).\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).\nThe detection of composition relationships relies on type annotations only, assigned values or expressions are never evaluated to prevent unwanted side-effects\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.3`: handle constructors decorated by wrapping decorators (decorators making uses of `functools.wrap`)\n* `0.5.2`: specify in pyproject.toml that py2puml requires python 3.8+ (`ast.get_source_segment` was introduced in 3.8)\n* `0.5.1`: prevent from parsing inherited constructors\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.\nFollow the [contributing guide](CONTRIBUTING.md).\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.8,<4.0',
}


setup(**setup_kwargs)
