aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiƩbaud Weksteen <tweek@google.com>2020-08-28 14:58:45 +0200
committerThiƩbaud Weksteen <tweek@google.com>2020-09-01 09:52:13 +0200
commitc9ba009aab3783cca8a71389de6ec2701c916b5e (patch)
tree33fd89c4413e02f5b12d92c8c390690c8bb178b9
parent7698778fb0f02c517ca0ffe6f85f80991e49e4a3 (diff)
downloadrepohooks-c9ba009aab3783cca8a71389de6ec2701c916b5e.tar.gz
config: add {Local,Global}PreUploadFile classes
Creates 2 new classes to differentiate local (PREUPLOAD.cfg) and global (GLOBAL-PREUPLOAD.cfg) files. While not useful yet, this allows to implement validation that is specific to local files. Ideally, PreUploadFile would be declared as @abstractclass but the support for py2/py3 makes this constraint tedious to implement. Test: pre-upload.py Bug: 160223496 Change-Id: I75e0e644f713002f1ba50a405965362c1c5a7589
-rw-r--r--rh/config.py58
-rwxr-xr-xrh/config_unittest.py4
2 files changed, 46 insertions, 16 deletions
diff --git a/rh/config.py b/rh/config.py
index 6240559..459d691 100644
--- a/rh/config.py
+++ b/rh/config.py
@@ -18,6 +18,7 @@
from __future__ import print_function
import functools
+import itertools
import os
import shlex
import sys
@@ -123,7 +124,8 @@ class PreUploadConfig(object):
Args:
config: A configparse.ConfigParser instance.
- source: Where this config came from.
+ source: Where this config came from. This is used in error messages to
+ facilitate debugging. It is not necessarily a valid path.
"""
self.config = config if config else RawConfigParser()
self.source = source
@@ -253,7 +255,15 @@ class PreUploadConfig(object):
class PreUploadFile(PreUploadConfig):
- """A single config (file) used for `repo upload` hooks."""
+ """A single config (file) used for `repo upload` hooks.
+
+ This is an abstract class that requires subclasses to define the FILENAME
+ constant.
+
+ Attributes:
+ path: The path of the file.
+ """
+ FILENAME = None
def __init__(self, path):
"""Initialize.
@@ -263,6 +273,7 @@ class PreUploadFile(PreUploadConfig):
"""
super(PreUploadFile, self).__init__(source=path)
+ self.path = path
try:
self.config.read(path)
except configparser.ParsingError as e:
@@ -270,6 +281,31 @@ class PreUploadFile(PreUploadConfig):
self._validate()
+ @classmethod
+ def from_paths(cls, paths):
+ """Search for files within paths that matches the class FILENAME.
+
+ Args:
+ paths: List of directories to look for config files.
+
+ Yields:
+ For each valid file found, an instance is created and returned.
+ """
+ for path in paths:
+ path = os.path.join(path, cls.FILENAME)
+ if os.path.exists(path):
+ yield cls(path)
+
+
+class LocalPreUploadFile(PreUploadFile):
+ """A single config file for a project (PREUPLOAD.cfg)."""
+ FILENAME = 'PREUPLOAD.cfg'
+
+
+class GlobalPreUploadFile(PreUploadFile):
+ """A single config file for a repo (GLOBAL-PREUPLOAD.cfg)."""
+ FILENAME = 'GLOBAL-PREUPLOAD.cfg'
+
class PreUploadSettings(PreUploadConfig):
"""Settings for `repo upload` hooks.
@@ -278,9 +314,6 @@ class PreUploadSettings(PreUploadConfig):
settings for a particular project.
"""
- FILENAME = 'PREUPLOAD.cfg'
- GLOBAL_FILENAME = 'GLOBAL-PREUPLOAD.cfg'
-
def __init__(self, paths=('',), global_paths=()):
"""Initialize.
@@ -292,16 +325,13 @@ class PreUploadSettings(PreUploadConfig):
"""
super(PreUploadSettings, self).__init__()
- def _search(paths, filename):
- for path in paths:
- path = os.path.join(path, filename)
- if os.path.exists(path):
- self.paths.append(path)
- self.update(PreUploadFile(path))
-
self.paths = []
- _search(global_paths, self.GLOBAL_FILENAME)
- _search(paths, self.FILENAME)
+ for config in itertools.chain(
+ GlobalPreUploadFile.from_paths(global_paths),
+ LocalPreUploadFile.from_paths(paths)):
+ self.paths.append(config.path)
+ self.update(config)
+
# We validated configs in isolation, now do one final pass altogether.
self.source = '{%s}' % '|'.join(self.paths)
diff --git a/rh/config_unittest.py b/rh/config_unittest.py
index 08128e8..596e17b 100755
--- a/rh/config_unittest.py
+++ b/rh/config_unittest.py
@@ -127,7 +127,7 @@ class PreUploadSettingsTests(unittest.TestCase):
def _write_config(self, data, filename=None):
"""Helper to write out a config file for testing."""
if filename is None:
- filename = rh.config.PreUploadSettings.FILENAME
+ filename = rh.config.LocalPreUploadFile.FILENAME
path = os.path.join(self.tempdir, filename)
with open(path, 'w') as fp:
fp.write(data)
@@ -135,7 +135,7 @@ class PreUploadSettingsTests(unittest.TestCase):
def _write_global_config(self, data):
"""Helper to write out a global config file for testing."""
self._write_config(
- data, filename=rh.config.PreUploadSettings.GLOBAL_FILENAME)
+ data, filename=rh.config.GlobalPreUploadFile.FILENAME)
def testGlobalConfigs(self):
"""Verify global configs stack properly."""