Lock infile

Separate out .in processing from .unlock and .lock implementations

drain_swamp.lock_infile.__all__: tuple[str, str, str, str] = ("strip_inline_comments", "InFileType", "InFile", "InFiles")
drain_swamp.lock_infile._logger: logging.Logger

Module level logger

drain_swamp.lock_infile.is_module_debug: bool = False

on/off for module level logging

class drain_swamp.lock_infile.InFile(relpath: str, stem: str, constraints: set[str] = <factory>, requirements: set[str] = <factory>)
Variables:
  • relpath (str) – Relative path to requirements file

  • stem (str) – Requirements file stem. Later, appends suffix .unlock

  • constraints (set[str]) – Requirement files may contain lines starting with -c [requirements file relative path]. This constitutes a constraint. The requirements file referenced by a constraint, can also contain constraints. The tree of constraints is resolved recursively until all constraints on all requirements files are resolved.

  • requirements (set[str]) – Contains all dependencies from a requirements file. There is no attempt made to resolve package versions.

abspath(path_package_base)

Get the absolute path. The relative path is relative to the package folder.

Parameters:

path_package_base (pathlib.Path) – package base folder

Returns:

absolute path

Return type:

pathlib.Path

static check_path(cwd, path_to_check)

Check Path. Should not be a str

Parameters:
  • cwd (pathlib.Path) – Package base folder

  • path_to_check (Any) – Hopefully a relative Path

Raises:
  • TypeError – Sequence contains one or more unsupported types

  • ValueError – Requirements file, (.in), not relative to base folder

  • FileNotFoundError – Requirements file, (.in), not found

constraints: set[str]
property depth

Number of unresolved constraints. One this number gets down to zero, the InFile is moved from files set –> zeroes set

Returns:

unresolved constraints count

Return type:

int

relpath: str
requirements: set[str]
resolve(constraint, requirements)
Parameters:
  • constraint (str) – A .in file relative path

  • requirements (set[str]) – The .in file’s requirement lines, which might have silly version upper limits. No attempt is made to address these upper bounds version limits

stem: str
class drain_swamp.lock_infile.InFileType(value)

Each .in files constaints and requirements have to be resolved. This occurs recursively. Once resolved, InFile is moved from FILES –> ZEROES set

FILES = "_files"

.in file that has unresolved -c (constraints) and -r (requirements)

ZEROES = "_zeroes"

.in file that have all -c (constraints) and -r (requirements) resolved

class drain_swamp.lock_infile.InFiles(cwd: Path, in_files: dataclasses.InitVar[collections.abc.Sequence[pathlib.Path]])

Container of InFile

Variables:
  • cwd (pathlib.Path) – current working directory

  • in_files (collections.abc.Sequence[pathlib.Path]) – Requirements files. Relative path to .in files

  • _files (set[InFile]) – Set of InFile. Which contains the relative path to a Requirement file. May contain unresolved constraints

  • _zeroes (set[InFile]) – Set of InFile that have all constraints resolved

Raises:
cwd: Path
property files

Generator of InFile

Returns:

Yields InFile. These tend to contain constraints

Return type:

collections.abc.Generator[drain_swamp.lock_infile.InFile, None, None]

get_by_relpath(relpath, set_name=InFileType.FILES)

Get the index and InFile

Parameters:
Returns:

The .in file and index within InFiles

Return type:

drain_swamp.lock_infile.InFile | None

Raises:
  • ValueError – Unsupported type. relpath is neither str nor Path

in_files: dataclasses.InitVar[collections.abc.Sequence[pathlib.Path]]
in_generic(val, set_name=InFileType.FILES)

A generic __contains__

Parameters:
Returns:

True if InFile contained within zeroes otherwise False

Return type:

bool

in_zeroes(val)

Check if within zeroes

Parameters:

val (Any) – item to check if within zeroes

Returns:

True if InFile contained within zeroes otherwise False

Return type:

bool

static is_requirement_or_constraint(line)

Line identify if a requirement (-r) or constraint (-c)

Parameters:

line (str) – .in file line is a file which should be included

Returns:

True if a line needs to be included otherwise False

Return type:

bool

static line_comment_or_blank(line)

Comments or blank lines can be safely ignored

Parameters:

line (str) – .in file line to check if inconsequential

Returns:

True if a line which can be safely ignored otherwise False

Return type:

bool

move_zeroes()

Zeroes have had all their constraints resolved and therefore do not need to be further scrutinized.

resolution_loop()

Run loop of resolve_zeroes calls, sampling before and after counts. If not fully resolved and two iterations have the same result, raise an Exception

Raises:
resolve_zeroes()

If a requirements file have constraint(s) that can be resolved, by a zero, do so.

_files and _zeroes are both type, set. Modifying an element modifies element within the set

write()

After resolving all constraints. Write out all .unlock files

Returns:

Generator of .unlock absolute paths

Return type:

collections.abc.Generator[pathlib.Path, None, None]

property zeroes

Generator of InFile

Returns:

Yields InFile without any constraints

Return type:

collections.abc.Generator[drain_swamp.lock_infile.InFile, None, None]

drain_swamp.lock_infile.strip_inline_comments(val)

Strip off inline comments. Which may be to the right of a requirement

Parameters:

val (str) – line with contains a requirement and optionally an in-line comment

Returns:

Requirement without a inline comment

Return type:

str