Class: Dependabot::Python::DependencyGrapher::RequirementsLayers

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dependabot/python/dependency_grapher/requirements_layers.rb

Overview

Splits a directory of requirements files (pip / pip-compile) into one manifest group per "layer".

Python is the reported case of "layered requirements": a single directory can hold multiple independent requirements files (e.g. base-requirements.txt, test-requirements.txt) cross-linked with -r/-c.

Each 'layer' is its own manifest and must get its own snapshot, rather than the whole directory collapsing onto the first .txt alphabetically.

Constant Summary collapse

REQUIREMENTS_TXT_REGEX =

Matches "requirements" preceded by a hyphen, period, underscore, start-of-string, or slash, followed by non-whitespace chars and ".txt". Examples: requirements.txt, requirements.prod.txt, requirements/production.txt

T.let(%r{(?:[-._]|^|/)requirements[^\s]*\.txt$}i, Regexp)
REQUIRE_TXT_REGEX =

More lenient: matches "require" at the start of the filename or after a hyphen/period/underscore/ slash delimiter, with an optional hyphen/underscore/slash suffix. The leading delimiter prevents matching "require" as a substring of another word (e.g. "prequire.txt", "acquire.txt"). Examples: require.txt, require-test.txt, py3-require.txt, pyenv_require_e2e.txt

T.let(%r{(?:[-._]|^|/)require(?:[-_/][^\s.]*)?\.txt$}i, Regexp)
DEPENDENCIES_TXT_REGEX =

Matches "dependencies" / "dependency" preceded by a hyphen, period, underscore, start-of-string, or slash, followed by non-whitespace chars and ".txt". Examples: dependencies.txt, my-dependencies.txt, dependencies/python/ansible-lint.txt

T.let(%r{(?:[-._]|^|/)dependenc(?:y|ies)[^\s]*\.txt$}i, Regexp)
DEPEND_TXT_REGEX =

More lenient: matches "depend" / "depends" at the start of the filename or after a hyphen/period/ underscore/slash delimiter, with an optional hyphen/underscore/slash suffix. The leading delimiter prevents matching "depend" as a substring of another word (e.g. "independ.txt"). Examples: depend.txt, depends.txt, depend-test.txt, py3-depends.txt

T.let(%r{(?:[-._]|^|/)depend(?:s)?(?:[-_/][^\s.]*)?\.txt$}i, Regexp)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dependency_files:) ⇒ RequirementsLayers

Returns a new instance of RequirementsLayers.



82
83
84
# File 'lib/dependabot/python/dependency_grapher/requirements_layers.rb', line 82

def initialize(dependency_files:)
  @dependency_files = dependency_files
end

Class Method Details

.manifest_txt_filename?(path) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
56
57
58
# File 'lib/dependabot/python/dependency_grapher/requirements_layers.rb', line 53

def self.manifest_txt_filename?(path)
  path.match?(REQUIREMENTS_TXT_REGEX) ||
    path.match?(REQUIRE_TXT_REGEX) ||
    path.match?(DEPENDENCIES_TXT_REGEX) ||
    path.match?(DEPEND_TXT_REGEX)
end

.referenced_paths(file) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/dependabot/python/dependency_grapher/requirements_layers.rb', line 66

def self.referenced_paths(file)
  content = file.content
  return [] if content.nil?

  current_dir = File.dirname(file.name)
  referenced =
    content.scan(Dependabot::Python::SharedFileFetcher::CHILD_REQUIREMENT_REGEX).flatten +
    content.scan(Dependabot::Python::SharedFileFetcher::CONSTRAINT_REGEX).flatten

  referenced.map do |path|
    resolved = current_dir == "." ? path : File.join(current_dir, path)
    Pathname.new(resolved).cleanpath.to_path
  end
end

Instance Method Details

#groupsObject



91
92
93
94
95
96
97
98
# File 'lib/dependabot/python/dependency_grapher/requirements_layers.rb', line 91

def groups
  layer_primaries.map do |primary|
    Dependabot::DependencyGraphers::ManifestGroup.new(
      primary: primary,
      files: files_for_layer(primary)
    )
  end
end