Skip to content

dependenpy ¤

Dependenpy package.

Show the inter-dependencies between modules of Python packages.

With dependenpy you will be able to analyze the internal dependencies in your Python code, i.e. which module needs which other module. You will then be able to build a dependency matrix and use it for other purposes.

If you read this message, you probably want to learn about the library and not the command-line tool: please refer to the README.md included in this package to get the link to the official documentation.

Modules:

  • cli

    Deprecated. Import from dependenpy directly.

  • debug

    Deprecated. Import from dependenpy directly.

  • dsm

    Deprecated. Import from dependenpy directly.

  • finder

    Deprecated. Import from dependenpy directly.

  • helpers

    Deprecated. Import from dependenpy directly.

  • node

    Deprecated. Import from dependenpy directly.

  • plugins

    Deprecated. Import from dependenpy directly.

  • structures

    Deprecated. Import from dependenpy directly.

Classes:

Functions:

  • get_parser

    Return the CLI argument parser.

  • guess_depth

    Guess the optimal depth to use for the given list of arguments.

  • main

    Run the main program.

Attributes:

  • CSV

    CSV format.

  • FORMAT

    Supported output formats.

  • JSON

    JSON format.

  • TEXT

    Plain text format.

CSV module-attribute ¤

CSV = 'csv'

CSV format.

FORMAT module-attribute ¤

FORMAT = (CSV, JSON, TEXT)

Supported output formats.

JSON module-attribute ¤

JSON = 'json'

JSON format.

DSM ¤

DSM(
    *packages: str,
    build_tree: bool = True,
    build_dependencies: bool = True,
    enforce_init: bool = True,
)

Bases: RootNode, NodeMixin, PrintMixin

DSM-capable class.

Technically speaking, a DSM instance is not a real DSM but more a tree representing the Python packages structure. However, it has the necessary methods to build a real DSM in the form of a square matrix, a dictionary or a tree-map.

Parameters:

  • *packages (str, default: () ) –

    List of packages to search for.

  • build_tree (bool, default: True ) –

    Auto-build the tree or not.

  • build_dependencies (bool, default: True ) –

    Auto-build the dependencies or not.

  • enforce_init (bool, default: True ) –

    If True, only treat directories if they contain an __init__.py file.

Methods:

  • __bool__

    Node as Boolean.

  • __contains__

    Get result of _contains, cache it and return it.

  • __getitem__

    Return the corresponding Package or Module object.

  • as_dict

    Return the dependencies as a dictionary.

  • as_graph

    Create a graph with self as node, cache it, return it.

  • as_matrix

    Create a matrix with self as node, cache it, return it.

  • as_treemap

    Return the dependencies as a TreeMap.

  • build_dependencies

    Recursively build the dependencies for sub-modules and sub-packages.

  • build_tree

    Build the Python packages tree.

  • get

    Get item through __getitem__ and cache the result.

  • get_target

    Get the result of _get_target, cache it and return it.

  • print

    Print the object in a file or on standard output by default.

  • print_graph

    Print the graph for self's nodes.

  • print_matrix

    Print the matrix for self's nodes.

  • print_treemap

    Print the matrix for self's nodes.

Attributes:

Source code in src/dependenpy/_internal/dsm.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def __init__(
    self,
    *packages: str,
    build_tree: bool = True,
    build_dependencies: bool = True,
    enforce_init: bool = True,
):
    """Initialization method.

    Parameters:
        *packages: List of packages to search for.
        build_tree: Auto-build the tree or not.
        build_dependencies: Auto-build the dependencies or not.
        enforce_init: If True, only treat directories if they contain an `__init__.py` file.
    """
    self.base_packages: tuple[str, ...] = packages
    """Packages initially specified."""
    self.finder: Finder = Finder()
    """Finder instance for locating packages and modules."""
    self.specs: list[PackageSpec] = []
    """List of package specifications found."""
    self.not_found: list[str] = []
    """List of packages that were not found."""
    self.enforce_init: bool = enforce_init
    """Whether to enforce the presence of `__init__.py` files."""

    specs = []
    for package in packages:
        spec = self.finder.find(package, enforce_init=enforce_init)
        if spec:
            specs.append(spec)
        else:
            self.not_found.append(package)

    if not specs:
        print("** dependenpy: DSM empty.", file=sys.stderr)  # noqa: T201

    self.specs = PackageSpec.combine(specs)

    for module in self.not_found:
        print(f"** dependenpy: Not found: {module}.", file=sys.stderr)  # noqa: T201

    super().__init__(build_tree)

    if build_tree and build_dependencies:
        self.build_dependencies()

base_packages instance-attribute ¤

base_packages: tuple[str, ...] = packages

Packages initially specified.

empty property ¤

empty: bool

Whether the node has neither modules nor packages.

Returns:

  • bool

    True if empty, False otherwise.

enforce_init instance-attribute ¤

enforce_init: bool = enforce_init

Whether to enforce the presence of __init__.py files.

finder instance-attribute ¤

finder: Finder = Finder()

Finder instance for locating packages and modules.

isdsm property ¤

isdsm: bool

Inherited from NodeMixin. Always True.

Returns:

  • bool

    Whether this object is a DSM.

ismodule property ¤

ismodule: bool

Property to check if object is instance of Module.

Returns:

  • bool

    Whether this object is a module.

ispackage property ¤

ispackage: bool

Property to check if object is instance of Package.

Returns:

  • bool

    Whether this object is a package.

modules instance-attribute ¤

modules: list[Module] = []

List of modules contained in the node.

not_found instance-attribute ¤

not_found: list[str] = []

List of packages that were not found.

packages instance-attribute ¤

packages: list[Package] = []

List of packages contained in the node.

specs instance-attribute ¤

specs: list[PackageSpec] = combine(specs)

List of package specifications found.

submodules property ¤

submodules: list[Module]

Property to return all sub-modules of the node, recursively.

Returns:

__bool__ ¤

__bool__() -> bool

Node as Boolean.

Returns:

  • bool

    Result of node.empty.

Source code in src/dependenpy/_internal/node.py
106
107
108
109
110
111
112
def __bool__(self) -> bool:
    """Node as Boolean.

    Returns:
        Result of node.empty.
    """
    return bool(self.modules or self.packages)

__contains__ ¤

__contains__(item: Package | Module) -> bool

Get result of _contains, cache it and return it.

Parameters:

Returns:

  • bool

    True if self contains item, False otherwise.

Source code in src/dependenpy/_internal/node.py
67
68
69
70
71
72
73
74
75
76
77
78
def __contains__(self, item: Package | Module) -> bool:
    """Get result of _contains, cache it and return it.

    Parameters:
        item: A package or module.

    Returns:
        True if self contains item, False otherwise.
    """
    if item not in self._contains_cache:
        self._contains_cache[item] = self._contains(item)
    return self._contains_cache[item]

__getitem__ ¤

__getitem__(item: str) -> Package | Module

Return the corresponding Package or Module object.

Parameters:

  • item (str) –

    Name of the package/module, dot-separated.

Raises:

  • KeyError

    When the package or module cannot be found.

Returns:

Source code in src/dependenpy/_internal/node.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def __getitem__(self, item: str) -> Package | Module:
    """Return the corresponding Package or Module object.

    Parameters:
        item: Name of the package/module, dot-separated.

    Raises:
        KeyError: When the package or module cannot be found.

    Returns:
        The corresponding object.
    """
    depth = item.count(".") + 1
    parts = item.split(".", 1)
    for module in self.modules:
        if parts[0] == module.name and depth == 1:
            return module
    for package in self.packages:
        if parts[0] == package.name:
            if depth == 1:
                return package
            obj = package.get(parts[1])
            if obj:
                return obj
    raise KeyError(item)

as_dict ¤

as_dict() -> dict

Return the dependencies as a dictionary.

Returns:

  • dict

    Dictionary of dependencies.

Source code in src/dependenpy/_internal/node.py
300
301
302
303
304
305
306
307
308
309
310
def as_dict(self) -> dict:
    """Return the dependencies as a dictionary.

    Returns:
        Dictionary of dependencies.
    """
    return {
        "name": str(self),
        "modules": [module.as_dict() for module in self.modules],
        "packages": [package.as_dict() for package in self.packages],
    }

as_graph ¤

as_graph(depth: int = 0) -> Graph

Create a graph with self as node, cache it, return it.

Parameters:

  • depth (int, default: 0 ) –

    Depth of the graph.

Returns:

  • Graph

    An instance of Graph.

Source code in src/dependenpy/_internal/node.py
312
313
314
315
316
317
318
319
320
321
322
323
def as_graph(self, depth: int = 0) -> Graph:
    """Create a graph with self as node, cache it, return it.

    Parameters:
        depth: Depth of the graph.

    Returns:
        An instance of Graph.
    """
    if depth not in self._graph_cache:
        self._graph_cache[depth] = Graph(self, depth=depth)  # type: ignore[arg-type]
    return self._graph_cache[depth]

as_matrix ¤

as_matrix(depth: int = 0) -> Matrix

Create a matrix with self as node, cache it, return it.

Parameters:

  • depth (int, default: 0 ) –

    Depth of the matrix.

Returns:

  • Matrix

    An instance of Matrix.

Source code in src/dependenpy/_internal/node.py
325
326
327
328
329
330
331
332
333
334
335
336
def as_matrix(self, depth: int = 0) -> Matrix:
    """Create a matrix with self as node, cache it, return it.

    Parameters:
        depth: Depth of the matrix.

    Returns:
        An instance of Matrix.
    """
    if depth not in self._matrix_cache:
        self._matrix_cache[depth] = Matrix(self, depth=depth)  # type: ignore[arg-type]
    return self._matrix_cache[depth]

as_treemap ¤

as_treemap() -> TreeMap

Return the dependencies as a TreeMap.

Returns:

  • TreeMap

    An instance of TreeMap.

Source code in src/dependenpy/_internal/node.py
338
339
340
341
342
343
344
345
346
def as_treemap(self) -> TreeMap:
    """Return the dependencies as a TreeMap.

    Returns:
        An instance of TreeMap.
    """
    if not self._treemap_cache:
        self._treemap_cache = TreeMap(self)
    return self._treemap_cache

build_dependencies ¤

build_dependencies() -> None

Recursively build the dependencies for sub-modules and sub-packages.

Iterate on node's modules then packages and call their build_dependencies methods.

Source code in src/dependenpy/_internal/node.py
217
218
219
220
221
222
223
224
225
226
def build_dependencies(self) -> None:
    """Recursively build the dependencies for sub-modules and sub-packages.

    Iterate on node's modules then packages and call their
    build_dependencies methods.
    """
    for module in self.modules:
        module.build_dependencies()
    for package in self.packages:
        package.build_dependencies()

build_tree ¤

build_tree() -> None

Build the Python packages tree.

Source code in src/dependenpy/_internal/dsm.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
def build_tree(self) -> None:
    """Build the Python packages tree."""
    for spec in self.specs:
        if spec.ismodule:
            self.modules.append(Module(spec.name, spec.path, dsm=self))
        else:
            self.packages.append(
                Package(
                    spec.name,
                    spec.path,
                    dsm=self,
                    limit_to=spec.limit_to,
                    build_tree=True,
                    build_dependencies=False,
                    enforce_init=self.enforce_init,
                ),
            )

get ¤

get(item: str) -> Package | Module

Get item through __getitem__ and cache the result.

Parameters:

  • item (str) –

    Name of package or module.

Returns:

Source code in src/dependenpy/_internal/node.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def get(self, item: str) -> Package | Module:
    """Get item through `__getitem__` and cache the result.

    Parameters:
        item: Name of package or module.

    Returns:
        The corresponding object.
    """
    if item not in self._item_cache:
        try:
            obj = self.__getitem__(item)
        except KeyError:
            obj = None
        self._item_cache[item] = obj
    return self._item_cache[item]

get_target ¤

get_target(target: str) -> Package | Module

Get the result of _get_target, cache it and return it.

Parameters:

  • target (str) –

    Target to find.

Returns:

  • Package | Module

    Package containing target or corresponding module.

Source code in src/dependenpy/_internal/node.py
173
174
175
176
177
178
179
180
181
182
183
184
def get_target(self, target: str) -> Package | Module:
    """Get the result of _get_target, cache it and return it.

    Parameters:
        target: Target to find.

    Returns:
        Package containing target or corresponding module.
    """
    if target not in self._target_cache:
        self._target_cache[target] = self._get_target(target)
    return self._target_cache[target]

print ¤

print(
    format: str | None = TEXT,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the object in a file or on standard output by default.

Parameters:

  • format (str | None, default: TEXT ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    Descriptor to an opened file (default to standard output).

  • **kwargs (Any, default: {} ) –

    Additional arguments.

Source code in src/dependenpy/_internal/helpers.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def print(self, format: str | None = TEXT, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the object in a file or on standard output by default.

    Parameters:
        format: Output format (csv, json or text).
        output: Descriptor to an opened file (default to standard output).
        **kwargs: Additional arguments.
    """
    if format is None:
        format = TEXT

    if format != TEXT:
        kwargs.pop("zero", "")

    if format == TEXT:
        print(self._to_text(**kwargs), file=output)
    elif format == CSV:
        print(self._to_csv(**kwargs), file=output)
    elif format == JSON:
        print(self._to_json(**kwargs), file=output)

print_graph ¤

print_graph(
    format: str | None = None,
    output: IO = stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None

Print the graph for self's nodes.

Parameters:

  • format (str | None, default: None ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    File descriptor on which to write.

  • depth (int, default: 0 ) –

    Depth of the graph.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments passed to graph.print.

Source code in src/dependenpy/_internal/node.py
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
def print_graph(
    self,
    format: str | None = None,  # noqa: A002
    output: IO = sys.stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None:
    """Print the graph for self's nodes.

    Parameters:
        format: Output format (csv, json or text).
        output: File descriptor on which to write.
        depth: Depth of the graph.
        **kwargs: Additional keyword arguments passed to `graph.print`.
    """
    graph = self.as_graph(depth=depth)
    graph.print(format=format, output=output, **kwargs)

print_matrix ¤

print_matrix(
    format: str | None = None,
    output: IO = stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None

Print the matrix for self's nodes.

Parameters:

  • format (str | None, default: None ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    File descriptor on which to write.

  • depth (int, default: 0 ) –

    Depth of the matrix.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments passed to matrix.print.

Source code in src/dependenpy/_internal/node.py
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
def print_matrix(
    self,
    format: str | None = None,  # noqa: A002
    output: IO = sys.stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None:
    """Print the matrix for self's nodes.

    Parameters:
        format: Output format (csv, json or text).
        output: File descriptor on which to write.
        depth: Depth of the matrix.
        **kwargs: Additional keyword arguments passed to `matrix.print`.
    """
    matrix = self.as_matrix(depth=depth)
    matrix.print(format=format, output=output, **kwargs)

print_treemap ¤

print_treemap(
    format: str | None = None,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the matrix for self's nodes.

Parameters:

  • format (str | None, default: None ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    File descriptor on which to write.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments passed to treemap.print.

Source code in src/dependenpy/_internal/node.py
264
265
266
267
268
269
270
271
272
273
def print_treemap(self, format: str | None = None, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the matrix for self's nodes.

    Parameters:
        format: Output format (csv, json or text).
        output: File descriptor on which to write.
        **kwargs: Additional keyword arguments passed to `treemap.print`.
    """
    treemap = self.as_treemap()
    treemap.print(format=format, output=output, **kwargs)

Dependency ¤

Dependency(
    source: Module,
    lineno: int,
    target: str | Module | Package,
    what: str | None = None,
)

Dependency class.

Represent a dependency from a module to another.

Parameters:

  • source (Module) –

    Source Module.

  • lineno (int) –

    Number of line at which import statement occurs.

  • target (str | Module | Package) –

    The target node.

  • what (str | None, default: None ) –

    What is imported (optional).

Attributes:

  • external (bool) –

    Property to tell if the dependency's target is a valid node.

  • lineno

    Line number of the import statement.

  • source

    Source module.

  • target

    Target module or package.

  • what

    What is imported (optional).

Source code in src/dependenpy/_internal/dsm.py
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
def __init__(self, source: Module, lineno: int, target: str | Module | Package, what: str | None = None) -> None:
    """Initialization method.

    Parameters:
        source: Source Module.
        lineno: Number of line at which import statement occurs.
        target: The target node.
        what: What is imported (optional).
    """
    self.source = source
    """Source module."""
    self.lineno = lineno
    """Line number of the import statement."""
    self.target = target
    """Target module or package."""
    self.what = what
    """What is imported (optional)."""

external property ¤

external: bool

Property to tell if the dependency's target is a valid node.

Returns:

  • bool

    Whether the dependency's target is a valid node.

lineno instance-attribute ¤

lineno = lineno

Line number of the import statement.

source instance-attribute ¤

source = source

Source module.

target instance-attribute ¤

target = target

Target module or package.

what instance-attribute ¤

what = what

What is imported (optional).

Edge ¤

Edge(
    vertex_out: Vertex, vertex_in: Vertex, weight: int = 1
)

Edge class. Used in Graph class.

Parameters:

  • vertex_out (Vertex) –

    source vertex (edge going out).

  • vertex_in (Vertex) –

    target vertex (edge going in).

  • weight (int, default: 1 ) –

    weight of the edge.

Methods:

  • go_from

    Tell the edge to go out from this vertex.

  • go_in

    Tell the edge to go into this vertex.

Attributes:

Source code in src/dependenpy/_internal/structures.py
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
def __init__(self, vertex_out: Vertex, vertex_in: Vertex, weight: int = 1) -> None:
    """Initialization method.

    Parameters:
        vertex_out (Vertex): source vertex (edge going out).
        vertex_in (Vertex): target vertex (edge going in).
        weight (int): weight of the edge.
    """
    self.vertex_out: Vertex | None = None
    """Outgoing vertex."""
    self.vertex_in: Vertex | None = None
    """Incoming vertex."""
    self.weight = weight
    """Weight of the edge."""
    self.go_from(vertex_out)
    self.go_in(vertex_in)

vertex_in instance-attribute ¤

vertex_in: Vertex | None = None

Incoming vertex.

vertex_out instance-attribute ¤

vertex_out: Vertex | None = None

Outgoing vertex.

weight instance-attribute ¤

weight = weight

Weight of the edge.

go_from ¤

go_from(vertex: Vertex) -> None

Tell the edge to go out from this vertex.

Parameters:

  • vertex (Vertex) –

    vertex to go from.

Source code in src/dependenpy/_internal/structures.py
273
274
275
276
277
278
279
280
281
282
def go_from(self, vertex: Vertex) -> None:
    """Tell the edge to go out from this vertex.

    Parameters:
        vertex (Vertex): vertex to go from.
    """
    if self.vertex_out:
        self.vertex_out.edges_out.remove(self)
    self.vertex_out = vertex
    vertex.edges_out.add(self)

go_in ¤

go_in(vertex: Vertex) -> None

Tell the edge to go into this vertex.

Parameters:

  • vertex (Vertex) –

    vertex to go into.

Source code in src/dependenpy/_internal/structures.py
284
285
286
287
288
289
290
291
292
293
def go_in(self, vertex: Vertex) -> None:
    """Tell the edge to go into this vertex.

    Parameters:
        vertex (Vertex): vertex to go into.
    """
    if self.vertex_in:
        self.vertex_in.edges_in.remove(self)
    self.vertex_in = vertex
    vertex.edges_in.add(self)

Finder ¤

Finder(finders: list[type] | None = None)

Main package finder class.

Initialize it with a list of package finder classes (not instances).

Parameters:

  • finders (list[type] | None, default: None ) –

    list of package finder classes (not instances) in a specific order. Default: [LocalPackageFinder, InstalledPackageFinder].

Methods:

  • find

    Find a package using package finders.

Attributes:

Source code in src/dependenpy/_internal/finder.py
153
154
155
156
157
158
159
160
161
162
163
164
165
166
def __init__(self, finders: list[type] | None = None):
    """Initialization method.

    Parameters:
        finders: list of package finder classes (not instances) in a specific
            order. Default: [LocalPackageFinder, InstalledPackageFinder].
    """
    self.finders: list[PackageFinder]
    """Selected finders."""
    if finders is None:
        finder_instances = [LocalPackageFinder(), InstalledPackageFinder()]
    else:
        finder_instances = [finder() for finder in finders]
    self.finders = finder_instances

finders instance-attribute ¤

finders: list[PackageFinder] = finder_instances

Selected finders.

find ¤

find(package: str, **kwargs: Any) -> PackageSpec | None

Find a package using package finders.

Return the first package found.

Parameters:

  • package (str) –

    package to find.

  • **kwargs (Any, default: {} ) –

    additional keyword arguments used by finders.

Returns:

Source code in src/dependenpy/_internal/finder.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
def find(self, package: str, **kwargs: Any) -> PackageSpec | None:
    """Find a package using package finders.

    Return the first package found.

    Parameters:
        package: package to find.
        **kwargs: additional keyword arguments used by finders.

    Returns:
        Package spec or None.
    """
    for finder in self.finders:
        package_spec = finder.find(package, **kwargs)
        if package_spec:
            return package_spec
    return None

Graph ¤

Graph(*nodes: DSM | Package | Module, depth: int = 0)

Bases: PrintMixin

Graph class.

A class to build a graph given a list of nodes. After instantiation, it has two attributes: vertices, the set of nodes, and edges, the set of edges.

An intermediary matrix is built to ease the creation of the graph.

Parameters:

  • *nodes (list of DSM/Package/Module, default: () ) –

    the nodes on which to build the graph.

  • depth (int, default: 0 ) –

    the depth of the intermediary matrix. See the documentation for Matrix class.

Methods:

  • print

    Print the object in a file or on standard output by default.

Attributes:

  • edges

    Set of edges in the graph.

  • vertices

    Set of vertices in the graph.

Source code in src/dependenpy/_internal/structures.py
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
def __init__(self, *nodes: DSM | Package | Module, depth: int = 0) -> None:
    """Initialization method.

    An intermediary matrix is built to ease the creation of the graph.

    Parameters:
        *nodes (list of DSM/Package/Module):
            the nodes on which to build the graph.
        depth (int): the depth of the intermediary matrix. See
            the documentation for Matrix class.
    """
    self.edges = set()
    """Set of edges in the graph."""
    vertices = []
    matrix = Matrix(*nodes, depth=depth)
    for key in matrix.keys:
        vertices.append(Vertex(key))
    for line_index, line in enumerate(matrix.data):
        for col_index, cell in enumerate(line):
            if cell > 0:
                self.edges.add(Edge(vertices[line_index], vertices[col_index], weight=cell))
    self.vertices = set(vertices)
    """Set of vertices in the graph."""

edges instance-attribute ¤

edges = set()

Set of edges in the graph.

vertices instance-attribute ¤

vertices = set(vertices)

Set of vertices in the graph.

print ¤

print(
    format: str | None = TEXT,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the object in a file or on standard output by default.

Parameters:

  • format (str | None, default: TEXT ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    Descriptor to an opened file (default to standard output).

  • **kwargs (Any, default: {} ) –

    Additional arguments.

Source code in src/dependenpy/_internal/helpers.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def print(self, format: str | None = TEXT, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the object in a file or on standard output by default.

    Parameters:
        format: Output format (csv, json or text).
        output: Descriptor to an opened file (default to standard output).
        **kwargs: Additional arguments.
    """
    if format is None:
        format = TEXT

    if format != TEXT:
        kwargs.pop("zero", "")

    if format == TEXT:
        print(self._to_text(**kwargs), file=output)
    elif format == CSV:
        print(self._to_csv(**kwargs), file=output)
    elif format == JSON:
        print(self._to_json(**kwargs), file=output)

InstalledPackageFinder ¤

Bases: PackageFinder

Finder to find installed Python packages using importlib.

Methods:

  • find

    Find method.

find ¤

find(package: str, **kwargs: Any) -> PackageSpec | None

Find method.

Parameters:

  • package (str) –

    package to find.

  • **kwargs (Any, default: {} ) –

    additional keyword arguments.

Returns:

Source code in src/dependenpy/_internal/finder.py
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
def find(self, package: str, **kwargs: Any) -> PackageSpec | None:  # noqa: ARG002
    """Find method.

    Parameters:
        package: package to find.
        **kwargs: additional keyword arguments.

    Returns:
        Package spec or None.
    """
    spec = find_spec(package)
    if spec is None:
        return None
    if "." in package:
        package, rest = package.split(".", 1)
        limit = [rest]
        spec = find_spec(package)
    else:
        limit = []
    if spec is not None:
        if spec.submodule_search_locations:
            path = spec.submodule_search_locations[0]
        elif spec.origin and spec.origin != "built-in":
            path = spec.origin
        else:
            return None
        return PackageSpec(spec.name, path, limit)
    return None

InternalDependencies ¤

Bases: Provider

Dependenpy provider for Archan.

Methods:

  • get_data

    Provide matrix data for internal dependencies in a set of packages.

Attributes:

argument_list class-attribute instance-attribute ¤

argument_list = (
    Argument(
        "packages",
        list,
        "The list of packages to check for.",
    ),
    Argument(
        "enforce_init",
        bool,
        default=True,
        description="Whether to assert presence of __init__.py files in directories.",
    ),
    Argument(
        "depth", int, "The depth of the matrix to generate."
    ),
)

List of arguments for the provider.

description class-attribute instance-attribute ¤

description = "Provide matrix data about internal dependencies in a set of packages."

Description of the provider.

identifier class-attribute instance-attribute ¤

identifier = 'dependenpy.InternalDependencies'

Identifier of the provider.

name class-attribute instance-attribute ¤

name = 'Internal Dependencies'

Name of the provider.

get_data ¤

get_data(
    packages: list[str],
    enforce_init: bool = True,
    depth: int | None = None,
) -> DSM

Provide matrix data for internal dependencies in a set of packages.

Parameters:

  • packages (list[str]) –

    The list of packages to check for.

  • enforce_init (bool, default: True ) –

    Whether to assert presence of init.py files in directories.

  • depth (int | None, default: None ) –

    The depth of the matrix to generate.

Returns:

  • DSM

    Instance of archan DSM.

Source code in src/dependenpy/_internal/plugins.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def get_data(
    self,
    packages: list[str],
    enforce_init: bool = True,  # noqa: FBT001,FBT002
    depth: int | None = None,
) -> archan.DSM:
    """Provide matrix data for internal dependencies in a set of packages.

    Parameters:
        packages: The list of packages to check for.
        enforce_init: Whether to assert presence of __init__.py files in directories.
        depth: The depth of the matrix to generate.

    Returns:
        Instance of archan DSM.
    """
    dsm = DependenpyDSM(*packages, enforce_init=enforce_init)
    if depth is None:
        depth = guess_depth(packages)
    matrix = dsm.as_matrix(depth=depth)
    return archan.DesignStructureMatrix(data=matrix.data, entities=matrix.keys)

LeafNode ¤

LeafNode()

Shared code between Package and Module.

Methods:

Attributes:

  • depth (int) –

    Property to tell the depth of the node in the tree.

  • root (Package) –

    Property to return the root of this node.

Source code in src/dependenpy/_internal/node.py
352
353
354
def __init__(self):
    """Initialization method."""
    self._depth_cache = None

depth property ¤

depth: int

Property to tell the depth of the node in the tree.

Returns:

  • int

    The node's depth in the tree.

root property ¤

root: Package

Property to return the root of this node.

Returns:

  • Package ( Package ) –

    this node's root package.

absolute_name ¤

absolute_name(depth: int = 0) -> str

Return the absolute name of the node.

Concatenate names from root to self within depth.

Parameters:

  • depth (int, default: 0 ) –

    Maximum depth to go to.

Returns:

  • str

    Absolute name of the node (until given depth is reached).

Source code in src/dependenpy/_internal/node.py
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
def absolute_name(self, depth: int = 0) -> str:
    """Return the absolute name of the node.

    Concatenate names from root to self within depth.

    Parameters:
        depth: Maximum depth to go to.

    Returns:
        Absolute name of the node (until given depth is reached).
    """
    node: Package
    node, node_depth = self, self.depth  # type: ignore[assignment]
    if depth < 1:
        depth = node_depth
    while node_depth > depth and node.package is not None:
        node = node.package
        node_depth -= 1
    names = []
    while node is not None:
        names.append(node.name)
        node = node.package  # type: ignore[assignment]
    return ".".join(reversed(names))

LocalPackageFinder ¤

Bases: PackageFinder

Finder to find local packages (directories on the disk).

Methods:

  • find

    Find method.

find ¤

find(package: str, **kwargs: Any) -> PackageSpec | None

Find method.

Parameters:

  • package (str) –

    Package to find.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments.

Returns:

Source code in src/dependenpy/_internal/finder.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
def find(self, package: str, **kwargs: Any) -> PackageSpec | None:
    """Find method.

    Parameters:
        package: Package to find.
        **kwargs: Additional keyword arguments.

    Returns:
        Package spec or None.
    """
    if not exists(package):
        return None
    name, path = None, None
    enforce_init = kwargs.pop("enforce_init", True)
    if isdir(package):
        if isfile(join(package, "__init__.py")) or not enforce_init:
            name, path = basename(package), package
    elif isfile(package) and package.endswith(".py"):
        name, path = splitext(basename(package))[0], package
    if name and path:
        return PackageSpec(name, path)
    return None

Matrix ¤

Matrix(*nodes: DSM | Package | Module, depth: int = 0)

Bases: PrintMixin

Matrix class.

A class to build a matrix given a list of nodes. After instantiation, it has two attributes: data, a 2-dimensions array, and keys, the names of the entities in the corresponding order.

Parameters:

  • *nodes (DSM | Package | Module, default: () ) –

    The nodes on which to build the matrix.

  • depth (int, default: 0 ) –

    The depth of the matrix. This depth is always absolute, meaning that building a matrix with a sub-package "A.B.C" and a depth of 1 will return a matrix of size 1, containing A only. To see the matrix for the sub-modules and sub-packages in C, you will have to give depth=4.

Methods:

  • cast

    Cast a set of keys and an array to a Matrix object.

  • print

    Print the object in a file or on standard output by default.

Attributes:

  • data

    The data of the matrix.

  • keys

    The keys of the matrix.

  • size

    The size of the matrix.

  • total (int) –

    Return the total number of dependencies within this matrix.

Source code in src/dependenpy/_internal/structures.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def __init__(self, *nodes: DSM | Package | Module, depth: int = 0):
    """Initialization method.

    Parameters:
        *nodes: The nodes on which to build the matrix.
        depth: The depth of the matrix. This depth is always
            absolute, meaning that building a matrix with a sub-package
            "A.B.C" and a depth of 1 will return a matrix of size 1,
            containing A only. To see the matrix for the sub-modules and
            sub-packages in C, you will have to give depth=4.
    """
    modules: list[Module] = []
    for node in nodes:
        if node.ismodule:
            modules.append(node)  # type: ignore[arg-type]
        elif node.ispackage or node.isdsm:
            modules.extend(node.submodules)  # type: ignore[union-attr]

    if depth < 1:
        keys = modules
    else:
        keys = []
        for module in modules:
            if module.depth <= depth:
                keys.append(module)
                continue
            package = module.package
            while package.depth > depth and package.package and package not in nodes:  # type: ignore[union-attr]
                package = package.package  # type: ignore[union-attr]
            if package not in keys:
                keys.append(package)  # type: ignore[arg-type]

    size = len(keys)
    data = [[0] * size for _ in range(size)]
    keys = sorted(keys, key=lambda key: key.absolute_name())

    if depth < 1:
        for index, key in enumerate(keys):
            key.index = index  # type: ignore[attr-defined]
        for index, key in enumerate(keys):
            for dep in key.dependencies:
                if dep.external:
                    continue
                if dep.target.ismodule and dep.target in keys:  # type: ignore[union-attr]
                    data[index][dep.target.index] += 1  # type: ignore[index,union-attr]
                elif dep.target.ispackage:  # type: ignore[union-attr]
                    init = dep.target.get("__init__")  # type: ignore[union-attr]
                    if init is not None and init in keys:
                        data[index][init.index] += 1  # type: ignore[union-attr]
    else:
        for row, row_key in enumerate(keys):
            for col, col_key in enumerate(keys):
                data[row][col] = row_key.cardinal(to=col_key)

    self.size = size
    """The size of the matrix."""
    self.keys = [key.absolute_name() for key in keys]
    """The keys of the matrix."""
    self.data = data
    """The data of the matrix."""

data instance-attribute ¤

data = data

The data of the matrix.

keys instance-attribute ¤

keys = [(absolute_name()) for key in keys]

The keys of the matrix.

size instance-attribute ¤

size = size

The size of the matrix.

total property ¤

total: int

Return the total number of dependencies within this matrix.

Returns:

  • int

    The total number of dependencies.

cast staticmethod ¤

cast(keys: list[str], data: list[list[int]]) -> Matrix

Cast a set of keys and an array to a Matrix object.

Parameters:

Returns:

Source code in src/dependenpy/_internal/structures.py
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
@staticmethod
def cast(keys: list[str], data: list[list[int]]) -> Matrix:
    """Cast a set of keys and an array to a Matrix object.

    Arguments:
        keys: The matrix keys.
        data: The matrix data.

    Returns:
        A new matrix.
    """
    matrix = Matrix()
    matrix.keys = copy.deepcopy(keys)
    matrix.data = copy.deepcopy(data)
    return matrix

print ¤

print(
    format: str | None = TEXT,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the object in a file or on standard output by default.

Parameters:

  • format (str | None, default: TEXT ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    Descriptor to an opened file (default to standard output).

  • **kwargs (Any, default: {} ) –

    Additional arguments.

Source code in src/dependenpy/_internal/helpers.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def print(self, format: str | None = TEXT, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the object in a file or on standard output by default.

    Parameters:
        format: Output format (csv, json or text).
        output: Descriptor to an opened file (default to standard output).
        **kwargs: Additional arguments.
    """
    if format is None:
        format = TEXT

    if format != TEXT:
        kwargs.pop("zero", "")

    if format == TEXT:
        print(self._to_text(**kwargs), file=output)
    elif format == CSV:
        print(self._to_csv(**kwargs), file=output)
    elif format == JSON:
        print(self._to_json(**kwargs), file=output)

Module ¤

Module(
    name: str,
    path: str,
    dsm: DSM | None = None,
    package: Package | None = None,
)

Bases: LeafNode, NodeMixin, PrintMixin

Module class.

This class represents a Python module (a Python file).

Parameters:

  • name (str) –

    Name of the module.

  • path (str) –

    Path to the module.

  • dsm (DSM | None, default: None ) –

    Parent DSM.

  • package (Package | None, default: None ) –

    Parent Package.

Methods:

  • __contains__

    Whether given item is contained inside this module.

  • absolute_name

    Return the absolute name of the node.

  • as_dict

    Return the dependencies as a dictionary.

  • build_dependencies

    Build the dependencies for this module.

  • cardinal

    Return the number of dependencies of this module to the given node.

  • get_imports

    Return all the import statements given an AST body (AST nodes).

  • parse_code

    Read the source code and return all the import statements.

  • print

    Print the object in a file or on standard output by default.

Attributes:

  • RECURSIVE_NODES

    Nodes that can be recursive.

  • dependencies (list[Dependency]) –

    List of dependencies.

  • depth (int) –

    Property to tell the depth of the node in the tree.

  • dsm

    Parent DSM.

  • isdsm (bool) –

    Property to check if object is instance of DSM.

  • ismodule (bool) –

    Inherited from NodeMixin. Always True.

  • ispackage (bool) –

    Property to check if object is instance of Package.

  • name

    Name of the module.

  • package

    Package to which the module belongs.

  • path

    Path to the module.

  • root (Package) –

    Property to return the root of this node.

Source code in src/dependenpy/_internal/dsm.py
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
def __init__(self, name: str, path: str, dsm: DSM | None = None, package: Package | None = None) -> None:
    """Initialization method.

    Parameters:
        name: Name of the module.
        path: Path to the module.
        dsm: Parent DSM.
        package: Parent Package.
    """
    super().__init__()
    self.name = name
    """Name of the module."""
    self.path = path
    """Path to the module."""
    self.package = package
    """Package to which the module belongs."""
    self.dsm = dsm
    """Parent DSM."""
    self.dependencies: list[Dependency] = []
    """List of dependencies."""

RECURSIVE_NODES class-attribute instance-attribute ¤

RECURSIVE_NODES = (
    ClassDef,
    FunctionDef,
    If,
    IfExp,
    Try,
    With,
    ExceptHandler,
)

Nodes that can be recursive.

dependencies instance-attribute ¤

dependencies: list[Dependency] = []

List of dependencies.

depth property ¤

depth: int

Property to tell the depth of the node in the tree.

Returns:

  • int

    The node's depth in the tree.

dsm instance-attribute ¤

dsm = dsm

Parent DSM.

isdsm property ¤

isdsm: bool

Property to check if object is instance of DSM.

Returns:

  • bool

    Whether this object is a DSM.

ismodule property ¤

ismodule: bool

Inherited from NodeMixin. Always True.

Returns:

  • bool

    Whether this object is a module.

ispackage property ¤

ispackage: bool

Property to check if object is instance of Package.

Returns:

  • bool

    Whether this object is a package.

name instance-attribute ¤

name = name

Name of the module.

package instance-attribute ¤

package = package

Package to which the module belongs.

path instance-attribute ¤

path = path

Path to the module.

root property ¤

root: Package

Property to return the root of this node.

Returns:

  • Package ( Package ) –

    this node's root package.

__contains__ ¤

__contains__(item: Package | Module) -> bool

Whether given item is contained inside this module.

Parameters:

Returns:

  • bool

    True if self is item or item is self's package and self if an __init__ module.

Source code in src/dependenpy/_internal/dsm.py
274
275
276
277
278
279
280
281
282
283
284
285
286
def __contains__(self, item: Package | Module) -> bool:
    """Whether given item is contained inside this module.

    Parameters:
        item (Package/Module): a package or module.

    Returns:
        True if self is item or item is self's package and
            self if an `__init__` module.
    """
    if self is item:
        return True
    return self.package is item and self.name == "__init__"

absolute_name ¤

absolute_name(depth: int = 0) -> str

Return the absolute name of the node.

Concatenate names from root to self within depth.

Parameters:

  • depth (int, default: 0 ) –

    Maximum depth to go to.

Returns:

  • str

    Absolute name of the node (until given depth is reached).

Source code in src/dependenpy/_internal/node.py
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
def absolute_name(self, depth: int = 0) -> str:
    """Return the absolute name of the node.

    Concatenate names from root to self within depth.

    Parameters:
        depth: Maximum depth to go to.

    Returns:
        Absolute name of the node (until given depth is reached).
    """
    node: Package
    node, node_depth = self, self.depth  # type: ignore[assignment]
    if depth < 1:
        depth = node_depth
    while node_depth > depth and node.package is not None:
        node = node.package
        node_depth -= 1
    names = []
    while node is not None:
        names.append(node.name)
        node = node.package  # type: ignore[assignment]
    return ".".join(reversed(names))

as_dict ¤

as_dict(absolute: bool = False) -> dict

Return the dependencies as a dictionary.

Parameters:

  • absolute (bool, default: False ) –

    Whether to use the absolute name.

Returns:

  • dict

    Dictionary of dependencies.

Source code in src/dependenpy/_internal/dsm.py
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
def as_dict(self, absolute: bool = False) -> dict:  # noqa: FBT001,FBT002
    """Return the dependencies as a dictionary.

    Arguments:
        absolute: Whether to use the absolute name.

    Returns:
        Dictionary of dependencies.
    """
    return {
        "name": self.absolute_name() if absolute else self.name,
        "path": self.path,
        "dependencies": [
            {
                # 'source': d.source.absolute_name(),  # redundant
                "target": dep.target if dep.external else dep.target.absolute_name(),  # type: ignore[union-attr]
                "lineno": dep.lineno,
                "what": dep.what,
                "external": dep.external,
            }
            for dep in self.dependencies
        ],
    }

build_dependencies ¤

build_dependencies() -> None

Build the dependencies for this module.

Parse the code with ast, find all the import statements, convert them into Dependency objects.

Source code in src/dependenpy/_internal/dsm.py
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
def build_dependencies(self) -> None:
    """Build the dependencies for this module.

    Parse the code with ast, find all the import statements, convert
    them into Dependency objects.
    """
    highest = self.dsm or self.root
    for import_ in self.parse_code():
        target = highest.get_target(import_["target"])
        if target:
            what = import_["target"].split(".")[-1]
            if what != target.name:
                import_["what"] = what
            import_["target"] = target
        self.dependencies.append(Dependency(source=self, **import_))

cardinal ¤

cardinal(to: Package | Module) -> int

Return the number of dependencies of this module to the given node.

Parameters:

Returns:

  • int

    Number of dependencies.

Source code in src/dependenpy/_internal/dsm.py
405
406
407
408
409
410
411
412
413
414
def cardinal(self, to: Package | Module) -> int:
    """Return the number of dependencies of this module to the given node.

    Parameters:
        to: The target node.

    Returns:
        Number of dependencies.
    """
    return len([dep for dep in self.dependencies if not dep.external and dep.target in to])  # type: ignore[operator]

get_imports ¤

get_imports(ast_body: Sequence[AST]) -> list[dict]

Return all the import statements given an AST body (AST nodes).

Returns:

Source code in src/dependenpy/_internal/dsm.py
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
def get_imports(self, ast_body: Sequence[ast.AST]) -> list[dict]:
    """Return all the import statements given an AST body (AST nodes).

    Parameters:
        The body to filter.

    Returns:
        The import statements.
    """
    imports: list[dict] = []
    for node in ast_body:
        if isinstance(node, ast.Import):
            imports.extend({"target": name.name, "lineno": node.lineno} for name in node.names)
        elif isinstance(node, ast.ImportFrom):
            for name in node.names:
                abs_name = self.absolute_name(self.depth - node.level) + "." if node.level > 0 else ""
                node_module = node.module + "." if node.module else ""
                name = abs_name + node_module + name.name  # type: ignore[assignment]  # noqa: PLW2901
                imports.append({"target": name, "lineno": node.lineno})
        elif isinstance(node, Module.RECURSIVE_NODES):
            imports.extend(self.get_imports(node.body))  # type: ignore[arg-type]
            if isinstance(node, ast.Try):
                imports.extend(self.get_imports(node.finalbody))
    return imports

parse_code ¤

parse_code() -> list[dict]

Read the source code and return all the import statements.

Returns:

Source code in src/dependenpy/_internal/dsm.py
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
def parse_code(self) -> list[dict]:
    """Read the source code and return all the import statements.

    Returns:
        The import statements.
    """
    code = Path(self.path).read_text(encoding="utf-8")
    try:
        body = ast.parse(code).body
    except SyntaxError:
        code = code.encode("utf-8")  # type: ignore[assignment]
        try:
            body = ast.parse(code).body
        except SyntaxError:
            return []
    return self.get_imports(body)

print ¤

print(
    format: str | None = TEXT,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the object in a file or on standard output by default.

Parameters:

  • format (str | None, default: TEXT ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    Descriptor to an opened file (default to standard output).

  • **kwargs (Any, default: {} ) –

    Additional arguments.

Source code in src/dependenpy/_internal/helpers.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def print(self, format: str | None = TEXT, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the object in a file or on standard output by default.

    Parameters:
        format: Output format (csv, json or text).
        output: Descriptor to an opened file (default to standard output).
        **kwargs: Additional arguments.
    """
    if format is None:
        format = TEXT

    if format != TEXT:
        kwargs.pop("zero", "")

    if format == TEXT:
        print(self._to_text(**kwargs), file=output)
    elif format == CSV:
        print(self._to_csv(**kwargs), file=output)
    elif format == JSON:
        print(self._to_json(**kwargs), file=output)

NodeMixin ¤

Shared code between DSM, Package and Module.

Attributes:

  • isdsm (bool) –

    Property to check if object is instance of DSM.

  • ismodule (bool) –

    Property to check if object is instance of Module.

  • ispackage (bool) –

    Property to check if object is instance of Package.

isdsm property ¤

isdsm: bool

Property to check if object is instance of DSM.

Returns:

  • bool

    Whether this object is a DSM.

ismodule property ¤

ismodule: bool

Property to check if object is instance of Module.

Returns:

  • bool

    Whether this object is a module.

ispackage property ¤

ispackage: bool

Property to check if object is instance of Package.

Returns:

  • bool

    Whether this object is a package.

Package ¤

Package(
    name: str,
    path: str,
    dsm: DSM | None = None,
    package: Package | None = None,
    limit_to: list[str] | None = None,
    build_tree: bool = True,
    build_dependencies: bool = True,
    enforce_init: bool = True,
)

Bases: RootNode, LeafNode, NodeMixin, PrintMixin

Package class.

This class represent Python packages as nodes in a tree.

Parameters:

  • name (str) –

    Name of the package.

  • path (str) –

    Path to the package.

  • dsm (DSM | None, default: None ) –

    Parent DSM.

  • package (Package | None, default: None ) –

    Parent package.

  • limit_to (list[str] | None, default: None ) –

    List of string to limit the recursive tree-building to what is specified.

  • build_tree (bool, default: True ) –

    Auto-build the tree or not.

  • build_dependencies (bool, default: True ) –

    Auto-build the dependencies or not.

  • enforce_init (bool, default: True ) –

    If True, only treat directories if they contain an __init__.py file.

Methods:

  • __bool__

    Node as Boolean.

  • __contains__

    Get result of _contains, cache it and return it.

  • __getitem__

    Return the corresponding Package or Module object.

  • absolute_name

    Return the absolute name of the node.

  • as_dict

    Return the dependencies as a dictionary.

  • as_graph

    Create a graph with self as node, cache it, return it.

  • as_matrix

    Create a matrix with self as node, cache it, return it.

  • as_treemap

    Return the dependencies as a TreeMap.

  • build_dependencies

    Recursively build the dependencies for sub-modules and sub-packages.

  • build_tree

    Build the tree for this package.

  • cardinal

    Return the number of dependencies of this package to the given node.

  • get

    Get item through __getitem__ and cache the result.

  • get_target

    Get the result of _get_target, cache it and return it.

  • print

    Print the object in a file or on standard output by default.

  • print_graph

    Print the graph for self's nodes.

  • print_matrix

    Print the matrix for self's nodes.

  • print_treemap

    Print the matrix for self's nodes.

  • split_limits_heads

    Return first parts of dot-separated strings, and rest of strings.

Attributes:

  • depth (int) –

    Property to tell the depth of the node in the tree.

  • dsm

    Parent DSM.

  • empty (bool) –

    Whether the node has neither modules nor packages.

  • enforce_init

    Whether to enforce the presence of __init__.py files.

  • isdsm (bool) –

    Property to check if object is instance of DSM.

  • ismodule (bool) –

    Property to check if object is instance of Module.

  • ispackage (bool) –

    Inherited from NodeMixin. Always True.

  • isroot (bool) –

    Property to tell if this node is a root node.

  • issubpackage (bool) –

    Property to tell if this node is a sub-package.

  • limit_to

    List of strings to limit the recursive tree-building.

  • modules (list[Module]) –

    List of modules contained in the node.

  • name

    Name of the package.

  • package

    Parent package.

  • packages (list[Package]) –

    List of packages contained in the node.

  • path

    Path to the package.

  • root (Package) –

    Property to return the root of this node.

  • submodules (list[Module]) –

    Property to return all sub-modules of the node, recursively.

Source code in src/dependenpy/_internal/dsm.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
def __init__(
    self,
    name: str,
    path: str,
    dsm: DSM | None = None,
    package: Package | None = None,
    limit_to: list[str] | None = None,
    build_tree: bool = True,  # noqa: FBT001,FBT002
    build_dependencies: bool = True,  # noqa: FBT001,FBT002
    enforce_init: bool = True,  # noqa: FBT001,FBT002
):
    """Initialization method.

    Parameters:
        name: Name of the package.
        path: Path to the package.
        dsm: Parent DSM.
        package: Parent package.
        limit_to: List of string to limit the recursive tree-building to what is specified.
        build_tree: Auto-build the tree or not.
        build_dependencies: Auto-build the dependencies or not.
        enforce_init: If True, only treat directories if they contain an `__init__.py` file.
    """
    self.name = name
    """Name of the package."""
    self.path = path
    """Path to the package."""
    self.package = package
    """Parent package."""
    self.dsm = dsm
    """Parent DSM."""
    self.limit_to = limit_to or []
    """List of strings to limit the recursive tree-building."""
    self.enforce_init = enforce_init
    """Whether to enforce the presence of `__init__.py` files."""

    RootNode.__init__(self, build_tree)
    LeafNode.__init__(self)

    if build_tree and build_dependencies:
        self.build_dependencies()

depth property ¤

depth: int

Property to tell the depth of the node in the tree.

Returns:

  • int

    The node's depth in the tree.

dsm instance-attribute ¤

dsm = dsm

Parent DSM.

empty property ¤

empty: bool

Whether the node has neither modules nor packages.

Returns:

  • bool

    True if empty, False otherwise.

enforce_init instance-attribute ¤

enforce_init = enforce_init

Whether to enforce the presence of __init__.py files.

isdsm property ¤

isdsm: bool

Property to check if object is instance of DSM.

Returns:

  • bool

    Whether this object is a DSM.

ismodule property ¤

ismodule: bool

Property to check if object is instance of Module.

Returns:

  • bool

    Whether this object is a module.

ispackage property ¤

ispackage: bool

Inherited from NodeMixin. Always True.

Returns:

  • bool

    Whether this object is a package.

isroot property ¤

isroot: bool

Property to tell if this node is a root node.

Returns:

  • bool

    This package has no parent.

issubpackage property ¤

issubpackage: bool

Property to tell if this node is a sub-package.

Returns:

  • bool

    This package has a parent.

limit_to instance-attribute ¤

limit_to = limit_to or []

List of strings to limit the recursive tree-building.

modules instance-attribute ¤

modules: list[Module] = []

List of modules contained in the node.

name instance-attribute ¤

name = name

Name of the package.

package instance-attribute ¤

package = package

Parent package.

packages instance-attribute ¤

packages: list[Package] = []

List of packages contained in the node.

path instance-attribute ¤

path = path

Path to the package.

root property ¤

root: Package

Property to return the root of this node.

Returns:

  • Package ( Package ) –

    this node's root package.

submodules property ¤

submodules: list[Module]

Property to return all sub-modules of the node, recursively.

Returns:

__bool__ ¤

__bool__() -> bool

Node as Boolean.

Returns:

  • bool

    Result of node.empty.

Source code in src/dependenpy/_internal/node.py
106
107
108
109
110
111
112
def __bool__(self) -> bool:
    """Node as Boolean.

    Returns:
        Result of node.empty.
    """
    return bool(self.modules or self.packages)

__contains__ ¤

__contains__(item: Package | Module) -> bool

Get result of _contains, cache it and return it.

Parameters:

Returns:

  • bool

    True if self contains item, False otherwise.

Source code in src/dependenpy/_internal/node.py
67
68
69
70
71
72
73
74
75
76
77
78
def __contains__(self, item: Package | Module) -> bool:
    """Get result of _contains, cache it and return it.

    Parameters:
        item: A package or module.

    Returns:
        True if self contains item, False otherwise.
    """
    if item not in self._contains_cache:
        self._contains_cache[item] = self._contains(item)
    return self._contains_cache[item]

__getitem__ ¤

__getitem__(item: str) -> Package | Module

Return the corresponding Package or Module object.

Parameters:

  • item (str) –

    Name of the package/module, dot-separated.

Raises:

  • KeyError

    When the package or module cannot be found.

Returns:

Source code in src/dependenpy/_internal/node.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def __getitem__(self, item: str) -> Package | Module:
    """Return the corresponding Package or Module object.

    Parameters:
        item: Name of the package/module, dot-separated.

    Raises:
        KeyError: When the package or module cannot be found.

    Returns:
        The corresponding object.
    """
    depth = item.count(".") + 1
    parts = item.split(".", 1)
    for module in self.modules:
        if parts[0] == module.name and depth == 1:
            return module
    for package in self.packages:
        if parts[0] == package.name:
            if depth == 1:
                return package
            obj = package.get(parts[1])
            if obj:
                return obj
    raise KeyError(item)

absolute_name ¤

absolute_name(depth: int = 0) -> str

Return the absolute name of the node.

Concatenate names from root to self within depth.

Parameters:

  • depth (int, default: 0 ) –

    Maximum depth to go to.

Returns:

  • str

    Absolute name of the node (until given depth is reached).

Source code in src/dependenpy/_internal/node.py
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
def absolute_name(self, depth: int = 0) -> str:
    """Return the absolute name of the node.

    Concatenate names from root to self within depth.

    Parameters:
        depth: Maximum depth to go to.

    Returns:
        Absolute name of the node (until given depth is reached).
    """
    node: Package
    node, node_depth = self, self.depth  # type: ignore[assignment]
    if depth < 1:
        depth = node_depth
    while node_depth > depth and node.package is not None:
        node = node.package
        node_depth -= 1
    names = []
    while node is not None:
        names.append(node.name)
        node = node.package  # type: ignore[assignment]
    return ".".join(reversed(names))

as_dict ¤

as_dict() -> dict

Return the dependencies as a dictionary.

Returns:

  • dict

    Dictionary of dependencies.

Source code in src/dependenpy/_internal/node.py
300
301
302
303
304
305
306
307
308
309
310
def as_dict(self) -> dict:
    """Return the dependencies as a dictionary.

    Returns:
        Dictionary of dependencies.
    """
    return {
        "name": str(self),
        "modules": [module.as_dict() for module in self.modules],
        "packages": [package.as_dict() for package in self.packages],
    }

as_graph ¤

as_graph(depth: int = 0) -> Graph

Create a graph with self as node, cache it, return it.

Parameters:

  • depth (int, default: 0 ) –

    Depth of the graph.

Returns:

  • Graph

    An instance of Graph.

Source code in src/dependenpy/_internal/node.py
312
313
314
315
316
317
318
319
320
321
322
323
def as_graph(self, depth: int = 0) -> Graph:
    """Create a graph with self as node, cache it, return it.

    Parameters:
        depth: Depth of the graph.

    Returns:
        An instance of Graph.
    """
    if depth not in self._graph_cache:
        self._graph_cache[depth] = Graph(self, depth=depth)  # type: ignore[arg-type]
    return self._graph_cache[depth]

as_matrix ¤

as_matrix(depth: int = 0) -> Matrix

Create a matrix with self as node, cache it, return it.

Parameters:

  • depth (int, default: 0 ) –

    Depth of the matrix.

Returns:

  • Matrix

    An instance of Matrix.

Source code in src/dependenpy/_internal/node.py
325
326
327
328
329
330
331
332
333
334
335
336
def as_matrix(self, depth: int = 0) -> Matrix:
    """Create a matrix with self as node, cache it, return it.

    Parameters:
        depth: Depth of the matrix.

    Returns:
        An instance of Matrix.
    """
    if depth not in self._matrix_cache:
        self._matrix_cache[depth] = Matrix(self, depth=depth)  # type: ignore[arg-type]
    return self._matrix_cache[depth]

as_treemap ¤

as_treemap() -> TreeMap

Return the dependencies as a TreeMap.

Returns:

  • TreeMap

    An instance of TreeMap.

Source code in src/dependenpy/_internal/node.py
338
339
340
341
342
343
344
345
346
def as_treemap(self) -> TreeMap:
    """Return the dependencies as a TreeMap.

    Returns:
        An instance of TreeMap.
    """
    if not self._treemap_cache:
        self._treemap_cache = TreeMap(self)
    return self._treemap_cache

build_dependencies ¤

build_dependencies() -> None

Recursively build the dependencies for sub-modules and sub-packages.

Iterate on node's modules then packages and call their build_dependencies methods.

Source code in src/dependenpy/_internal/node.py
217
218
219
220
221
222
223
224
225
226
def build_dependencies(self) -> None:
    """Recursively build the dependencies for sub-modules and sub-packages.

    Iterate on node's modules then packages and call their
    build_dependencies methods.
    """
    for module in self.modules:
        module.build_dependencies()
    for package in self.packages:
        package.build_dependencies()

build_tree ¤

build_tree() -> None

Build the tree for this package.

Source code in src/dependenpy/_internal/dsm.py
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
def build_tree(self) -> None:
    """Build the tree for this package."""
    for module in listdir(self.path):
        abs_m = join(self.path, module)
        if isfile(abs_m) and module.endswith(".py"):
            name = splitext(module)[0]
            if not self.limit_to or name in self.limit_to:
                self.modules.append(Module(name, abs_m, self.dsm, self))
        elif isdir(abs_m) and (isfile(join(abs_m, "__init__.py")) or not self.enforce_init):
            heads, new_limit_to = self.split_limits_heads()
            if not heads or module in heads:
                self.packages.append(
                    Package(
                        module,
                        abs_m,
                        self.dsm,
                        self,
                        new_limit_to,
                        build_tree=True,
                        build_dependencies=False,
                        enforce_init=self.enforce_init,
                    ),
                )

cardinal ¤

cardinal(to: Package | Module) -> int

Return the number of dependencies of this package to the given node.

Parameters:

Returns:

  • int

    Number of dependencies.

Source code in src/dependenpy/_internal/dsm.py
232
233
234
235
236
237
238
239
240
241
def cardinal(self, to: Package | Module) -> int:
    """Return the number of dependencies of this package to the given node.

    Parameters:
        to: Target node.

    Returns:
        Number of dependencies.
    """
    return sum(module.cardinal(to) for module in self.submodules)

get ¤

get(item: str) -> Package | Module

Get item through __getitem__ and cache the result.

Parameters:

  • item (str) –

    Name of package or module.

Returns:

Source code in src/dependenpy/_internal/node.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def get(self, item: str) -> Package | Module:
    """Get item through `__getitem__` and cache the result.

    Parameters:
        item: Name of package or module.

    Returns:
        The corresponding object.
    """
    if item not in self._item_cache:
        try:
            obj = self.__getitem__(item)
        except KeyError:
            obj = None
        self._item_cache[item] = obj
    return self._item_cache[item]

get_target ¤

get_target(target: str) -> Package | Module

Get the result of _get_target, cache it and return it.

Parameters:

  • target (str) –

    Target to find.

Returns:

  • Package | Module

    Package containing target or corresponding module.

Source code in src/dependenpy/_internal/node.py
173
174
175
176
177
178
179
180
181
182
183
184
def get_target(self, target: str) -> Package | Module:
    """Get the result of _get_target, cache it and return it.

    Parameters:
        target: Target to find.

    Returns:
        Package containing target or corresponding module.
    """
    if target not in self._target_cache:
        self._target_cache[target] = self._get_target(target)
    return self._target_cache[target]

print ¤

print(
    format: str | None = TEXT,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the object in a file or on standard output by default.

Parameters:

  • format (str | None, default: TEXT ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    Descriptor to an opened file (default to standard output).

  • **kwargs (Any, default: {} ) –

    Additional arguments.

Source code in src/dependenpy/_internal/helpers.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def print(self, format: str | None = TEXT, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the object in a file or on standard output by default.

    Parameters:
        format: Output format (csv, json or text).
        output: Descriptor to an opened file (default to standard output).
        **kwargs: Additional arguments.
    """
    if format is None:
        format = TEXT

    if format != TEXT:
        kwargs.pop("zero", "")

    if format == TEXT:
        print(self._to_text(**kwargs), file=output)
    elif format == CSV:
        print(self._to_csv(**kwargs), file=output)
    elif format == JSON:
        print(self._to_json(**kwargs), file=output)

print_graph ¤

print_graph(
    format: str | None = None,
    output: IO = stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None

Print the graph for self's nodes.

Parameters:

  • format (str | None, default: None ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    File descriptor on which to write.

  • depth (int, default: 0 ) –

    Depth of the graph.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments passed to graph.print.

Source code in src/dependenpy/_internal/node.py
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
def print_graph(
    self,
    format: str | None = None,  # noqa: A002
    output: IO = sys.stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None:
    """Print the graph for self's nodes.

    Parameters:
        format: Output format (csv, json or text).
        output: File descriptor on which to write.
        depth: Depth of the graph.
        **kwargs: Additional keyword arguments passed to `graph.print`.
    """
    graph = self.as_graph(depth=depth)
    graph.print(format=format, output=output, **kwargs)

print_matrix ¤

print_matrix(
    format: str | None = None,
    output: IO = stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None

Print the matrix for self's nodes.

Parameters:

  • format (str | None, default: None ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    File descriptor on which to write.

  • depth (int, default: 0 ) –

    Depth of the matrix.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments passed to matrix.print.

Source code in src/dependenpy/_internal/node.py
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
def print_matrix(
    self,
    format: str | None = None,  # noqa: A002
    output: IO = sys.stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None:
    """Print the matrix for self's nodes.

    Parameters:
        format: Output format (csv, json or text).
        output: File descriptor on which to write.
        depth: Depth of the matrix.
        **kwargs: Additional keyword arguments passed to `matrix.print`.
    """
    matrix = self.as_matrix(depth=depth)
    matrix.print(format=format, output=output, **kwargs)

print_treemap ¤

print_treemap(
    format: str | None = None,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the matrix for self's nodes.

Parameters:

  • format (str | None, default: None ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    File descriptor on which to write.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments passed to treemap.print.

Source code in src/dependenpy/_internal/node.py
264
265
266
267
268
269
270
271
272
273
def print_treemap(self, format: str | None = None, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the matrix for self's nodes.

    Parameters:
        format: Output format (csv, json or text).
        output: File descriptor on which to write.
        **kwargs: Additional keyword arguments passed to `treemap.print`.
    """
    treemap = self.as_treemap()
    treemap.print(format=format, output=output, **kwargs)

split_limits_heads ¤

split_limits_heads() -> tuple[list[str], list[str]]

Return first parts of dot-separated strings, and rest of strings.

Returns:

Source code in src/dependenpy/_internal/dsm.py
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
def split_limits_heads(self) -> tuple[list[str], list[str]]:
    """Return first parts of dot-separated strings, and rest of strings.

    Returns:
        The heads and rest of the strings.
    """
    heads = []
    new_limit_to = []
    for limit in self.limit_to:
        if "." in limit:
            name, limit = limit.split(".", 1)  # noqa: PLW2901
            heads.append(name)
            new_limit_to.append(limit)
        else:
            heads.append(limit)
    return heads, new_limit_to

PackageFinder ¤

Abstract package finder class.

Methods:

  • find

    Find method.

find ¤

find(package: str, **kwargs: Any) -> PackageSpec | None

Find method.

Parameters:

  • package (str) –

    Package to find.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments.

Returns:

Source code in src/dependenpy/_internal/finder.py
74
75
76
77
78
79
80
81
82
83
84
def find(self, package: str, **kwargs: Any) -> PackageSpec | None:
    """Find method.

    Parameters:
        package: Package to find.
        **kwargs: Additional keyword arguments.

    Returns:
        Package spec or None.
    """
    raise NotImplementedError

PackageSpec ¤

PackageSpec(
    name: str, path: str, limit_to: list[str] | None = None
)

Holder for a package specification (given as argument to DSM).

Parameters:

  • name (str) –

    Name of the package.

  • path (str) –

    Path to the package.

  • limit_to (list[str] | None, default: None ) –

    Limitations.

Methods:

  • __hash__

    Hash method.

  • add

    Add limitations of given spec to self's.

  • combine

    Combine package specifications' limitations.

Attributes:

  • ismodule (bool) –

    Property to tell if the package is in fact a module (a file).

  • limit_to

    List of limitations.

  • name

    Name of the package.

  • path

    Path to the package.

Source code in src/dependenpy/_internal/finder.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def __init__(self, name: str, path: str, limit_to: list[str] | None = None) -> None:
    """Initialization method.

    Parameters:
        name: Name of the package.
        path: Path to the package.
        limit_to: Limitations.
    """
    self.name = name
    """Name of the package."""
    self.path = path
    """Path to the package."""
    self.limit_to = limit_to or []
    """List of limitations."""

ismodule property ¤

ismodule: bool

Property to tell if the package is in fact a module (a file).

Returns:

  • bool

    Whether this package is in fact a module.

limit_to instance-attribute ¤

limit_to = limit_to or []

List of limitations.

name instance-attribute ¤

name = name

Name of the package.

path instance-attribute ¤

path = path

Path to the package.

__hash__ ¤

__hash__()

Hash method.

The hash is computed based on the package name and path.

Source code in src/dependenpy/_internal/finder.py
26
27
28
29
30
31
def __hash__(self):
    """Hash method.

    The hash is computed based on the package name and path.
    """
    return hash((self.name, self.path))

add ¤

add(spec: PackageSpec) -> None

Add limitations of given spec to self's.

Parameters:

Source code in src/dependenpy/_internal/finder.py
42
43
44
45
46
47
48
49
50
def add(self, spec: PackageSpec) -> None:
    """Add limitations of given spec to self's.

    Parameters:
        spec: Another spec.
    """
    for limit in spec.limit_to:
        if limit not in self.limit_to:
            self.limit_to.append(limit)

combine staticmethod ¤

combine(specs: list[PackageSpec]) -> list[PackageSpec]

Combine package specifications' limitations.

Parameters:

Returns:

Source code in src/dependenpy/_internal/finder.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@staticmethod
def combine(specs: list[PackageSpec]) -> list[PackageSpec]:
    """Combine package specifications' limitations.

    Parameters:
        specs: The package specifications.

    Returns:
        The new, merged list of PackageSpec.
    """
    new_specs: dict[PackageSpec, PackageSpec] = {}
    for spec in specs:
        if new_specs.get(spec) is None:
            new_specs[spec] = spec
        else:
            new_specs[spec].add(spec)
    return list(new_specs.values())

PrintMixin ¤

Print mixin class.

Methods:

  • print

    Print the object in a file or on standard output by default.

print ¤

print(
    format: str | None = TEXT,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the object in a file or on standard output by default.

Parameters:

  • format (str | None, default: TEXT ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    Descriptor to an opened file (default to standard output).

  • **kwargs (Any, default: {} ) –

    Additional arguments.

Source code in src/dependenpy/_internal/helpers.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def print(self, format: str | None = TEXT, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the object in a file or on standard output by default.

    Parameters:
        format: Output format (csv, json or text).
        output: Descriptor to an opened file (default to standard output).
        **kwargs: Additional arguments.
    """
    if format is None:
        format = TEXT

    if format != TEXT:
        kwargs.pop("zero", "")

    if format == TEXT:
        print(self._to_text(**kwargs), file=output)
    elif format == CSV:
        print(self._to_csv(**kwargs), file=output)
    elif format == JSON:
        print(self._to_json(**kwargs), file=output)

RootNode ¤

RootNode(build_tree: bool = True)

Shared code between DSM and Package.

Parameters:

  • build_tree (bool, default: True ) –

    Whether to immediately build the tree or not.

Methods:

  • __bool__

    Node as Boolean.

  • __contains__

    Get result of _contains, cache it and return it.

  • __getitem__

    Return the corresponding Package or Module object.

  • as_dict

    Return the dependencies as a dictionary.

  • as_graph

    Create a graph with self as node, cache it, return it.

  • as_matrix

    Create a matrix with self as node, cache it, return it.

  • as_treemap

    Return the dependencies as a TreeMap.

  • build_dependencies

    Recursively build the dependencies for sub-modules and sub-packages.

  • build_tree

    To be overridden.

  • get

    Get item through __getitem__ and cache the result.

  • get_target

    Get the result of _get_target, cache it and return it.

  • print_graph

    Print the graph for self's nodes.

  • print_matrix

    Print the matrix for self's nodes.

  • print_treemap

    Print the matrix for self's nodes.

Attributes:

Source code in src/dependenpy/_internal/node.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def __init__(self, build_tree: bool = True):  # noqa: FBT001,FBT002
    """Initialization method.

    Parameters:
        build_tree: Whether to immediately build the tree or not.
    """
    self._target_cache: dict[str, Any] = {}
    self._item_cache: dict[str, Any] = {}
    self._contains_cache: dict[Package | Module, bool] = {}
    self._matrix_cache: dict[int, Matrix] = {}
    self._graph_cache: dict[int, Graph] = {}
    self._treemap_cache = TreeMap()
    self.modules: list[Module] = []
    """List of modules contained in the node."""
    self.packages: list[Package] = []
    """List of packages contained in the node."""

    if build_tree:
        self.build_tree()

empty property ¤

empty: bool

Whether the node has neither modules nor packages.

Returns:

  • bool

    True if empty, False otherwise.

modules instance-attribute ¤

modules: list[Module] = []

List of modules contained in the node.

packages instance-attribute ¤

packages: list[Package] = []

List of packages contained in the node.

submodules property ¤

submodules: list[Module]

Property to return all sub-modules of the node, recursively.

Returns:

__bool__ ¤

__bool__() -> bool

Node as Boolean.

Returns:

  • bool

    Result of node.empty.

Source code in src/dependenpy/_internal/node.py
106
107
108
109
110
111
112
def __bool__(self) -> bool:
    """Node as Boolean.

    Returns:
        Result of node.empty.
    """
    return bool(self.modules or self.packages)

__contains__ ¤

__contains__(item: Package | Module) -> bool

Get result of _contains, cache it and return it.

Parameters:

Returns:

  • bool

    True if self contains item, False otherwise.

Source code in src/dependenpy/_internal/node.py
67
68
69
70
71
72
73
74
75
76
77
78
def __contains__(self, item: Package | Module) -> bool:
    """Get result of _contains, cache it and return it.

    Parameters:
        item: A package or module.

    Returns:
        True if self contains item, False otherwise.
    """
    if item not in self._contains_cache:
        self._contains_cache[item] = self._contains(item)
    return self._contains_cache[item]

__getitem__ ¤

__getitem__(item: str) -> Package | Module

Return the corresponding Package or Module object.

Parameters:

  • item (str) –

    Name of the package/module, dot-separated.

Raises:

  • KeyError

    When the package or module cannot be found.

Returns:

Source code in src/dependenpy/_internal/node.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def __getitem__(self, item: str) -> Package | Module:
    """Return the corresponding Package or Module object.

    Parameters:
        item: Name of the package/module, dot-separated.

    Raises:
        KeyError: When the package or module cannot be found.

    Returns:
        The corresponding object.
    """
    depth = item.count(".") + 1
    parts = item.split(".", 1)
    for module in self.modules:
        if parts[0] == module.name and depth == 1:
            return module
    for package in self.packages:
        if parts[0] == package.name:
            if depth == 1:
                return package
            obj = package.get(parts[1])
            if obj:
                return obj
    raise KeyError(item)

as_dict ¤

as_dict() -> dict

Return the dependencies as a dictionary.

Returns:

  • dict

    Dictionary of dependencies.

Source code in src/dependenpy/_internal/node.py
300
301
302
303
304
305
306
307
308
309
310
def as_dict(self) -> dict:
    """Return the dependencies as a dictionary.

    Returns:
        Dictionary of dependencies.
    """
    return {
        "name": str(self),
        "modules": [module.as_dict() for module in self.modules],
        "packages": [package.as_dict() for package in self.packages],
    }

as_graph ¤

as_graph(depth: int = 0) -> Graph

Create a graph with self as node, cache it, return it.

Parameters:

  • depth (int, default: 0 ) –

    Depth of the graph.

Returns:

  • Graph

    An instance of Graph.

Source code in src/dependenpy/_internal/node.py
312
313
314
315
316
317
318
319
320
321
322
323
def as_graph(self, depth: int = 0) -> Graph:
    """Create a graph with self as node, cache it, return it.

    Parameters:
        depth: Depth of the graph.

    Returns:
        An instance of Graph.
    """
    if depth not in self._graph_cache:
        self._graph_cache[depth] = Graph(self, depth=depth)  # type: ignore[arg-type]
    return self._graph_cache[depth]

as_matrix ¤

as_matrix(depth: int = 0) -> Matrix

Create a matrix with self as node, cache it, return it.

Parameters:

  • depth (int, default: 0 ) –

    Depth of the matrix.

Returns:

  • Matrix

    An instance of Matrix.

Source code in src/dependenpy/_internal/node.py
325
326
327
328
329
330
331
332
333
334
335
336
def as_matrix(self, depth: int = 0) -> Matrix:
    """Create a matrix with self as node, cache it, return it.

    Parameters:
        depth: Depth of the matrix.

    Returns:
        An instance of Matrix.
    """
    if depth not in self._matrix_cache:
        self._matrix_cache[depth] = Matrix(self, depth=depth)  # type: ignore[arg-type]
    return self._matrix_cache[depth]

as_treemap ¤

as_treemap() -> TreeMap

Return the dependencies as a TreeMap.

Returns:

  • TreeMap

    An instance of TreeMap.

Source code in src/dependenpy/_internal/node.py
338
339
340
341
342
343
344
345
346
def as_treemap(self) -> TreeMap:
    """Return the dependencies as a TreeMap.

    Returns:
        An instance of TreeMap.
    """
    if not self._treemap_cache:
        self._treemap_cache = TreeMap(self)
    return self._treemap_cache

build_dependencies ¤

build_dependencies() -> None

Recursively build the dependencies for sub-modules and sub-packages.

Iterate on node's modules then packages and call their build_dependencies methods.

Source code in src/dependenpy/_internal/node.py
217
218
219
220
221
222
223
224
225
226
def build_dependencies(self) -> None:
    """Recursively build the dependencies for sub-modules and sub-packages.

    Iterate on node's modules then packages and call their
    build_dependencies methods.
    """
    for module in self.modules:
        module.build_dependencies()
    for package in self.packages:
        package.build_dependencies()

build_tree ¤

build_tree() -> None

To be overridden.

Source code in src/dependenpy/_internal/node.py
136
137
138
def build_tree(self) -> None:
    """To be overridden."""
    raise NotImplementedError

get ¤

get(item: str) -> Package | Module

Get item through __getitem__ and cache the result.

Parameters:

  • item (str) –

    Name of package or module.

Returns:

Source code in src/dependenpy/_internal/node.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def get(self, item: str) -> Package | Module:
    """Get item through `__getitem__` and cache the result.

    Parameters:
        item: Name of package or module.

    Returns:
        The corresponding object.
    """
    if item not in self._item_cache:
        try:
            obj = self.__getitem__(item)
        except KeyError:
            obj = None
        self._item_cache[item] = obj
    return self._item_cache[item]

get_target ¤

get_target(target: str) -> Package | Module

Get the result of _get_target, cache it and return it.

Parameters:

  • target (str) –

    Target to find.

Returns:

  • Package | Module

    Package containing target or corresponding module.

Source code in src/dependenpy/_internal/node.py
173
174
175
176
177
178
179
180
181
182
183
184
def get_target(self, target: str) -> Package | Module:
    """Get the result of _get_target, cache it and return it.

    Parameters:
        target: Target to find.

    Returns:
        Package containing target or corresponding module.
    """
    if target not in self._target_cache:
        self._target_cache[target] = self._get_target(target)
    return self._target_cache[target]

print_graph ¤

print_graph(
    format: str | None = None,
    output: IO = stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None

Print the graph for self's nodes.

Parameters:

  • format (str | None, default: None ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    File descriptor on which to write.

  • depth (int, default: 0 ) –

    Depth of the graph.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments passed to graph.print.

Source code in src/dependenpy/_internal/node.py
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
def print_graph(
    self,
    format: str | None = None,  # noqa: A002
    output: IO = sys.stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None:
    """Print the graph for self's nodes.

    Parameters:
        format: Output format (csv, json or text).
        output: File descriptor on which to write.
        depth: Depth of the graph.
        **kwargs: Additional keyword arguments passed to `graph.print`.
    """
    graph = self.as_graph(depth=depth)
    graph.print(format=format, output=output, **kwargs)

print_matrix ¤

print_matrix(
    format: str | None = None,
    output: IO = stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None

Print the matrix for self's nodes.

Parameters:

  • format (str | None, default: None ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    File descriptor on which to write.

  • depth (int, default: 0 ) –

    Depth of the matrix.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments passed to matrix.print.

Source code in src/dependenpy/_internal/node.py
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
def print_matrix(
    self,
    format: str | None = None,  # noqa: A002
    output: IO = sys.stdout,
    depth: int = 0,
    **kwargs: Any,
) -> None:
    """Print the matrix for self's nodes.

    Parameters:
        format: Output format (csv, json or text).
        output: File descriptor on which to write.
        depth: Depth of the matrix.
        **kwargs: Additional keyword arguments passed to `matrix.print`.
    """
    matrix = self.as_matrix(depth=depth)
    matrix.print(format=format, output=output, **kwargs)

print_treemap ¤

print_treemap(
    format: str | None = None,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the matrix for self's nodes.

Parameters:

  • format (str | None, default: None ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    File descriptor on which to write.

  • **kwargs (Any, default: {} ) –

    Additional keyword arguments passed to treemap.print.

Source code in src/dependenpy/_internal/node.py
264
265
266
267
268
269
270
271
272
273
def print_treemap(self, format: str | None = None, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the matrix for self's nodes.

    Parameters:
        format: Output format (csv, json or text).
        output: File descriptor on which to write.
        **kwargs: Additional keyword arguments passed to `treemap.print`.
    """
    treemap = self.as_treemap()
    treemap.print(format=format, output=output, **kwargs)

TreeMap ¤

TreeMap(*nodes: Any, value: int = -1)

Bases: PrintMixin

TreeMap class.

Parameters:

  • *nodes (Any, default: () ) –

    the nodes from which to build the treemap.

  • value (int, default: -1 ) –

    the value of the current area.

Methods:

  • print

    Print the object in a file or on standard output by default.

Attributes:

  • value

    The value of the current area.

Source code in src/dependenpy/_internal/structures.py
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
def __init__(self, *nodes: Any, value: int = -1):  # noqa: ARG002
    """Initialization method.

    Arguments:
        *nodes: the nodes from which to build the treemap.
        value: the value of the current area.
    """
    # if nodes:
    #     matrix_lower_level = Matrix(*nodes, depth=2)
    #     matrix_current_level = Matrix(*nodes, depth=1)
    #     if value == -1:
    #         value = sum(c for row in matrix_current_level.data for c in row)
    #     splits = [0]
    #     key_comp = matrix_lower_level.keys[0].split('.')[0]
    #     i = 1
    #     for key in matrix_lower_level.keys[1:]:
    #         key = key.split('.')[0]
    #         if key != key_comp:
    #             splits.append(i)
    #             key_comp = key
    #         i += 1
    #     splits.append(i)
    #
    #     self.data = []
    #     for i in range(len(splits) - 1):
    #         self.data.append([])
    #         rows = matrix_lower_level.data[splits[i]:splits[i+1]]
    #         for j in range(len(splits) - 1):
    #             self.data[i].append([row[splits[j]:splits[j+1]] for row in rows])

    self.value = value
    """The value of the current area."""

value instance-attribute ¤

value = value

The value of the current area.

print ¤

print(
    format: str | None = TEXT,
    output: IO = stdout,
    **kwargs: Any,
) -> None

Print the object in a file or on standard output by default.

Parameters:

  • format (str | None, default: TEXT ) –

    Output format (csv, json or text).

  • output (IO, default: stdout ) –

    Descriptor to an opened file (default to standard output).

  • **kwargs (Any, default: {} ) –

    Additional arguments.

Source code in src/dependenpy/_internal/helpers.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def print(self, format: str | None = TEXT, output: IO = sys.stdout, **kwargs: Any) -> None:  # noqa: A002
    """Print the object in a file or on standard output by default.

    Parameters:
        format: Output format (csv, json or text).
        output: Descriptor to an opened file (default to standard output).
        **kwargs: Additional arguments.
    """
    if format is None:
        format = TEXT

    if format != TEXT:
        kwargs.pop("zero", "")

    if format == TEXT:
        print(self._to_text(**kwargs), file=output)
    elif format == CSV:
        print(self._to_csv(**kwargs), file=output)
    elif format == JSON:
        print(self._to_json(**kwargs), file=output)

Vertex ¤

Vertex(name: str)

Vertex class. Used in Graph class.

Parameters:

  • name (str) –

    name of the vertex.

Methods:

Attributes:

Source code in src/dependenpy/_internal/structures.py
203
204
205
206
207
208
209
210
211
212
213
214
def __init__(self, name: str) -> None:
    """Initialization method.

    Parameters:
        name (str): name of the vertex.
    """
    self.name = name
    """Name of the vertex."""
    self.edges_in: set[Edge] = set()
    """Incoming edges."""
    self.edges_out: set[Edge] = set()
    """Outgoing edges."""

edges_in instance-attribute ¤

edges_in: set[Edge] = set()

Incoming edges.

edges_out instance-attribute ¤

edges_out: set[Edge] = set()

Outgoing edges.

name instance-attribute ¤

name = name

Name of the vertex.

connect_from ¤

connect_from(vertex: Vertex, weight: int = 1) -> Edge

Connect another vertex to this one.

Parameters:

  • vertex (Vertex) –

    Vertex to connect from.

  • weight (int, default: 1 ) –

    Weight of the edge.

Returns:

  • Edge

    The newly created edge.

Source code in src/dependenpy/_internal/structures.py
234
235
236
237
238
239
240
241
242
243
244
245
246
247
def connect_from(self, vertex: Vertex, weight: int = 1) -> Edge:
    """Connect another vertex to this one.

    Parameters:
        vertex: Vertex to connect from.
        weight: Weight of the edge.

    Returns:
        The newly created edge.
    """
    for edge in self.edges_in:
        if vertex == edge.vertex_out:
            return edge
    return Edge(vertex, self, weight)

connect_to ¤

connect_to(vertex: Vertex, weight: int = 1) -> Edge

Connect this vertex to another one.

Parameters:

  • vertex (Vertex) –

    Vertex to connect to.

  • weight (int, default: 1 ) –

    Weight of the edge.

Returns:

  • Edge

    The newly created edge.

Source code in src/dependenpy/_internal/structures.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
def connect_to(self, vertex: Vertex, weight: int = 1) -> Edge:
    """Connect this vertex to another one.

    Parameters:
        vertex: Vertex to connect to.
        weight: Weight of the edge.

    Returns:
        The newly created edge.
    """
    for edge in self.edges_out:
        if vertex == edge.vertex_in:
            return edge
    return Edge(self, vertex, weight)

get_parser ¤

get_parser() -> ArgumentParser

Return the CLI argument parser.

Returns:

Source code in src/dependenpy/_internal/cli.py
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
def get_parser() -> argparse.ArgumentParser:
    """Return the CLI argument parser.

    Returns:
        An argparse parser.
    """
    parser = argparse.ArgumentParser(
        prog="dependenpy",
        add_help=False,
        description="Command line tool for dependenpy Python package.",
    )
    mxg = parser.add_mutually_exclusive_group(required=False)

    parser.add_argument(
        "packages",
        metavar="PACKAGES",
        nargs=argparse.ONE_OR_MORE,
        help="The package list. Can be a comma-separated list. Each package "
        "must be either a valid path or a package in PYTHONPATH.",
    )
    parser.add_argument(
        "-d",
        "--depth",
        default=None,
        type=int,
        dest="depth",
        help="Specify matrix or graph depth. Default: best guess.",
    )
    parser.add_argument(
        "-f",
        "--format",
        choices=FORMAT,
        default="text",
        dest="format",
        help="Output format. Default: text.",
    )
    mxg.add_argument(
        "-g",
        "--show-graph",
        action="store_true",
        dest="graph",
        default=False,
        help="Show the graph (no text format). Default: false.",
    )
    parser.add_argument(
        "-G",
        "--greedy",
        action="store_true",
        dest="greedy",
        default=False,
        help="Explore subdirectories even if they do not contain an "
        "__init__.py file. Can make execution slower. Default: false.",
    )
    parser.add_argument(
        "-h",
        "--help",
        action="help",
        default=argparse.SUPPRESS,
        help="Show this help message and exit.",
    )
    parser.add_argument(
        "-i",
        "--indent",
        default=None,
        type=int,
        dest="indent",
        help="Specify output indentation. CSV will never be indented. "
        "Text will always have new-lines. JSON can be minified with "
        "a negative value. Default: best guess.",
    )
    mxg.add_argument(
        "-l",
        "--show-dependencies-list",
        action="store_true",
        dest="dependencies",
        default=False,
        help="Show the dependencies list. Default: false.",
    )
    mxg.add_argument(
        "-m",
        "--show-matrix",
        action="store_true",
        dest="matrix",
        default=False,
        help="Show the matrix. Default: true unless -g, -l or -t.",
    )
    parser.add_argument(
        "-o",
        "--output",
        action="store",
        dest="output",
        default=sys.stdout,
        help="Output to given file. Default: stdout.",
    )
    mxg.add_argument(
        "-t",
        "--show-treemap",
        action="store_true",
        dest="treemap",
        default=False,
        help="Show the treemap (work in progress). Default: false.",
    )
    parser.add_argument(
        "-v",
        "--version",
        action="version",
        version=f"dependenpy {debug._get_version()}",
        help="Show the current version of the program and exit.",
    )
    parser.add_argument(
        "-z",
        "--zero",
        dest="zero",
        default="0",
        help="Character to use for cells with value=0 (text matrix display only).",
    )

    parser.add_argument("--debug-info", action=_DebugInfo, help="Print debug information.")
    return parser

guess_depth ¤

guess_depth(packages: Sequence[str]) -> int

Guess the optimal depth to use for the given list of arguments.

Parameters:

Returns:

  • int

    Guessed depth to use.

Source code in src/dependenpy/_internal/helpers.py
54
55
56
57
58
59
60
61
62
63
64
65
def guess_depth(packages: Sequence[str]) -> int:
    """Guess the optimal depth to use for the given list of arguments.

    Parameters:
        packages: List of packages.

    Returns:
        Guessed depth to use.
    """
    if len(packages) == 1:
        return packages[0].count(".") + 2
    return min(package.count(".") for package in packages) + 1

main ¤

main(args: list[str] | None = None) -> int

Run the main program.

This function is executed when you type dependenpy or python -m dependenpy.

Parameters:

  • args (list[str] | None, default: None ) –

    Arguments passed from the command line.

Returns:

  • int

    An exit code. 0 (OK), 1 (dsm empty) or 2 (error).

Source code in src/dependenpy/_internal/cli.py
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
def main(args: list[str] | None = None) -> int:
    """Run the main program.

    This function is executed when you type `dependenpy` or `python -m dependenpy`.

    Parameters:
        args: Arguments passed from the command line.

    Returns:
        An exit code. 0 (OK), 1 (dsm empty) or 2 (error).
    """
    parser = get_parser()
    opts = parser.parse_args(args=args)
    if not (opts.matrix or opts.dependencies or opts.treemap or opts.graph):
        opts.matrix = True

    dsm = DSM(*_get_packages(opts), build_tree=True, build_dependencies=True, enforce_init=not opts.greedy)
    if dsm.empty:
        return 1

    # init colorama
    init()

    try:
        _run(opts, dsm)
    except BrokenPipeError:
        # avoid traceback
        return 2

    return 0