Module: StillActive::Pep440Helper

Extended by:
Pep440Helper
Included in:
Pep440Helper
Defined in:
lib/helpers/pep440_helper.rb

Overview

Translates a PEP 440 requires_python specifier into a RubyGems requirement STRING, so the generic RuntimeCeilingHelper can reason about a Python runtime ceiling with no core change -- the same way Ruby's ruby_version already feeds it. PEP 440 and RubyGems disagree on two operators that matter here:

- `~=` (compatible release) is a syntax error to Gem::Requirement, so a
naive parse raises and the ceiling is silently missed. It maps cleanly to
RubyGems `~>` for the major.minor.patch shapes `requires_python` uses.
- `== X.*` / `== X.Y.*` prefix wildcards are likewise unparseable and map to
a pessimistic `~>` over the prefix.

!= exclusions are dropped: a hole-punch can never create an upper bound, so it cannot be a runtime ceiling, and dropping it can only ADMIT more runtimes (fewer findings) -- conservative, never a false ceiling. Anything that still won't parse degrades to a dropped clause (or nil overall), never a raise: this feeds the core audit and must fail safe, matching RuntimeCeilingHelper's best-effort contract.

Constant Summary collapse

MAX_SPECIFIER_LENGTH =

Match ConstraintHelper / RuntimeCeilingHelper: bound pathological registry input before it reaches Gem::Requirement's own regex.

256
CLAUSE_PATTERN =

Operator, then the version as a run of non-space chars. \s*(\S+) (not \s*(.+)) keeps the two groups over disjoint character classes so there's no polynomial backtracking on pathological input like "<" + many spaces (a PEP 440 version never contains internal spaces, so this loses nothing).

/\A(===|==|~=|!=|<=|>=|<|>)\s*(\S+)\z/

Instance Method Summary collapse

Instance Method Details

#to_gem_requirement_string(specifier) ⇒ Object

=> a comma-joined RubyGems requirement string, or nil when nothing usable survives translation. The caller feeds the string to RuntimeCeilingHelper, which splits and splats it exactly like a ruby_version string.



37
38
39
40
41
42
43
44
45
# File 'lib/helpers/pep440_helper.rb', line 37

def to_gem_requirement_string(specifier)
  spec = specifier.to_s
  return if spec.strip.empty? || spec.length > MAX_SPECIFIER_LENGTH

  clauses = spec.split(",").filter_map { |clause| translate_clause(clause.strip) }
  return if clauses.empty?

  clauses.join(", ")
end