Types and Helpers
Collection of shared structures, types, and functions.
Attributes¶
ImportKind: TypeAlias = Literal['dynamic', 'conditional', 'typing', 'parent', 'vanilla']
module-attribute
¶
The types/kinds of imports that are currently recognized.
EdgeKind: TypeAlias = Literal['good', 'bad', 'complicated', 'skip']
module-attribute
¶
Describes an import cycle, helping with evaluating how much of an issue it could be.
GraphDict: TypeAlias = dict[str, dict[str, ImportMetaData]]
module-attribute
¶
Dictionary representation of an import graph.
The keys on the first level are the qualnames of importing modules, the keys on the second
level are the qualnames of imported modules, and the values on the second level contain
the metadata dictionary of their keyed imports (ImportMetaData
).
Metadata consists of a tags
-list of ImportKind
s and a
cycle
which is either an EdgeKind
if there is a cycle, or
None
if there isn't.
Example
{
"foo": {
"foo.a": {
"tags": ["vanilla"],
"cycle": "complicated"
}
}
"foo.a": {
"foo": {
"tags": ["parent", "vanilla"],
"cycle": "complicated"
},
"foo.c": {
"tags": ["vanilla"],
"cycle": None
}
}
"foo.b": {
"foo": {
"tags": ["parent"],
"cycle": "complicated"
},
"foo.c": {
"tags": ["typing"],
"cycle": "skip"
}
}
"foo.c": {
"foo": {
"tags": ["parent"],
"cycle": None
},
"foo.b": {
"tags": ["vanilla"],
"cycle": "skip"
}
}
}
Classes¶
ImportMetaData
¶
SeverityMap
¶
ImportStatement
¶
Bases: TypedDict
Container for the information that we need from an AST import node.
The module-value is always non-empty, the name-value is only set by ast.ImportFrom
.
Source code in src/byecycle/misc.py
Functions¶
cycle_severity(tags_a, tags_b, **kwargs)
¶
Interpret the severity of an import cycle given their tags.
In general, all tags get thrown in the same bag and the one with the highest mapped severity "wins". Except for the "vanilla" tag, which will only have its severity considered if both imports had "vanilla" in their tag list.
Parameters:
-
tags_a
(
set[ImportKind]
) –The set of import-kind tags for the first import statement.
-
tags_b
(
set[ImportKind]
) –The set of import-kind tags for the second import statement.
-
**kwargs
(
Unpack[SeverityMap]
) –Valid values are keywords equating to
ImportKind
s mapping toEdgeKind
s in order to override thatImportKind
's severity-interpretation.
Returns:
-
EdgeKind
–A string denoting the severity of the cycle.
Source code in src/byecycle/misc.py
path_to_module_name(path, base, name)
¶
Turns a file path into a valid module name.
Just an educated guess on my part, I couldn't find an official reference. Chances are that you can't know the real name of a package unless you actually install it, and only projects that adhere to best practices and/or common sense regarding naming and structure can be handled correctly by this function.
Parameters:
-
path
(
str
) –Absolute path to the file in question.
-
base
(
str
) –Absolute path to the "source root".
-
name
(
str
) –Name of the distribution.
Returns:
-
str
–A string in the form of an importable python module.
Example
>>> # Sample call #1:
>>> path_to_module_name(
... path = "/home/me/dev/project/src/project/__init__.py"
... base = "/home/me/dev/project/src/project/"
... name = "project"
... )
project
>>> # Sample call #2:
>>> path_to_module_name(
... path = "/home/me/dev/project/src/project/code.py"
... base = "/home/me/dev/project/src/project/"
... name = "project"
... )
project.code
>>> # etc.
Notes
- What if there is a namespace?
- What if the name of the distribution is different from the base?
- What if a distribution installs multiple packages?