Skip to content

Commit 2c1348a

Browse files
author
Alex Burke
committed
Add header and docstrings throughout the file.
1 parent 6597a2a commit 2c1348a

1 file changed

Lines changed: 81 additions & 7 deletions

File tree

mig/install/features.py

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,29 @@
11
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
#
4+
# --- BEGIN_HEADER ---
5+
#
6+
# features - bootstrap tool for managing per-feature dependencies
7+
# Copyright (C) 2003-2026 The MiG Project by the Science HPC Center at UCPH
8+
#
9+
# This file is part of MiG.
10+
#
11+
# MiG is free software: you can redistribute it and/or modify
12+
# it under the terms of the GNU General Public License as published by
13+
# the Free Software Foundation; either version 2 of the License, or
14+
# (at your option) any later version.
15+
#
16+
# MiG is distributed in the hope that it will be useful,
17+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
# GNU General Public License for more details.
20+
#
21+
# You should have received a copy of the GNU General Public License
22+
# along with this program; if not, write to the Free Software
23+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24+
#
25+
# -- END_HEADER ---
26+
#
227

328
import argparse
429
from collections import defaultdict
@@ -32,6 +57,9 @@
3257

3358

3459
def warn(msg=''):
60+
"""
61+
Wrapper function for printing to stderr.
62+
"""
3563
print(msg, file=sys.stderr)
3664

3765

@@ -149,6 +177,9 @@ def list_enabled_features(self, return_as=list):
149177
if self._enabled_by_feature[feature_name]))
150178

151179
def required_package_names(self, feature_name):
180+
"""
181+
Return the set of required packages for a named feature.
182+
"""
152183
return set((Features._strip_version_if_present(entry.requirement)
153184
for entry in self._requirements_by_feature[feature_name]))
154185

@@ -176,9 +207,12 @@ def _interpret_feature_definition(feature_name, feature_definition, requirements
176207

177208
@staticmethod
178209
def _is_package_present(package_name):
210+
"""
211+
Determine whether a package is available to the active interpreter.
212+
"""
213+
179214
try:
180215
importlib.util.find_spec(package_name)
181-
182216
return True
183217
except ModuleNotFoundError as exc:
184218
return False
@@ -213,6 +247,11 @@ def expand_definitions(definitions, requirements_dir):
213247

214248
@classmethod
215249
def from_definitions_file(cls, features_file, requirements_dir, overrides_supported={}):
250+
"""
251+
Return a Features instance populated with the features declared
252+
within the specified definitions file.
253+
"""
254+
216255
assert os.path.isabs(features_file)
217256
with open(features_file) as thefile:
218257
definitions = ConfigParser()
@@ -221,6 +260,13 @@ def from_definitions_file(cls, features_file, requirements_dir, overrides_suppor
221260

222261
@staticmethod
223262
def match_env_dict(features, env_dict):
263+
"""
264+
Check the supplied dictionary for env-style flags (i.e. ENABLE_<NAME>)
265+
which indicate whether the correspnding feature should be enabled and
266+
optionally - based upon the definitions - for any applicable version
267+
overrides being specified if such flags are supported.
268+
"""
269+
224270
def enabled_or_fallback(feature_name):
225271
try:
226272
enable_string = env_dict[f"ENABLE_{feature_name.upper()}"]
@@ -248,6 +294,10 @@ def enabled_or_fallback(feature_name):
248294

249295
@staticmethod
250296
def match_dotenv_file(features, dotenv_file):
297+
"""
298+
Match a .env file for feature enablement and overrides.
299+
"""
300+
251301
from dotenv import dotenv_values
252302

253303
assert os.path.isabs(dotenv_file)
@@ -257,6 +307,10 @@ def match_dotenv_file(features, dotenv_file):
257307

258308
@staticmethod
259309
def match_configuration_file(features, configuration_file):
310+
"""
311+
Match a .configuration file for feature enablement and overrides.
312+
"""
313+
260314
from mig.shared.conf import get_configuration_object
261315
configuration = get_configuration_object(configuration_file, skip_log=True, disable_auth_log=True)
262316

@@ -271,7 +325,11 @@ def enabled_or_fallback(feature_name):
271325
return enabled_by_feature_name, {}
272326

273327

274-
def main_enabled(features, args, print=print, warn=warn):
328+
def subcommand_enabled(features, args, print=print, warn=warn):
329+
"""
330+
'enabled' subcommand executor.
331+
"""
332+
275333
if args.c:
276334
enabled_by_feature_name = Features.match_configuration_file(features, args.c)
277335
features.apply_enabled(enabled_by_feature_name)
@@ -288,7 +346,11 @@ def main_enabled(features, args, print=print, warn=warn):
288346
return 0
289347

290348

291-
def main_install(features, args, print=print, warn=warn):
349+
def subcommand_install(features, args, print=print, warn=warn):
350+
"""
351+
'install' subcommand executor.
352+
"""
353+
292354
if args.c:
293355
enabled_by_feature_name = Features.match_configuration_file(features, args.c)
294356
features.apply_enabled(enabled_by_feature_name)
@@ -313,18 +375,26 @@ def main_install(features, args, print=print, warn=warn):
313375
raise NotImplementedError("install is not currently implemented")
314376

315377

316-
def main_show(features, args, print=print, warn=warn):
378+
def subcommand_show(features, args, print=print, warn=warn):
379+
"""
380+
'show' subcommand executor.
381+
"""
382+
317383
print(f"available features: {', '.join(features.feature_names)}")
318384

319385

320386
_COMMAND_HANDLERS = dict(
321-
enabled=main_enabled,
322-
install=main_install,
323-
show=main_show,
387+
enabled=subcommand_enabled,
388+
install=subcommand_install,
389+
show=subcommand_show,
324390
)
325391

326392

327393
def main(argv):
394+
"""
395+
Main entrypoint function.
396+
"""
397+
328398
parser = argparse.ArgumentParser()
329399
subparsers = parser.add_subparsers(dest='command')
330400

@@ -351,6 +421,10 @@ def main(argv):
351421
return args_main(parser.parse_args(args=argv))
352422

353423
def args_main(args, *, print=print, warn=warn, features=None):
424+
"""
425+
Internal helper for executing the parsed arguments.
426+
"""
427+
354428
features = features or Features.from_definitions_file(
355429
FEATURES_FILE,
356430
FEATURES_REQUIREMENTS_DIR,

0 commit comments

Comments
 (0)