fix: make sure pip install from github works ()

pip install from github was failing with the following error:

```
× python setup.py egg_info did not run successfully.
  │ exit code: 1
  ╰─> [8 lines of output]
      Traceback (most recent call last):
        File "<string>", line 2, in <module>
        File "<pip-setuptools-caller>", line 34, in <module>
        File "/private/var/folders/8l/klypdyl51dvb7_1kztfgsv8m0000gn/T/pip-req-build-vx02zbxx/setup.py", line 20, in <module>
          from ansibleplaybookgrapher import __version__, __prog__
        File "/private/var/folders/8l/klypdyl51dvb7_1kztfgsv8m0000gn/T/pip-req-build-vx02zbxx/ansibleplaybookgrapher/__init__.py", line 18, in <module>
          from ansible.utils.display import Display
      ModuleNotFoundError: No module named 'ansible'
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

× Encountered error while generating package metadata.
╰─> See above for output.
```

This is due to setup tools trying to inspect the files during the
installation process while some of dependencies are not installed yet.

---------

Co-authored-by: haidaraM <haidaraM@users.noreply.github.com>
This commit is contained in:
Mohamed El Mouctar Haidara 2024-03-23 06:55:34 +01:00 committed by GitHub
parent 888ff457aa
commit 4979cf9119
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 93 additions and 84 deletions

View file

@ -48,10 +48,20 @@ for the supported Ansible version.
## Installation
```shell script
```shell
pip install ansible-playbook-grapher
```
You can also install the unpublished version from GitHub direction. Examples:
```shell
# Install the version from the main branch
pip install "ansible-playbook-grapher @ git+https://github.com/haidaraM/ansible-playbook-grapher"
# Install the version from a specific branch
pip install "ansible-playbook-grapher @ git+https://github.com/haidaraM/ansible-playbook-grapher@specific-branch"
```
### Renderers
At the time of writing, two renderers are supported:

View file

@ -1,77 +1,2 @@
# Copyright (C) 2023 Mohamed El Mouctar HAIDARA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Dict, List, Set, Tuple
from ansible.utils.display import Display
from ansibleplaybookgrapher.graph_model import (
PlaybookNode,
RoleNode,
PlayNode,
)
from ansibleplaybookgrapher.parser import PlaybookParser
from ansibleplaybookgrapher.utils import merge_dicts
from .graph_model import PlaybookNode, PlayNode, TaskNode, RoleNode, BlockNode
from .parser import PlaybookParser
__version__ = "2.1.2"
__version__ = "2.2.0.dev0"
__prog__ = "ansible-playbook-grapher"
display = Display()
class Grapher:
def __init__(self, playbook_filenames: List[str]):
"""
:param playbook_filenames: List of playbooks to graph
"""
self.playbook_filenames = playbook_filenames
def parse(
self,
include_role_tasks: bool = False,
tags: List[str] = None,
skip_tags: List[str] = None,
group_roles_by_name: bool = False,
) -> Tuple[List[PlaybookNode], Dict[RoleNode, Set[PlayNode]]]:
"""
Parses all the provided playbooks
:param include_role_tasks: Should we include the role tasks
:param tags: Only add plays and tasks tagged with these values
:param skip_tags: Only add plays and tasks whose tags do not match these values
:param group_roles_by_name: Group roles by name instead of considering them as separate nodes with different IDs
:return: Tuple of the list of playbook nodes and the dictionary of the role usages: the key is the role and the
value is the set of plays that use the role.
"""
playbook_nodes = []
roles_usage: Dict[RoleNode, Set[PlayNode]] = {}
for playbook_file in self.playbook_filenames:
display.display(f"Parsing playbook {playbook_file}")
playbook_parser = PlaybookParser(
playbook_filename=playbook_file,
tags=tags,
skip_tags=skip_tags,
include_role_tasks=include_role_tasks,
group_roles_by_name=group_roles_by_name,
)
playbook_node = playbook_parser.parse()
playbook_nodes.append(playbook_node)
# Update the usage of the roles
roles_usage = merge_dicts(roles_usage, playbook_node.roles_usage())
return playbook_nodes, roles_usage

View file

@ -1,4 +1,4 @@
# Copyright (C) 2023 Mohamed El Mouctar HAIDARA
# Copyright (C) 2024 Mohamed El Mouctar HAIDARA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -23,7 +23,8 @@ from ansible.errors import AnsibleOptionsError
from ansible.release import __version__ as ansible_version
from ansible.utils.display import Display
from ansibleplaybookgrapher import __prog__, __version__, Grapher
from ansibleplaybookgrapher.grapher import Grapher
from ansibleplaybookgrapher import __prog__, __version__
from ansibleplaybookgrapher.renderer import OPEN_PROTOCOL_HANDLERS
from ansibleplaybookgrapher.renderer.graphviz import GraphvizRenderer
from ansibleplaybookgrapher.renderer.mermaid import (

View file

@ -0,0 +1,67 @@
# Copyright (C) 2024 Mohamed El Mouctar HAIDARA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Dict, List, Set, Tuple
from ansibleplaybookgrapher.graph_model import (
PlaybookNode,
RoleNode,
PlayNode,
)
from ansibleplaybookgrapher.parser import PlaybookParser
from ansibleplaybookgrapher.utils import merge_dicts
class Grapher:
def __init__(self, playbook_filenames: List[str]):
"""
:param playbook_filenames: List of playbooks to graph
"""
self.playbook_filenames = playbook_filenames
def parse(
self,
include_role_tasks: bool = False,
tags: List[str] = None,
skip_tags: List[str] = None,
group_roles_by_name: bool = False,
) -> Tuple[List[PlaybookNode], Dict[RoleNode, Set[PlayNode]]]:
"""
Parses all the provided playbooks
:param include_role_tasks: Should we include the role tasks
:param tags: Only add plays and tasks tagged with these values
:param skip_tags: Only add plays and tasks whose tags do not match these values
:param group_roles_by_name: Group roles by name instead of considering them as separate nodes with different IDs
:return: Tuple of the list of playbook nodes and the dictionary of the role usages: the key is the role and the
value is the set of plays that use the role.
"""
playbook_nodes = []
roles_usage: Dict[RoleNode, Set[PlayNode]] = {}
for playbook_file in self.playbook_filenames:
playbook_parser = PlaybookParser(
playbook_filename=playbook_file,
tags=tags,
skip_tags=skip_tags,
include_role_tasks=include_role_tasks,
group_roles_by_name=group_roles_by_name,
)
playbook_node = playbook_parser.parse()
playbook_nodes.append(playbook_node)
# Update the usage of the roles
roles_usage = merge_dicts(roles_usage, playbook_node.roles_usage())
return playbook_nodes, roles_usage

View file

@ -1,4 +1,4 @@
# Copyright (C) 2023 Mohamed El Mouctar HAIDARA
# Copyright (C) 2024 Mohamed El Mouctar HAIDARA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -167,7 +167,7 @@ class PlaybookParser(BaseParser):
add post_tasks
:return:
"""
display.display(f"Parsing playbook {self.playbook_filename}")
playbook = Playbook.load(
self.playbook_filename,
loader=self.data_loader,

View file

@ -18,7 +18,13 @@ from typing import Dict, Set, List
from ansible.utils.display import Display
from ansibleplaybookgrapher import BlockNode, RoleNode, TaskNode, PlayNode, PlaybookNode
from ansibleplaybookgrapher.graph_model import (
BlockNode,
RoleNode,
TaskNode,
PlayNode,
PlaybookNode,
)
from ansibleplaybookgrapher.renderer import PlaybookBuilder, Renderer
display = Display()

View file

@ -1,5 +1,5 @@
[metadata]
description-file = Readme.md
description_file = Readme.md
[bdist_wheel]
universal = 1

View file

@ -4,7 +4,7 @@ from typing import List
import pytest
from ansible.utils.display import Display
from ansibleplaybookgrapher import PlaybookParser
from ansibleplaybookgrapher.parser import PlaybookParser
from ansibleplaybookgrapher.cli import PlaybookGrapherCLI
from ansibleplaybookgrapher.graph_model import (
TaskNode,