Skip to content

Commit 88147ac

Browse files
authored
Merge pull request #22 from MKLeb/hotfix/resolve-circular-imports
Allow passing a string or list of strings as the parent to avoid circular imports
2 parents 3debf50 + 8fdc094 commit 88147ac

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

changelog/22.improvement.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow passing a string or list of strings as the parent to avoid circular imports.

src/ptscripts/parser.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,43 @@ def __getattr__(self, attr):
413413
return getattr(self.parser, attr)
414414

415415

416+
class GroupReference:
417+
"""
418+
Simple class to hold tools command group names comparable to how
419+
they would be invoked using the CLI.
420+
421+
For example, tools vm create is stored as ("tools", "vm", "create")
422+
"""
423+
424+
_instance: GroupReference | None = None
425+
_commands: list[str]
426+
427+
def __new__(cls):
428+
"""
429+
Method that instantiates a singleton class and returns it.
430+
"""
431+
if cls._instance is None:
432+
instance = super().__new__(cls)
433+
instance._commands = {}
434+
cls._instance = instance
435+
return cls._instance
436+
437+
@classmethod
438+
def add_command(cls, cli_name: tuple[str], group: CommandGroup) -> None:
439+
"""
440+
Add a tools command.
441+
"""
442+
instance = cls()
443+
if cli_name not in instance._commands:
444+
instance._commands[cli_name] = group
445+
446+
def __getitem__(self, item):
447+
"""
448+
Propogate getting a command parser to the underlying dict.
449+
"""
450+
return self._commands[item]
451+
452+
416453
class CommandGroup:
417454
"""
418455
Command group which holds the available tool functions.
@@ -424,6 +461,16 @@ def __init__(self, name, help, description=None, parent=None, venv_config=None):
424461
description = help
425462
if parent is None:
426463
parent = Parser()
464+
GroupReference.add_command((name,), self)
465+
# We can also pass a string or list of strings that specify the parent commands.
466+
# This should help avoid circular imports
467+
if isinstance(parent, str):
468+
parent = [parent]
469+
if isinstance(parent, list):
470+
# NOTE: This means ordering of imports is important, but better than risking circular imports
471+
GroupReference.add_command(tuple(parent + [name]), self)
472+
parent = GroupReference()[tuple(parent)]
473+
427474
self.venv_config = venv_config or {}
428475
self.parser = parent.subparsers.add_parser(
429476
name.replace("_", "-"),

0 commit comments

Comments
 (0)