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.
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/PKG-INFO +40 -5
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/README.md +35 -1
- prepare_assignment-0.2.0/prepare_assignment/__init__.py +3 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/cli/main.py +23 -6
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/main.py +4 -3
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/preparer.py +2 -2
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/runner.py +2 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/subsituter.py +3 -3
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/task_handler.py +2 -3
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/validator.py +2 -3
- prepare_assignment-0.2.0/prepare_assignment/data/config.py +20 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/constants.py +2 -10
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/task_properties.py +1 -1
- prepare_assignment-0.2.0/prepare_assignment/schemas/config.schema.json +33 -0
- prepare_assignment-0.2.0/prepare_assignment/utils/config.py +56 -0
- prepare_assignment-0.1.2/prepare_assignment/utils/cache.py → prepare_assignment-0.2.0/prepare_assignment/utils/paths.py +26 -1
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/tasks.py +2 -2
- prepare_assignment-0.2.0/prepare_assignment/utils/virtual_env.py +15 -0
- prepare_assignment-0.2.0/prepare_assignment/utils/yml_loader.py +5 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/pyproject.toml +3 -2
- prepare_assignment-0.1.2/prepare_assignment/data/config.py +0 -15
- prepare_assignment-0.1.2/prepare_assignment/data/dependency_graph.py +0 -33
- prepare_assignment-0.1.2/prepare_assignment/utils/__init__.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/LICENSE +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/__main__.py +0 -0
- {prepare_assignment-0.1.2/prepare_assignment → prepare_assignment-0.2.0/prepare_assignment/cli}/__init__.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/cli/task.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/cli/tasks.py +0 -0
- {prepare_assignment-0.1.2/prepare_assignment/cli → prepare_assignment-0.2.0/prepare_assignment/core}/__init__.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/command.py +0 -0
- {prepare_assignment-0.1.2/prepare_assignment/core → prepare_assignment-0.2.0/prepare_assignment/data}/__init__.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/errors.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/job_environment.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/prepare.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/task_definition.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/schemas/prepare.schema.json +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/schemas/task.schema.json +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/schemas/task.schema.json_template +0 -0
- {prepare_assignment-0.1.2/prepare_assignment/data → prepare_assignment-0.2.0/prepare_assignment/utils}/__init__.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/default_validator.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/dependency.py +0 -0
- {prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/executables.py +0 -0
- {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
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: prepare-assignment
|
|
3
|
-
Version: 0.
|
|
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
|
+
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
|
-
##
|
|
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
|
-
##
|
|
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:
|
|
@@ -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
|
-
] =
|
|
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
|
-
] =
|
|
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
|
-
] =
|
|
51
|
+
] = CONFIG.core.verbose
|
|
35
52
|
):
|
|
36
53
|
"""
|
|
37
54
|
Parse 'prepare_assignment.y(a)ml' and execute all jobs
|
|
38
55
|
"""
|
|
39
|
-
CONFIG.
|
|
40
|
-
CONFIG.
|
|
41
|
-
CONFIG.
|
|
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
|
|
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.
|
|
48
|
-
set_logger_level(tasks_logger, CONFIG.
|
|
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.
|
|
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.
|
|
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
|
|
{prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/core/task_handler.py
RENAMED
|
@@ -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 =
|
|
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
|
|
@@ -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.
|
|
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)"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "prepare-assignment"
|
|
3
|
-
version = "0.
|
|
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.
|
|
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)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/job_environment.py
RENAMED
|
File without changes
|
|
File without changes
|
{prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/data/task_definition.py
RENAMED
|
File without changes
|
{prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/schemas/prepare.schema.json
RENAMED
|
File without changes
|
{prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/schemas/task.schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/default_validator.py
RENAMED
|
File without changes
|
{prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/dependency.py
RENAMED
|
File without changes
|
{prepare_assignment-0.1.2 → prepare_assignment-0.2.0}/prepare_assignment/utils/executables.py
RENAMED
|
File without changes
|
|
File without changes
|