Files
chromium_depot_tools/metadata/fields/custom/version.py
Jiewei Qian 79cfa048c0 metadata: early terminate certain fields to avoid over extraction
This CL adds a "early terminate the field based on field value" parser
mechanism to end the field as soon as the field value provides an
unambiguous answer to the question we care about.

This is to prevent over-extraction over certain fields (specifically,
local modifications) which can either be a definitive answer (e.g. No
modification) or multi-line free-form texts (which may contain unknown
fields that we don't care about at this stage).

This mitigates over extraction of README.chromium files like:

```
Local Modifications:
None

How to Uprev:
Steps...
```

Where the old parser would extract "None\n\nHow to Uprev:\nSteps..."

This CL also refactors single line fields to use the same early
termination mechanism since single line field simply ends as soon as
the line is parsed.

Union[Something, None] is changed to Optional[Something] based on
styleguide.

Bug: b/324149233
Change-Id: I3fca80eaceb071263f8ae8730afda230fff0bbb0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/5394917
Reviewed-by: Anne Redulla <aredulla@google.com>
Commit-Queue: Jiewei Qian <qjw@chromium.org>
2024-03-26 22:42:03 +00:00

58 lines
1.9 KiB
Python

#!/usr/bin/env python3
# Copyright 2023 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import re
import sys
from typing import Optional
_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
# The repo's root directory.
_ROOT_DIR = os.path.abspath(os.path.join(_THIS_DIR, "..", "..", ".."))
# Add the repo's root directory for clearer imports.
sys.path.insert(0, _ROOT_DIR)
import metadata.fields.field_types as field_types
import metadata.fields.util as util
import metadata.validation_result as vr
_PATTERN_NOT_APPLICABLE = re.compile(r"^N ?\/ ?A$", re.IGNORECASE)
def is_unknown(value: str) -> bool:
"""Returns whether the value denotes the version being unknown."""
return (value == "0" or util.matches(_PATTERN_NOT_APPLICABLE, value)
or util.is_unknown(value))
class VersionField(field_types.SingleLineTextField):
"""Custom field for the package version."""
def __init__(self):
super().__init__(name="Version")
def validate(self, value: str) -> Optional[vr.ValidationResult]:
"""Checks the given value is acceptable - there must be at least
one non-whitespace character, and "N/A" is preferred over "0" if
the version is unknown.
"""
if value == "0" or util.is_unknown(value):
return vr.ValidationWarning(
reason=f"{self._name} is '{value}'.",
additional=[
"Set this field to 'N/A' if this package does not version "
"or is versioned by date or revision.",
])
if util.is_empty(value):
return vr.ValidationError(
reason=f"{self._name} is empty.",
additional=[
"Set this field to 'N/A' if this package does not version "
"or is versioned by date or revision.",
])
return None