mirror of
https://github.com/TECHNOFAB11/bumpver.git
synced 2025-12-12 14:30:09 +01:00
85 lines
2.5 KiB
Python
85 lines
2.5 KiB
Python
# This file is part of the pycalver project
|
|
# https://github.com/mbarkhau/pycalver
|
|
#
|
|
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
|
# SPDX-License-Identifier: MIT
|
|
"""Parse PyCalVer strings from files."""
|
|
|
|
import typing as typ
|
|
|
|
from .patterns import Pattern
|
|
|
|
LineNo = int
|
|
Start = int
|
|
End = int
|
|
|
|
|
|
class LineSpan(typ.NamedTuple):
|
|
lineno: LineNo
|
|
start : Start
|
|
end : End
|
|
|
|
|
|
LineSpans = typ.List[LineSpan]
|
|
|
|
|
|
def _has_overlap(needle: LineSpan, haystack: LineSpans) -> bool:
|
|
for span in haystack:
|
|
# assume needle is in the center
|
|
has_overlap = (
|
|
span.lineno == needle.lineno
|
|
# needle starts before (or at) span end
|
|
and needle.start <= span.end
|
|
# needle ends after (or at) span start
|
|
and needle.end >= span.start
|
|
)
|
|
if has_overlap:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
class PatternMatch(typ.NamedTuple):
|
|
"""Container to mark a version string in a file."""
|
|
|
|
lineno : LineNo # zero based
|
|
line : str
|
|
pattern: Pattern
|
|
span : typ.Tuple[Start, End]
|
|
match : str
|
|
|
|
|
|
PatternMatches = typ.Iterable[PatternMatch]
|
|
|
|
|
|
def _iter_for_pattern(lines: typ.List[str], pattern: Pattern) -> PatternMatches:
|
|
for lineno, line in enumerate(lines):
|
|
match = pattern.regexp.search(line)
|
|
if match:
|
|
yield PatternMatch(lineno, line, pattern, match.span(), match.group(0))
|
|
|
|
|
|
def iter_matches(lines: typ.List[str], patterns: typ.List[Pattern]) -> PatternMatches:
|
|
"""Iterate over all matches of any pattern on any line.
|
|
|
|
>>> from . import v1patterns
|
|
>>> lines = ["__version__ = 'v201712.0002-alpha'"]
|
|
>>> version_pattern = "{pycalver}"
|
|
>>> raw_patterns = ["{pycalver}", "{pep440_pycalver}"]
|
|
>>> patterns = [v1patterns.compile_pattern(version_pattern, p) for p in raw_patterns]
|
|
>>> matches = list(iter_matches(lines, patterns))
|
|
>>> assert matches[0] == PatternMatch(
|
|
... lineno = 0,
|
|
... line = "__version__ = 'v201712.0002-alpha'",
|
|
... pattern= v1patterns.compile_pattern(version_pattern),
|
|
... span = (15, 33),
|
|
... match = "v201712.0002-alpha",
|
|
... )
|
|
"""
|
|
matched_spans: LineSpans = []
|
|
for pattern in patterns:
|
|
for match in _iter_for_pattern(lines, pattern):
|
|
needle_span = LineSpan(match.lineno, *match.span)
|
|
if not _has_overlap(needle_span, matched_spans):
|
|
yield match
|
|
matched_spans.append(needle_span)
|