prepare-assignment 0.1.2__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/PKG-INFO +40 -5
  2. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/README.md +35 -1
  3. prepare_assignment-0.2.0/prepare_assignment/__init__.py +3 -0
  4. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/cli/main.py +23 -6
  5. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/main.py +4 -3
  6. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/preparer.py +2 -2
  7. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/runner.py +2 -0
  8. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/subsituter.py +3 -3
  9. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/task_handler.py +2 -3
  10. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/validator.py +2 -3
  11. prepare_assignment-0.2.0/prepare_assignment/data/config.py +20 -0
  12. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/constants.py +2 -10
  13. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/task_properties.py +1 -1
  14. prepare_assignment-0.2.0/prepare_assignment/schemas/config.schema.json +33 -0
  15. prepare_assignment-0.2.0/prepare_assignment/utils/config.py +56 -0
  16. prepare_assignment-0.1.2/prepare_assignment/utils/cache.py → prepare_assignment-0.2.0/prepare_assignment/utils/paths.py +26 -1
  17. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/tasks.py +2 -2
  18. prepare_assignment-0.2.0/prepare_assignment/utils/virtual_env.py +15 -0
  19. prepare_assignment-0.2.0/prepare_assignment/utils/yml_loader.py +5 -0
  20. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/pyproject.toml +3 -2
  21. prepare_assignment-0.1.2/prepare_assignment/data/config.py +0 -15
  22. prepare_assignment-0.1.2/prepare_assignment/data/dependency_graph.py +0 -33
  23. prepare_assignment-0.1.2/prepare_assignment/utils/__init__.py +0 -0
  24. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/LICENSE +0 -0
  25. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/__main__.py +0 -0
  26. {prepare_assignment-0.1.2/prepare_assignment → prepare_assignment-0.2.0/prepare_assignment/cli}/__init__.py +0 -0
  27. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/cli/task.py +0 -0
  28. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/cli/tasks.py +0 -0
  29. {prepare_assignment-0.1.2/prepare_assignment/cli → prepare_assignment-0.2.0/prepare_assignment/core}/__init__.py +0 -0
  30. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/command.py +0 -0
  31. {prepare_assignment-0.1.2/prepare_assignment/core → prepare_assignment-0.2.0/prepare_assignment/data}/__init__.py +0 -0
  32. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/errors.py +0 -0
  33. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/job_environment.py +0 -0
  34. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/prepare.py +0 -0
  35. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/task_definition.py +0 -0
  36. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/schemas/prepare.schema.json +0 -0
  37. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/schemas/task.schema.json +0 -0
  38. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/schemas/task.schema.json_template +0 -0
  39. {prepare_assignment-0.1.2/prepare_assignment/data → prepare_assignment-0.2.0/prepare_assignment/utils}/__init__.py +0 -0
  40. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/default_validator.py +0 -0
  41. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/dependency.py +0 -0
  42. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/executables.py +0 -0
  43. {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/logger.py +0 -0
@@ -1,18 +1,19 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: prepare-assignment
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Prepare assignment
5
5
  License: MIT
6
6
  Author: Bonajo
7
7
  Author-email: m.bonajo@fontys.nl
8
- Requires-Python: >=3.8,<4.0
8
+ Requires-Python: >=3.9,<4.0
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.8
12
11
  Classifier: Programming Language :: Python :: 3.9
13
12
  Classifier: Programming Language :: Python :: 3.10
14
13
  Classifier: Programming Language :: Python :: 3.11
15
14
  Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Dist: dacite (>=1.9.2,<2.0.0)
16
17
  Requires-Dist: gitpython (>=3.1.41,<4.0.0)
17
18
  Requires-Dist: importlib-resources (>=6.1.1,<7.0.0)
18
19
  Requires-Dist: jsonschema (>=4.21.1,<5.0.0)
@@ -33,7 +34,28 @@ Prepare assignment is a GitHub Actions inspired helper tool to prepare assignmen
33
34
  - Git
34
35
  - Python >=3.8
35
36
 
36
- ## Example
37
+ ## Installation
38
+
39
+ Prepare-assignment is available from [PyPI](https://pypi.org/).
40
+
41
+
42
+ ```bash
43
+ # To install:
44
+ python3 -m pip install prepare-assignment
45
+
46
+ # To upgrade
47
+ python3 -m pip install --upgrade prepare-assignment
48
+ ```
49
+
50
+ ## Executing prepare-assignment
51
+
52
+ To execute a `prepare.yml` simply run `prepare run` from the same directory.
53
+
54
+ ### Command line interface
55
+
56
+ Use `prepare --help` to which commands and flags are available.
57
+
58
+ ## Example `prepare.yml`
37
59
 
38
60
  First we need to have tasks available that can be executed. Take for example a look at the [remove](https://github.com/prepare-assignment/remove) task.
39
61
 
@@ -66,6 +88,19 @@ jobs:
66
88
 
67
89
  For people familiar with GitHub Actions this should look very familiar. We have jobs that indicate what should happen to prepare an assignment. The tasks are defined in their own repositories, if the `uses` tag doesn't have a username/organization, it will default to `prepare-assignment`. So for example the `remove` task uses the following repository: [prepare-assignment/remove](https://github.com/prepare-assignment/remove)
68
90
 
91
+ ## Config file
92
+
93
+ It is possible to specify global options in a config file. The location of the config file can be found by running `prepare` without any commands.
94
+
95
+ The following settings are available:
96
+
97
+ ```yml
98
+ core:
99
+ git-mode: "ssh|https"
100
+ verbose: int
101
+ debug: int
102
+ ```
103
+
69
104
  ## Tasks
70
105
 
71
106
  There are three different kind of tasks available:
@@ -7,7 +7,28 @@ Prepare assignment is a GitHub Actions inspired helper tool to prepare assignmen
7
7
  - Git
8
8
  - Python >=3.8
9
9
 
10
- ## Example
10
+ ## Installation
11
+
12
+ Prepare-assignment is available from [PyPI](https://pypi.org/).
13
+
14
+
15
+ ```bash
16
+ # To install:
17
+ python3 -m pip install prepare-assignment
18
+
19
+ # To upgrade
20
+ python3 -m pip install --upgrade prepare-assignment
21
+ ```
22
+
23
+ ## Executing prepare-assignment
24
+
25
+ To execute a `prepare.yml` simply run `prepare run` from the same directory.
26
+
27
+ ### Command line interface
28
+
29
+ Use `prepare --help` to which commands and flags are available.
30
+
31
+ ## Example `prepare.yml`
11
32
 
12
33
  First we need to have tasks available that can be executed. Take for example a look at the [remove](https://github.com/prepare-assignment/remove) task.
13
34
 
@@ -40,6 +61,19 @@ jobs:
40
61
 
41
62
  For people familiar with GitHub Actions this should look very familiar. We have jobs that indicate what should happen to prepare an assignment. The tasks are defined in their own repositories, if the `uses` tag doesn't have a username/organization, it will default to `prepare-assignment`. So for example the `remove` task uses the following repository: [prepare-assignment/remove](https://github.com/prepare-assignment/remove)
42
63
 
64
+ ## Config file
65
+
66
+ It is possible to specify global options in a config file. The location of the config file can be found by running `prepare` without any commands.
67
+
68
+ The following settings are available:
69
+
70
+ ```yml
71
+ core:
72
+ git-mode: "ssh|https"
73
+ verbose: int
74
+ debug: int
75
+ ```
76
+
43
77
  ## Tasks
44
78
 
45
79
  There are three different kind of tasks available:
@@ -0,0 +1,3 @@
1
+ from importlib.metadata import version
2
+
3
+ __version__ = version("prepare_assignment")
@@ -1,19 +1,36 @@
1
+ import os.path
2
+ import sys
1
3
  from typing import Optional
2
4
 
3
5
  import typer
4
6
  from typing_extensions import Annotated
5
7
 
8
+ from prepare_assignment import __version__
6
9
  from prepare_assignment.cli.task import app as task_app
7
10
  from prepare_assignment.cli.tasks import app as tasks_app
8
11
  from prepare_assignment.core.main import prepare
9
12
  from prepare_assignment.data.config import GitMode
10
13
  from prepare_assignment.data.constants import CONFIG
14
+ from prepare_assignment.utils.paths import get_config_path
15
+ from prepare_assignment.utils.virtual_env import get_virtualenv_name
11
16
 
12
17
  app = typer.Typer(invoke_without_command=True)
13
18
  app.add_typer(task_app, name="task")
14
19
  app.add_typer(tasks_app, name="tasks")
15
20
 
16
21
 
22
+ @app.callback(invoke_without_command=True)
23
+ def main(ctx: typer.Context):
24
+ if ctx.invoked_subcommand is None:
25
+ config_path = os.path.join(get_config_path(), 'config.yml')
26
+ config_exists = os.path.exists(config_path)
27
+ typer.echo(f"Prepare version: {__version__}")
28
+ typer.echo(f"Config in use: {config_exists}")
29
+ typer.echo(f"Config path: {config_path}")
30
+ typer.echo(f"Python version: {sys.version.split(' ')[0]}")
31
+ typer.echo(f"Virtual env: {get_virtualenv_name()}")
32
+
33
+
17
34
  @app.command()
18
35
  def run(
19
36
  file_name: Annotated[
@@ -23,22 +40,22 @@ def run(
23
40
  git: Annotated[
24
41
  GitMode,
25
42
  typer.Option(case_sensitive=False, help="Clone mode for git, options are 'ssh' (default) or 'https'")
26
- ] = GitMode.ssh,
43
+ ] = CONFIG.core.git_mode,
27
44
  debug: Annotated[
28
45
  int,
29
46
  typer.Option("--debug", "-d", count=True, help="increase debug verbosity for prepare assignment")
30
- ] = 0,
47
+ ] = CONFIG.core.debug,
31
48
  verbose: Annotated[
32
49
  int,
33
50
  typer.Option("--verbose", "-v", count=True, help="increase task output verbosity")
34
- ] = 0
51
+ ] = CONFIG.core.verbose
35
52
  ):
36
53
  """
37
54
  Parse 'prepare_assignment.y(a)ml' and execute all jobs
38
55
  """
39
- CONFIG.DEBUG = debug # type: ignore
40
- CONFIG.GIT_MODE = git # type: ignore
41
- CONFIG.VERBOSITY = verbose # type: ignore
56
+ CONFIG.core.debug = debug # type: ignore
57
+ CONFIG.core.git_mode = git # type: ignore
58
+ CONFIG.core.verbose = verbose # type: ignore
42
59
 
43
60
  prepare(file_name)
44
61
 
@@ -8,10 +8,11 @@ from prepare_toolbox.file import get_matching_files
8
8
  from prepare_assignment.core.preparer import prepare_tasks
9
9
  from prepare_assignment.core.runner import run
10
10
  from prepare_assignment.core.validator import validate_prepare
11
- from prepare_assignment.data.constants import CONFIG, YAML_LOADER
11
+ from prepare_assignment.data.constants import CONFIG
12
12
  from prepare_assignment.data.errors import PrepareTaskError, PrepareError
13
13
  from prepare_assignment.data.prepare import Prepare
14
14
  from prepare_assignment.utils.logger import add_logging_level, set_logger_level
15
+ from prepare_assignment.utils.yml_loader import YAML_LOADER
15
16
 
16
17
 
17
18
  def __get_prepare_file(file: Optional[str]) -> str:
@@ -44,8 +45,8 @@ def prepare(file_name: Optional[str]) -> None:
44
45
  add_logging_level("TRACE", logging.DEBUG - 5, "trace")
45
46
  logger = logging.getLogger("prepare_assignment")
46
47
  tasks_logger = logging.getLogger("tasks")
47
- set_logger_level(logger, CONFIG.DEBUG)
48
- set_logger_level(tasks_logger, CONFIG.VERBOSITY, prefix="\t[TASK] ", debug_linenumbers=False)
48
+ set_logger_level(logger, CONFIG.core.debug)
49
+ set_logger_level(tasks_logger, CONFIG.core.verbose, prefix="\t[TASK] ", debug_linenumbers=False)
49
50
 
50
51
  try:
51
52
  # Get the prepare_assignment.yml file
@@ -19,7 +19,7 @@ from prepare_assignment.data.errors import DependencyError, ValidationError, Pre
19
19
  from prepare_assignment.data.task_definition import TaskDefinition, CompositeTaskDefinition, \
20
20
  PythonTaskDefinition, ValidableTask
21
21
  from prepare_assignment.data.task_properties import TaskProperties
22
- from prepare_assignment.utils.cache import get_cache_path, get_tasks_path
22
+ from prepare_assignment.utils.paths import get_cache_path, get_tasks_path
23
23
 
24
24
  # Set the cache path
25
25
  cache_path = get_cache_path()
@@ -40,7 +40,7 @@ def __download_task(props: TaskProperties) -> Path:
40
40
  """
41
41
  props.repo_path.mkdir(parents=True, exist_ok=True)
42
42
  git_url: str
43
- if CONFIG.GIT_MODE == "https":
43
+ if CONFIG.core.git_mode == "https":
44
44
  git_url = f"https://github.com/{props.organization}/{props.name}.git"
45
45
  else:
46
46
  git_url = f"git@github.com:{props.organization}/{props.name}.git"
@@ -1,3 +1,4 @@
1
+ import copy
1
2
  import json
2
3
  import logging
3
4
  import os.path
@@ -107,6 +108,7 @@ def __handle_task(mapping: Dict[str, TaskDefinition],
107
108
  sub_env = environment.environment.copy()
108
109
  sub_environment = JobEnvironment(sub_env, outputs={}, inputs=task.with_) # type: ignore
109
110
  for subtask in task_definition.tasks: # type: ignore
111
+ subtask = copy.deepcopy(subtask)
110
112
  subtask = Task.of(subtask)
111
113
  __handle_task(mapping, subtask, sub_environment)
112
114
  else:
@@ -73,9 +73,9 @@ def __substitute(value: str, environment: JobEnvironment, is_list: bool = False)
73
73
  })
74
74
  previous = 0
75
75
  result = ""
76
- for sub in substitutions:
77
- result += value[previous:sub["start"]] + sub["sub"]
78
- previous = sub["end"]
76
+ for sub in substitutions: # type: ignore
77
+ result += value[previous:sub["start"]] + sub["sub"] # type: ignore
78
+ previous = sub["end"] # type: ignore
79
79
  return result
80
80
 
81
81
 
@@ -2,19 +2,18 @@ import logging
2
2
  import os.path
3
3
  import shutil
4
4
  import sys
5
- from pathlib import Path
6
5
  from typing import Set
7
6
 
8
7
  import typer
9
8
  from treelib import Tree
10
9
 
11
10
  from prepare_assignment.core.preparer import __prepare_tasks
12
- from prepare_assignment.data.constants import YAML_LOADER
13
11
  from prepare_assignment.data.task_definition import TaskDefinition
14
12
  from prepare_assignment.data.task_properties import TaskProperties
15
- from prepare_assignment.utils.cache import get_tasks_path
16
13
  from prepare_assignment.utils.dependency import get_dependencies
14
+ from prepare_assignment.utils.paths import get_tasks_path
17
15
  from prepare_assignment.utils.tasks import get_all_tasks
16
+ from prepare_assignment.utils.yml_loader import YAML_LOADER
18
17
 
19
18
  logger = logging.getLogger("prepare_assignment")
20
19
  tasks_path = get_tasks_path()
@@ -9,12 +9,11 @@ from typing import Dict, Any, Type
9
9
  from importlib_resources import files
10
10
  from jsonschema.exceptions import ValidationError
11
11
  from jsonschema.validators import validate
12
- from ruamel.yaml import YAML
13
12
 
14
- from prepare_assignment.data.constants import YAML_LOADER
15
- from prepare_assignment.data.task_definition import TaskDefinition
16
13
  from prepare_assignment.data.errors import ValidationError as VE
14
+ from prepare_assignment.data.task_definition import TaskDefinition
17
15
  from prepare_assignment.utils.default_validator import DefaultValidatingValidator
16
+ from prepare_assignment.utils.yml_loader import YAML_LOADER
18
17
 
19
18
  logger = logging.getLogger("prepare_assignment")
20
19
 
@@ -0,0 +1,20 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+ from typing import Final, Literal, Optional
4
+
5
+
6
+ class GitMode(str, Enum):
7
+ ssh = "ssh"
8
+ https = "https"
9
+
10
+
11
+ @dataclass
12
+ class Core:
13
+ git_mode: GitMode = GitMode.ssh
14
+ verbose: int = 0
15
+ debug: int = 0
16
+
17
+
18
+ @dataclass
19
+ class Config:
20
+ core: Core
@@ -1,13 +1,9 @@
1
1
  import logging
2
- import os
3
2
  import re
4
- import shutil
5
- import sys
6
3
  from typing import Final, Dict, Type, List
7
4
 
8
- from ruamel.yaml import YAML
9
-
10
5
  from prepare_assignment.data.config import Config
6
+ from prepare_assignment.utils.config import load_config
11
7
  from prepare_assignment.utils.executables import get_bash_path
12
8
 
13
9
  TYPE_MAPPING: Final[Dict[str, Type]] = {
@@ -31,10 +27,6 @@ SUB_REGEX: Final[re.Pattern] = re.compile("|".join(SUBSTITUTIONS))
31
27
 
32
28
  LOG_LEVEL_TRACE: Final[int] = logging.DEBUG - 5
33
29
 
34
- CONFIG: Config = Config()
30
+ CONFIG: Config = load_config()
35
31
 
36
32
  BASH_EXECUTABLE: Final[str] = get_bash_path()
37
-
38
- YAML_LOADER = YAML(typ='safe')
39
- YAML_LOADER.brace_single_entry_mapping_in_flow_sequence = False
40
- YAML_LOADER.default_flow_style = True
@@ -5,7 +5,7 @@ from dataclasses import dataclass
5
5
  from functools import cached_property
6
6
  from pathlib import Path
7
7
 
8
- from prepare_assignment.utils.cache import get_tasks_path
8
+ from prepare_assignment.utils.paths import get_tasks_path
9
9
 
10
10
  tasks_path = get_tasks_path()
11
11
 
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "prepare-config",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "properties": {
7
+ "core": {
8
+ "type": "object",
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "git-mode": {
12
+ "description": "The mode git should use to checkout tasks",
13
+ "type": "string",
14
+ "enum": [
15
+ "ssh",
16
+ "https"
17
+ ],
18
+ "default": "ssh"
19
+ },
20
+ "debug": {
21
+ "description": "The level of debug messages to show",
22
+ "type": "integer",
23
+ "default": 0
24
+ },
25
+ "verbose": {
26
+ "description": "The level of verbosity",
27
+ "type": "integer",
28
+ "default": 0
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,56 @@
1
+ import json
2
+ import os.path
3
+ from enum import Enum
4
+ from typing import Dict, Any
5
+
6
+ import dacite
7
+ from dacite import from_dict
8
+ from importlib_resources import files
9
+ from pathlib import Path
10
+
11
+ from jsonschema import validate, ValidationError
12
+
13
+ from prepare_assignment.data.config import Config, Core
14
+ from prepare_assignment.data.errors import ValidationError as VE
15
+ from prepare_assignment.utils.paths import get_config_path
16
+ from prepare_assignment.utils.yml_loader import YAML_LOADER
17
+
18
+
19
+ def __convert_keys(obj: Any) -> Any:
20
+ if isinstance(obj, dict):
21
+ return {k.replace("-", "_"): __convert_keys(v) for k, v in obj.items()}
22
+ if isinstance(obj, list):
23
+ return [__convert_keys(i) for i in obj]
24
+ return obj
25
+
26
+
27
+ def __validate_config(config_path: Path, config: Dict[str, Any]) -> None:
28
+ schema_path = files().joinpath('../schemas/config.schema.json')
29
+ schema: Dict[str, Any] = json.loads(schema_path.read_text())
30
+
31
+ # Validate config.yml
32
+ try:
33
+ validate(config, schema)
34
+ except ValidationError as ve:
35
+ message = f"Error in config file: {config_path}, unable to verify '{ve.json_path}'\n\t -> {ve.message}"
36
+ raise VE(message)
37
+
38
+
39
+ def load_config() -> Config:
40
+ config_path = Path(os.path.join(get_config_path(), "config.yml"))
41
+ config = Config(Core())
42
+ if not config_path.is_file():
43
+ return config
44
+ yaml = YAML_LOADER.load(config_path)
45
+ # If the file is empty it is still valid config, but validator will fail with None
46
+ if not yaml:
47
+ return config
48
+
49
+ __validate_config(config_path, yaml)
50
+ converted_yaml = __convert_keys(yaml)
51
+ config = from_dict(
52
+ data_class=Config,
53
+ data=converted_yaml,
54
+ config=dacite.Config(cast=[Enum])
55
+ )
56
+ return config
@@ -2,12 +2,37 @@ import os
2
2
  import sys
3
3
 
4
4
  from pathlib import Path
5
- from typing import Final
5
+ from typing import Final, Optional
6
6
 
7
7
  TASKS_PATH: Final[str] = "tasks"
8
8
 
9
9
  __cache_path = None
10
10
  __tasks_path = None
11
+ __config_path: Optional[Path] = None
12
+
13
+
14
+ def get_config_path() -> Path:
15
+ """
16
+ Get the path to the default config location for applications
17
+ :return: Path to the OS specific application config location
18
+ :raises: AssertionError: if OS is not one of Linux, macOS or Windows
19
+ """
20
+ global __config_path
21
+ if __config_path:
22
+ return __config_path
23
+ if sys.platform == "linux":
24
+ config = os.environ.get("XDG_CONFIG_HOME")
25
+ if config is None:
26
+ config = "~/.config"
27
+ __config_path = Path(os.path.join(config, "prepare")).expanduser()
28
+ elif sys.platform == "darwin":
29
+ __config_path = Path("~/Library/Application Support/prepare").expanduser()
30
+ elif sys.platform == "win32":
31
+ ad = f"{os.environ.get('APPDATA')}"
32
+ __config_path = Path(os.path.join(ad, "prepare")).expanduser()
33
+ else:
34
+ raise AssertionError("Unsupported OS")
35
+ return __config_path
11
36
 
12
37
 
13
38
  def get_cache_path() -> Path:
@@ -1,10 +1,10 @@
1
1
  import os
2
2
  from typing import List
3
3
 
4
- from prepare_assignment.data.constants import YAML_LOADER
5
4
  from prepare_assignment.data.task_definition import TaskDefinition
6
5
  from prepare_assignment.data.task_properties import TaskProperties
7
- from prepare_assignment.utils.cache import get_tasks_path
6
+ from prepare_assignment.utils.paths import get_tasks_path
7
+ from prepare_assignment.utils.yml_loader import YAML_LOADER
8
8
 
9
9
 
10
10
  def get_all_tasks() -> List[TaskProperties]:
@@ -0,0 +1,15 @@
1
+ import os
2
+
3
+
4
+ def is_virtualenv_active() -> bool:
5
+ """Check if a virtual environment is active (including Poetry environments)."""
6
+ # Check if the VIRTUAL_ENV environment variable is set, which indicates a virtualenv is active
7
+ return os.getenv("VIRTUAL_ENV") is not None
8
+
9
+
10
+ def get_virtualenv_name() -> str:
11
+ """Get the name of the active virtual environment (works with Poetry as well)."""
12
+ virtualenv_path = os.getenv("VIRTUAL_ENV")
13
+ if virtualenv_path:
14
+ return os.path.basename(virtualenv_path) # Get the name from the virtualenv path
15
+ return "None (not active)"
@@ -0,0 +1,5 @@
1
+ from ruamel.yaml import YAML
2
+
3
+ YAML_LOADER = YAML(typ='safe')
4
+ YAML_LOADER.brace_single_entry_mapping_in_flow_sequence = False
5
+ YAML_LOADER.default_flow_style = True
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "prepare-assignment"
3
- version = "0.1.2"
3
+ version = "0.2.0"
4
4
  description = "Prepare assignment"
5
5
  authors = ["Bonajo <m.bonajo@fontys.nl>"]
6
6
  license = "MIT"
@@ -12,7 +12,7 @@ requires = ["poetry-core"]
12
12
  build-backend = "poetry.core.masonry.api"
13
13
 
14
14
  [tool.poetry.dependencies]
15
- python = "^3.8"
15
+ python = "^3.9"
16
16
  ruamel-yaml = "^0.18.5"
17
17
  jsonschema = "^4.21.1"
18
18
  importlib-resources = "^6.1.1"
@@ -22,6 +22,7 @@ virtualenv = "^20.25.0"
22
22
  typer = {extras = ["all"], version = "^0.9.0"}
23
23
  treelib = "^1.7.0"
24
24
  multipledispatch = "^1.0.0"
25
+ dacite = "^1.9.2"
25
26
 
26
27
  [tool.poetry.group.test.dependencies]
27
28
  mypy = "^1.1.1"
@@ -1,15 +0,0 @@
1
- from dataclasses import dataclass
2
- from enum import Enum
3
- from typing import Final, Literal
4
-
5
-
6
- class GitMode(str, Enum):
7
- ssh = "ssh"
8
- https = "https"
9
-
10
-
11
- @dataclass
12
- class Config:
13
- GIT_MODE: Final[GitMode] = GitMode.ssh
14
- VERBOSITY: Final[int] = 0
15
- DEBUG: Final[int] = 0
@@ -1,33 +0,0 @@
1
- from typing import Dict, List
2
-
3
-
4
- class Vertex:
5
-
6
- def __init__(self):
7
- self.dependents = []
8
- self.dependencies = []
9
-
10
-
11
- class DependencyGraph:
12
-
13
- def __init__(self):
14
- self.vertices: Dict[str, Vertex] = {}
15
-
16
- def add_node(self, name: str) -> None:
17
- if name in self.vertices:
18
- return
19
- self.vertices[name] = Vertex()
20
-
21
- def add_dependency(self, dependent: str, dependency: str) -> None:
22
- self.add_node(dependent)
23
- self.add_node(dependency)
24
- self.vertices[dependent].dependencies.append(dependency)
25
- self.vertices[dependency].dependents.append(dependent)
26
-
27
- def in_degree(self, name: str) -> int:
28
- vertex = self.vertices[name]
29
- return 0 if vertex is None else len(vertex.dependents)
30
-
31
- def out_degree(self, name: str) -> int:
32
- vertex = self.vertices[name]
33
- return 0 if vertex is None else len(vertex.dependencies)