Skip to content
This repository has been archived by the owner on Jan 14, 2024. It is now read-only.

Commit

Permalink
YAML: Add package importing feature
Browse files Browse the repository at this point in the history
```yaml
imports:
  # single task
  - rkd.standardlib.docker.TagImageTask
  # package
  - rkd.standardlib.docker
  ```
  • Loading branch information
blackandred committed May 14, 2020
1 parent be25e8f commit 502df86
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 8 deletions.
3 changes: 1 addition & 2 deletions .rkd/makefile.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@

from rkd.syntax import TaskAliasDeclaration as Task
from rkd.standardlib.python import imports as PythonImports
from rkd.standardlib.docker import imports as DockerImports

IMPORTS = [] + PythonImports() + DockerImports()
IMPORTS = [] + PythonImports()

TASKS = [
Task(':release', description='Release RKD to PyPI (snapshot when on master, release on tag)',
Expand Down
3 changes: 2 additions & 1 deletion .rkd/makefile.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
version: org.riotkit.rkd/0.3
imports:
- rkd.standardlib.docker.TagImageTask
#- rkd.standardlib.docker.TagImageTask # example of importing single task without dependencies
- rkd.standardlib.docker # example of importing a package with dependencies

tasks:
:examples:bash-test:
Expand Down
33 changes: 29 additions & 4 deletions src/rkd/yaml_context.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

import yaml
import ast
import os
import importlib
from types import FunctionType
from argparse import ArgumentParser
from typing import List, Tuple, Union, Callable
from traceback import format_exc
Expand Down Expand Up @@ -182,7 +182,23 @@ def arguments_callback(parser: ArgumentParser):

@staticmethod
def parse_imports(classes: List[str]) -> List[TaskDeclaration]:
""" Parses imports strings into Python classes """
"""Parses imports strings into Python classes
Args:
classes: List of classes to import
Returns:
A list of basic task declarations with imported tasks inside
[
TaskDeclaration(ProtestWorkplaceTask()),
TaskDeclaration(StrikeWorkplaceTask()),
TaskDeclaration(OccupyWorkplaceTask()),
TaskDeclaration(RunProductionByWorkersOnTheirOwnTask())
]
Raises:
YamlParsingException: When a class or module does not exist
"""

parsed: List[TaskDeclaration] = []

Expand All @@ -191,6 +207,12 @@ def parse_imports(classes: List[str]) -> List[TaskDeclaration]:
class_name = parts[-1]
import_path = '.'.join(parts[:-1])

# Test if it's not a class name
# In this case we treat is as a module and import an importing method imports()
if class_name.lower() == class_name:
import_path += '.' + class_name
class_name = 'imports'

try:
module = importlib.import_module(import_path)
except ImportError as e:
Expand All @@ -200,9 +222,12 @@ def parse_imports(classes: List[str]) -> List[TaskDeclaration]:

if class_name not in dir(module):
raise YamlParsingException('Import "%s" is invalid. Class "%s" not found in module "%s"' % (
import_str, import_path, class_name
import_str, class_name, import_path
))

parsed.append(TaskDeclaration(module.__getattribute__(class_name)()))
if isinstance(module.__getattribute__(class_name), FunctionType):
parsed += module.__getattribute__(class_name)()
else:
parsed.append(TaskDeclaration(module.__getattribute__(class_name)()))

return parsed
16 changes: 15 additions & 1 deletion test/test_yaml_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,24 @@


class TestYamlContext(unittest.TestCase):
def test_parse_imports_successful_case(self):
def test_parse_imports_successful_case_single_task(self):
factory = YamlParser(NullSystemIO())
imported = factory.parse_imports(['rkd.standardlib.python.PublishTask'])

self.assertEqual(':py:publish', imported[0].to_full_name())

def test_parse_imports_successful_case_module(self):
factory = YamlParser(NullSystemIO())
imported = factory.parse_imports(['rkd.standardlib.python'])

names_of_imported_tasks = []

for task in imported:
names_of_imported_tasks.append(task.to_full_name())

self.assertIn(':py:publish', names_of_imported_tasks)
self.assertIn(':py:build', names_of_imported_tasks)

def test_parse_imports_wrong_class_type_but_existing(self):
def test():
factory = YamlParser(NullSystemIO())
Expand Down Expand Up @@ -59,6 +71,7 @@ def test_parse_tasks_successful_case(self):
msg='Expected that the task name will be present')

declaration = parsed_tasks[0]
declaration.get_task_to_execute()._io = NullSystemIO()
declaration.get_task_to_execute().execute(ExecutionContext(declaration))

with open('/tmp/.test_parse_tasks', 'r') as test_helper:
Expand Down Expand Up @@ -88,6 +101,7 @@ def test_parse_tasks_signals_error_instead_of_throwing_exception(self):
parsed_tasks = factory.parse_tasks(input_tasks, '')

declaration = parsed_tasks[0]
declaration.get_task_to_execute()._io = IO()
task = declaration.get_task_to_execute()
task._io = io

Expand Down

0 comments on commit 502df86

Please sign in to comment.