Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch to modulegraph 2 #5808

Draft
wants to merge 174 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
174 commits
Select commit Hold shift + click to select a range
767a112
Initial checkin (building the graph doesn't work yet)
ronaldoussoren Dec 31, 2018
2c53da4
Tweaks to the documentation
ronaldoussoren Dec 31, 2018
3176bb7
Test public API symbols
ronaldoussoren Dec 31, 2018
4560486
Add internal API for extracting information about imports from an AST
ronaldoussoren Jan 1, 2019
e12bafd
Add bytecode scanner with tests
ronaldoussoren Jan 1, 2019
901f1f3
Add reference to PyPI distribution to nodes
ronaldoussoren Jan 1, 2019
06131d5
Update year in license file
ronaldoussoren Jan 3, 2019
2462aa8
Rename file to add filename extension
ronaldoussoren Jan 3, 2019
efbfccb
Initial work on graphbuilder (untested)
ronaldoussoren Jan 5, 2019
ffd469d
Closer to a working node builder
ronaldoussoren Jan 5, 2019
371e85c
Next step to working nodde builder
ronaldoussoren Jan 5, 2019
50c0883
Trivial code change to remove explicit conditional
ronaldoussoren Jan 6, 2019
ae0e4ae
GraphNode is never executed, mark body of property as nocover
ronaldoussoren Jan 6, 2019
fc92808
Fix import
ronaldoussoren Jan 6, 2019
08151f8
Graphbuilder work
ronaldoussoren Jan 6, 2019
3f9c494
Update tests for code in zipfiles
ronaldoussoren Jan 6, 2019
76d8e40
Graphbuilder now passes tests with 100% test coverage
ronaldoussoren Jan 6, 2019
3856c9e
Make ObjectGraph generic for the class of the nodes
ronaldoussoren Jan 6, 2019
07eed46
First steps to actually building a module graph
ronaldoussoren Jan 6, 2019
5bb01a8
Primarily adds a TODO file
ronaldoussoren Jan 6, 2019
c9d0a72
More updates to the graph building code
ronaldoussoren Jan 8, 2019
e9a0723
TODO updates
ronaldoussoren Jan 8, 2019
7244e94
Further test updates, with small changes to the code to match
ronaldoussoren Jan 9, 2019
1f393b9
This should finish the code for absolute imports
ronaldoussoren Jan 13, 2019
24253f7
Add some more TODOs
ronaldoussoren Jan 13, 2019
2b87f21
Restructure the exporter APIs (no implementation at this point)
ronaldoussoren Jan 13, 2019
13c31c1
More updates
ronaldoussoren Jan 15, 2019
fe4fbe0
Documentation updates
ronaldoussoren Jan 15, 2019
a112497
First stab at dotfile exporter.
ronaldoussoren Jan 15, 2019
4d27bb0
Dotfile update
ronaldoussoren Jan 15, 2019
87058b1
Fun with dot export
ronaldoussoren Jan 15, 2019
f2e619b
When a lot of names are defined in a module the bytecode for an impor…
ronaldoussoren Jan 16, 2019
c4c86b0
First stab at handling relative imports
ronaldoussoren Jan 16, 2019
a85e6ff
Update TODO list (including an XXX comment)
ronaldoussoren Jan 16, 2019
775891e
Further updates
ronaldoussoren Jan 17, 2019
86f14e8
Another testcase for EXTENDED_ARGS
ronaldoussoren Jan 19, 2019
5204936
Further work on relative imports
ronaldoussoren Jan 19, 2019
48e07c1
Some codestyle work
ronaldoussoren Jan 19, 2019
2fdbc7f
More work, including initial attempt at supporting "six.moves".
ronaldoussoren Jan 20, 2019
8bd7710
More progress on support for six.moves
ronaldoussoren Jan 20, 2019
404b280
Code cleanup
ronaldoussoren Jan 20, 2019
6a5811e
More work on finishing the graph implementation
ronaldoussoren Jan 22, 2019
fc66bed
Fix support for six (both six itself and vendored versions)
ronaldoussoren Jan 22, 2019
065f114
Change _process_namelist into method
ronaldoussoren Jan 22, 2019
bec8d40
Tweak implies definition for 3.6
ronaldoussoren Jan 22, 2019
0be93e6
1) Rewrite HTML builder, this now generates a simular report as in mo…
ronaldoussoren Jan 23, 2019
63f4316
* Fix typing error in "all_distributions"
ronaldoussoren Jan 23, 2019
4b197a2
Support files for SWIG tests
ronaldoussoren Jan 23, 2019
9595639
Empty test file for swig support
ronaldoussoren Jan 23, 2019
9cfddc5
Testing updates.
ronaldoussoren Jan 24, 2019
f8cdc8d
Write nicer readme file
ronaldoussoren Jan 25, 2019
3bc4c52
Configuration for readthedocs
ronaldoussoren Jan 26, 2019
81fbb3d
Finish support for SWIG
ronaldoussoren Jan 27, 2019
fc92aa2
Implement a nicer command-line interface, with most tests.
ronaldoussoren Jan 27, 2019
4f7914c
Some updates to the testsuite for the command-line
ronaldoussoren Jan 27, 2019
7718882
Documentation updates
ronaldoussoren Jan 27, 2019
ece5437
Add documentation
ronaldoussoren Jan 27, 2019
a961392
Various updates
ronaldoussoren Jan 28, 2019
5c920f5
Test updates
ronaldoussoren Jan 28, 2019
146ea11
Tests and fixes for some error cases (failed import in package init a…
ronaldoussoren Jan 29, 2019
632cd00
Slight tweak to get better coverage
ronaldoussoren Jan 29, 2019
ebc4199
Add test for submodule import when package init has syntax error
ronaldoussoren Jan 29, 2019
962d8b5
Add py.typed file to make it easier to typecheck users of modulegraph2
ronaldoussoren Jan 29, 2019
6acad2e
More fixes
ronaldoussoren Jan 29, 2019
c0a91ec
Documentation updates (still not finished)
ronaldoussoren Jan 30, 2019
26dd102
Support explicit namespace packages (setuptools and pkgutil)
ronaldoussoren Jan 31, 2019
df43ffe
The delayed caller mechanism isn't needed using some creative bookkee…
ronaldoussoren Jan 31, 2019
fec2e90
Code cleanup
ronaldoussoren Jan 31, 2019
072ed0c
Test coverage hacks...
ronaldoussoren Jan 31, 2019
d370ebf
implement "add_distribution" and move some code around
ronaldoussoren Feb 2, 2019
19721f6
Update license text
ronaldoussoren Feb 2, 2019
b4fa5c9
Add better support for running in virtual environments.
ronaldoussoren Feb 2, 2019
dba0fde
Add support for "as" clauses in import statement
ronaldoussoren Feb 2, 2019
cac153d
Move shared testing code to a test mixin
ronaldoussoren Feb 2, 2019
7c5d33d
Tweak the SWIG recipe
ronaldoussoren Feb 2, 2019
3a1eaf7
Forget to add some files to the repository
ronaldoussoren Feb 2, 2019
570c19f
Tweak _swig_support file to silence mypy messages
ronaldoussoren Feb 2, 2019
f20a1ca
Update version
ronaldoussoren Feb 2, 2019
9227fa8
Added tag modulegraph2-2.0a1 for changeset 13cb5bdfb906
ronaldoussoren Feb 2, 2019
d7de73f
Update index page
ronaldoussoren Feb 2, 2019
104a3e1
sync sphinx config with objectgraph
ronaldoussoren Feb 2, 2019
2c16d38
Attempt at fixing build issue @ readthedocs
ronaldoussoren Feb 2, 2019
d71b965
Another attempt at fixing a readthedocs issue
ronaldoussoren Feb 2, 2019
155e4b8
Another attempt at fixing a readthedocs issue
ronaldoussoren Feb 2, 2019
5826932
Another attempt at fixing a readthedocs issue
ronaldoussoren Feb 2, 2019
acfdcbd
yet another readthedocs attempt
ronaldoussoren Feb 2, 2019
f9e1062
Remove temporary setup.py
ronaldoussoren Feb 2, 2019
aa60ba3
Update to version 2 of the readthedocs config
ronaldoussoren Feb 2, 2019
b23513f
3.7 is not supported after all
ronaldoussoren Feb 2, 2019
2c6f941
Added tag modulegraph2-2.0a1 for changeset b62229ebaa18
ronaldoussoren Feb 2, 2019
2f16372
Change release date
ronaldoussoren Feb 2, 2019
182275f
Added tag modulegraph2-2.0a1 for changeset 791650d76a30
ronaldoussoren Feb 2, 2019
eeb69b1
Add Appveyor CI configuration
ronaldoussoren Feb 3, 2019
0363a4a
Add dummy test module for testing CI issue at Appveyor
ronaldoussoren Feb 3, 2019
515e6f9
Tweak appveyor configuration
ronaldoussoren Feb 3, 2019
ff2a095
Some tweaks to work better on windows (debugging while looking at App…
ronaldoussoren Feb 3, 2019
553f23f
Add linux support for testing on AppVeyor
ronaldoussoren Feb 3, 2019
3b2bfc5
Second attempt at testing Linux using AppVeyor
ronaldoussoren Feb 3, 2019
1c16376
Switch AppVeyors linux build back to 3.6, for some reason 3.7 won't work
ronaldoussoren Feb 3, 2019
7bdf508
The submodules for turtledemo have changed in 3.7, therefore add a sp…
ronaldoussoren Feb 3, 2019
817ff9f
Test fixes for python 3.6
ronaldoussoren Feb 3, 2019
49e5418
Updated comments
ronaldoussoren Feb 3, 2019
58f17c1
Turtledemo is not installed on the CI system, ignore
ronaldoussoren Feb 3, 2019
7b247a9
Fix for appveyor configuration
ronaldoussoren Feb 3, 2019
49932db
Switch to python3.6 for tooling, no 3.7 on my linux VM
ronaldoussoren Feb 3, 2019
24b750f
Switch to python 3.6 for running test commands
ronaldoussoren Feb 3, 2019
0f88fc6
Debugging file is not longer necessary.
ronaldoussoren Feb 3, 2019
9161747
Attempt at fixing failures on Windows
ronaldoussoren Feb 3, 2019
07cf9ed
Tweak tests to make it more likely they work on Windows
ronaldoussoren Feb 3, 2019
49605ca
Another attempt at fixing test failures on Windows
ronaldoussoren Feb 3, 2019
dace578
Another path that is different on windows
ronaldoussoren Feb 3, 2019
5117e6e
Another difference between windows and posix
ronaldoussoren Feb 3, 2019
437cab9
More windows support
ronaldoussoren Feb 3, 2019
747da82
This workaround is incorrect.
ronaldoussoren Feb 3, 2019
1a63beb
Attempt at a different workaround for building a C extension for a pa…
ronaldoussoren Feb 3, 2019
8c0b683
Remove test that is no longer necessary
ronaldoussoren Feb 3, 2019
559c63d
Yet another win32 attempt...
ronaldoussoren Feb 3, 2019
b06a986
Debug windows
ronaldoussoren Feb 3, 2019
cdd77e3
Debug windows
ronaldoussoren Feb 3, 2019
5f8382e
Remove dead code
ronaldoussoren Feb 3, 2019
d55bbaf
The library path is different on windows
ronaldoussoren Feb 3, 2019
e7db903
Different lib path is also relevant for the special cases
ronaldoussoren Feb 3, 2019
e446d22
Whoops, switch virtualenv and system paths...
ronaldoussoren Feb 3, 2019
08a8c39
Test pass on Linux and Window as well, with CI to automate the work.
ronaldoussoren Feb 3, 2019
cbe4d2f
Update changelog
ronaldoussoren Feb 4, 2019
e78a8aa
Minor code change to make MyPy happy.
ronaldoussoren Feb 4, 2019
429e589
Version update
ronaldoussoren Feb 4, 2019
7c894a7
Add support for python3.8 to tox.ini and Makefile
ronaldoussoren Feb 4, 2019
a9aaed6
Tweak PyPI information
ronaldoussoren Feb 5, 2019
fa686c3
Add google search console file
ronaldoussoren Apr 12, 2019
83dd8b7
Update readthedocs config
ronaldoussoren Apr 12, 2019
1225494
More readthedocs updates
ronaldoussoren Apr 12, 2019
308e863
Add sitemap
ronaldoussoren Apr 12, 2019
15b8f4e
Various minor changes related to git migration
ronaldoussoren Jan 6, 2020
b94cdbb
Small tweaks
ronaldoussoren Jan 14, 2020
86c6392
Fix references to bitbucket
ronaldoussoren Jan 19, 2020
f19c0d8
Add CI using GitHub actions
ronaldoussoren Jan 21, 2020
4d3662d
Tweak CI configuration
ronaldoussoren Jan 21, 2020
2d31bd6
Fix typo in readme
ronaldoussoren Jan 21, 2020
6cc858a
Tweak readme
ronaldoussoren Jan 21, 2020
3c71aa0
Tweak README
ronaldoussoren Jan 21, 2020
dfd3f63
Update test.yml
ronaldoussoren Jan 24, 2020
ce6667c
Fix URL in Readme
htgoebel May 10, 2020
283b03d
Fix link to source code repository.
htgoebel May 10, 2020
558cd12
Merge pull request #7 from htgoebel/master
ronaldoussoren May 13, 2020
fd8ed8f
Add Python 3.8 and 3.9 support to the package metadata
ronaldoussoren Jun 25, 2020
2be4d93
Merge branch 'master' of github.com:ronaldoussoren/modulegraph2
ronaldoussoren Jun 25, 2020
793a1ca
Fix typo in ReadMe.txt
ronaldoussoren Jul 26, 2020
b577535
Fix for #11: add_script did not work reliably
ronaldoussoren Sep 27, 2020
2e0b5fd
Add support for the way setuptools locates vendored packages
ronaldoussoren Sep 30, 2020
05fc9bb
Add missing files
ronaldoussoren Oct 6, 2020
b97c19a
Fix test failure due to additional files in dist-info directory
ronaldoussoren Oct 11, 2020
f3f6a93
Another test failure due to an additiona file in dist-info
ronaldoussoren Oct 11, 2020
34515fe
Typo in comment
ronaldoussoren Oct 11, 2020
54343fc
black changes
ronaldoussoren Oct 11, 2020
64be3d5
Fix issue in test case
ronaldoussoren Oct 11, 2020
cd43019
Add pre-commit configuration and fix some issues found
ronaldoussoren Jan 3, 2021
fbfc4d4
Merge branch 'fix' of https://github.com/xoviat/modulegraph2 into mod…
xoviat Apr 8, 2021
3e115b3
Merge branch 'develop' of https://github.com/pyinstaller/pyinstaller …
xoviat Apr 8, 2021
24db0d1
ci: update actions-pytest
xoviat Apr 8, 2021
ecdb887
ci: fix version
xoviat Apr 8, 2021
2fe4d07
tests: modulegraph2 -> PyInstaller.lib.modulegraph2
xoviat Apr 8, 2021
a01a276
setup: add dependencies
xoviat Apr 8, 2021
8d74105
fixup
xoviat Apr 8, 2021
8330dba
fixup
xoviat Apr 8, 2021
fdd0f0d
Merge branch 'develop' of https://github.com/pyinstaller/pyinstaller …
xoviat May 6, 2021
a14e1ee
fixup
xoviat May 6, 2021
69330a4
fixup
xoviat May 6, 2021
6b0f9ea
fixup
xoviat May 7, 2021
f926e45
modulegraph: rename methods to match modulegraph2
xoviat May 7, 2021
1d6baad
Merge branch 'rename-methods' into modulegraph2
xoviat May 7, 2021
e68df0f
Merge branch 'develop' of https://github.com/pyinstaller/pyinstaller …
xoviat May 7, 2021
8601b16
fixup
xoviat May 7, 2021
1cb2c2c
fixup
xoviat May 7, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ __pycache__/
/tests/python_exe.build
/tests/report.xml

/tests/unit/test_modulegraph2/**/*.pyd

/tests/**/build/
/tests/**/dist/

Expand Down
2 changes: 1 addition & 1 deletion PyInstaller/building/toc_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def __init__(self, graph, additional_files):
# Include files that were found by hooks.
# graph.iter_graph() should include only those modules that are reachable
# from top-level script.
for node in graph.iter_graph(start=graph._top_script_node):
for node in graph.iter_graph(node=graph._top_script_node):
# Update 'binaries', 'datas'
name = node.identifier
if name in additional_files:
Expand Down
36 changes: 26 additions & 10 deletions PyInstaller/depend/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
PURE_PYTHON_MODULE_TYPES, BINARY_MODULE_TYPES, VALID_MODULE_TYPES, \
BAD_MODULE_TYPES, MODULE_TYPES_TO_TOC_DICT
from ..lib.modulegraph.find_modules import get_implies
from ..lib.modulegraph.modulegraph import ModuleGraph
from ..lib.modulegraph2 import ModuleGraph
from ..lib.modulegraph2._modulegraph import DEFAULT_DEPENDENCY
from ..utils.hooks import collect_submodules, is_package


Expand Down Expand Up @@ -106,19 +107,25 @@ class PyiModuleGraph(ModuleGraph):
# Note: these levels are completely arbitrary and may be adjusted if needed.
LOG_LEVEL_MAPPING = {0: INFO, 1: DEBUG, 2: TRACE, 3: TRACE, 4: TRACE}

def __init__(self, pyi_homepath, user_hook_dirs=(), excludes=(), **kwargs):
super(PyiModuleGraph, self).__init__(excludes=excludes, **kwargs)
def __init__(self, pyi_homepath, user_hook_dirs=(), excludes=(), implies={}, **kwargs):
super(PyiModuleGraph, self).__init__(**kwargs)
self.add_excludes(excludes)
self.add_implies(implies)
# Homepath to the place where is PyInstaller located.
self._homepath = pyi_homepath
# modulegraph Node for the main python script that is analyzed
# by PyInstaller.
self._top_script_node = None
self.path = []

# Absolute paths of all user-defined hook directories.
self._excludes = excludes
self._reset(user_hook_dirs)
self._analyze_base_modules()

def set_setuptools_nspackages(self):
pass

def _reset(self, user_hook_dirs):
"""
Reset for another set of scripts.
Expand Down Expand Up @@ -309,7 +316,7 @@ def add_script(self, pathname, caller=None):
sys.exit(1)
# Create references from the top script to the base_modules in graph.
for node in self._base_modules:
self.add_edge(self._top_script_node, node)
self.add_edge(self._top_script_node, node, DEFAULT_DEPENDENCY)
# Return top-level script node.
return self._top_script_node
else:
Expand All @@ -318,7 +325,7 @@ def add_script(self, pathname, caller=None):
# top-level script.
caller = self._top_script_node
return super(PyiModuleGraph, self).add_script(
pathname, caller=caller)
pathname)


def process_post_graph_hooks(self):
Expand Down Expand Up @@ -348,7 +355,7 @@ def process_post_graph_hooks(self):
for module_name, module_hooks in self._hooks.items():
# Graph node for this module if imported or "None" otherwise.
module_node = self.find_node(
module_name, create_nspkg=False)
module_name)

# If this module has not been imported, temporarily ignore it.
# This module is retained in the cache, as a subsequently run
Expand Down Expand Up @@ -499,7 +506,7 @@ def get_code_objects(self):
"""
code_dict = {}
mod_types = PURE_PYTHON_MODULE_TYPES
for node in self.iter_graph(start=self._top_script_node):
for node in self.iter_graph(node=self._top_script_node):
# TODO This is terrible. To allow subclassing, types should never be
# directly compared. Use isinstance() instead, which is safer,
# simpler, and accepts sets. Most other calls to type() in the
Expand Down Expand Up @@ -534,7 +541,7 @@ def _make_toc(self, typecode=None, existing_TOC=None):
module_filter = re.compile(regex_str)

result = existing_TOC or TOC()
for node in self.iter_graph(start=self._top_script_node):
for node in self.iter_graph(node=self._top_script_node):
# Skip modules that are in base_library.zip.
if module_filter.match(node.identifier):
continue
Expand Down Expand Up @@ -625,6 +632,15 @@ def is_a_builtin(self, name) :
return False
return type(node).__name__ == 'BuiltinModule'

def flatten(self):
return self.iter_graph()

def import_hook(self, name, caller=None):
return self.iter_graph(node=self.add_module(name))

def find_node(self, node, create_nspkg=False):
return super().find_node(node)

def get_importers(self, name):
"""List all modules importing the module with the passed name.

Expand Down Expand Up @@ -718,7 +734,7 @@ def add_hiddenimports(self, module_list):
# Create references from the top script to the hidden import,
# even if found otherwise. Don't waste time checking whether it
# as actually added by this (test-) script.
self.add_edge(self._top_script_node, node)
self.add_edge(self._top_script_node, node, DEFAULT_DEPENDENCY)


def get_co_using_ctypes(self):
Expand All @@ -740,7 +756,7 @@ def get_co_using_ctypes(self):
node = self.find_node('ctypes')
if node:
referers = self.incoming(node)
for r in referers:
for (_, r) in referers:
# Under python 3.7 and earlier, if ctypes is added to
# hidden imports, one of referers ends up being None,
# causing #3825. Work around it.
Expand Down
8 changes: 4 additions & 4 deletions PyInstaller/depend/imphook.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ def _process_hook_func(self):
# Remove the graph link between the hooked module and item.
# This removes the 'item' node from the graph if no other
# links go to it (no other modules import it)
self.module_graph.removeReference(
self.module_graph.remove_all_edges(
hook_api.node, deleted_module_name)


Expand Down Expand Up @@ -569,7 +569,7 @@ def find_all_package_nodes(name):
# TODO: Optimize this by using a pattern and walking the graph
# only once.
for item in set(self.excludedimports):
excluded_node = self.module_graph.find_node(item, create_nspkg=False)
excluded_node = self.module_graph.find_node(item)
if excluded_node is None:
logger.info("Import to be excluded not found: %r", item)
continue
Expand All @@ -585,12 +585,12 @@ def find_all_package_nodes(name):
# modules, this `src` does import
references = set(
node.identifier
for node in self.module_graph.outgoing(src))
for (_, node) in self.module_graph.outgoing(src))

# Remove all of these imports which are also in
# "imports_to_remove".
for dest in imports_to_remove & references:
self.module_graph.removeReference(src, dest)
self.module_graph.remove_all_edges(src, dest)
logger.debug(
"Excluding import of %s from module %s", dest, src)

Expand Down
2 changes: 1 addition & 1 deletion PyInstaller/depend/imphookapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ def imports(self):
"""
List of the graph nodes of all modules directly imported by this module.
"""
return self.module_graph.iter_graph(start=self.module)
return self.module_graph.iter_graph(node=self.module)

def add_imports(self, *module_names):
"""
Expand Down
2 changes: 1 addition & 1 deletion PyInstaller/hooks/hook-sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def hook(hook_api):

hidden_imports_set = set()
known_imports = set()
for node in hook_api.module_graph.iter_graph(start=hook_api.module):
for node in hook_api.module_graph.iter_graph(node=hook_api.module):
if isinstance(node, SourceModule) and \
node.identifier.startswith('sqlalchemy.'):
known_imports.add(node.identifier)
Expand Down
65 changes: 65 additions & 0 deletions PyInstaller/lib/modulegraph2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""
A module import dependency graph for Python projects.

This package defines a class representing the
dependency graph between a collection of python
modules and scripts, as well as supporting functions
and classes.

The graph itself is an subclass of :class:`objectgraph.ObjectGraph`.

This module provides annotation for use with
`Mypy <https://mypy.readthedocs.io/en/latest/>`_.
"""
__version__ = "2.1"

from ._depinfo import DependencyInfo
from ._distributions import PyPIDistribution, all_distributions, distribution_named
from ._implies import Alias, Virtual
from ._modulegraph import ModuleGraph
from ._nodes import (
AliasNode,
BaseNode,
BuiltinModule,
BytecodeModule,
ExcludedModule,
ExtensionModule,
FrozenModule,
InvalidModule,
InvalidRelativeImport,
MissingModule,
Module,
NamespacePackage,
Package,
Script,
SourceModule,
VirtualNode,
)
from ._utilities import saved_sys_path

__all__ = (
"Alias",
"AliasNode",
"BaseNode",
"BuiltinModule",
"BytecodeModule",
"DependencyInfo",
"ExcludedModule",
"ExtensionModule",
"FrozenModule",
"InvalidModule",
"InvalidRelativeImport",
"MissingModule",
"Module",
"ModuleGraph",
"NamespacePackage",
"Package",
"PyPIDistribution",
"Script",
"SourceModule",
"all_distributions",
"distribution_named",
"saved_sys_path",
"Virtual",
"VirtualNode",
)