Skip to content

Commit

Permalink
fix: Fix IF statement and arguments used by dependencies (osl-incubat…
Browse files Browse the repository at this point in the history
…or#24)

* fix: Fix IF statement and arguments used by dependencies

* Add unittests
  • Loading branch information
xmnlab authored Mar 8, 2023
1 parent ccdfd44 commit e03886e
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .makim.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ groups:

unittest:
help: Run tests
run: pytest
run: pytest -s -vv tests

makim-file-simple:
help: Test makim using a simple makimfile
Expand Down
1 change: 1 addition & 0 deletions makim/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ def app():

makim.load(args.makim_file)
makim_args.update(dict(args._get_kwargs()))

return makim.run(makim_args)


Expand Down
84 changes: 49 additions & 35 deletions makim/makim.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,25 @@


def escape_template_tag(v: str) -> str:
return v.replace('{{', '\{\{').replace('}}', '\}\}') # noqa: W605
return v.replace('{{', r'\{\{').replace('}}', r'\}\}')


def unescape_template_tag(v: str) -> str:
return v.replace('\{\{', '{{').replace('\}\}', '}}') # noqa: W605
return v.replace(r'\{\{', '{{').replace(r'\}\}', '}}')


class Makim:
class PrintPlugin:
def _print_error(self, message: str):
print(Fore.RED, message, Fore.RESET)

def _print_info(self, message: str):
print(Fore.BLUE, message, Fore.RESET)

def _print_warning(self, message: str):
print(Fore.YELLOW, message, Fore.RESET)


class Makim(PrintPlugin):
makim_file: str = '.makim.yaml'
config_data: dict = {}
shell_app: sh.Command = sh.xonsh
Expand Down Expand Up @@ -54,12 +65,12 @@ def _call_shell_app(self, *args):
p.wait()
except sh.ErrorReturnCode as e:
self._print_error(str(e))
exit(1)
os._exit(1)
except KeyboardInterrupt:
pid = p.pid
p.kill()
self._print_error(f'[EE] Process {pid} killed.')
exit(1)
os._exit(1)

def _check_makim_file(self):
return Path(self.makim_file).exists()
Expand All @@ -72,12 +83,12 @@ def _verify_args(self):
self._print_error(
'[EE] CONFIG: Config file .makim.yaml not found.'
)
exit(1)
os._exit(1)

def _verify_config(self):
if not len(self.config_data['groups']):
self._print_error('[EE] No target groups found.')
exit(1)
os._exit(1)

def _load_config_data(self):
with open(self.makim_file, 'r') as f:
Expand Down Expand Up @@ -111,7 +122,7 @@ def _change_target(self, target_name: str):
f'[EE] The given target "{self.target_name}" was not found in the '
f'configuration file for the group {self.group_name}.'
)
exit(1)
os._exit(1)

def _change_group_data(self, group_name=None):
groups = self.config_data['groups']
Expand Down Expand Up @@ -140,24 +151,21 @@ def _change_group_data(self, group_name=None):
f'[EE] The given group target "{self.group_name}" '
'was not found in the configuration file.'
)
exit(1)
os._exit(1)

def _load_shell_args(self):
self.shell_args = ['-c']

# run commands

def _run_dependencies(self, args: dict):
if (
'dependencies' not in self.target_data
or not self.target_data['dependencies']
):
if not self.target_data.get('dependencies'):
return

makim_dep = deepcopy(self)
args_dep_original = {
'makim_file': args['makim_file'],
'help': args['help'],
'help': args.get('help', False),
'verbose': args.get('verbose', False),
'dry-run': args.get('dry-run', False),
'version': args.get('version', False),
Expand Down Expand Up @@ -188,8 +196,8 @@ def _run_dependencies(self, args: dict):
else str(arg_value)
)

args_dep[f'--{arg_name}'] = Template(unescaped_value).render(
args=original_args_clean
args_dep[f'--{arg_name}'] = yaml.safe_load(
Template(unescaped_value).render(args=original_args_clean)
)

args_dep['target'] = dep_data['target']
Expand All @@ -198,8 +206,10 @@ def _run_dependencies(self, args: dict):
# checking for the conditional statement
if_stmt = dep_data.get('if')
if if_stmt:
result = Template(if_stmt).render(args=args_dep)
if not result and args.get('verbose'):
result = Template(unescape_template_tag(if_stmt)).render(
args=original_args_clean
)
if not yaml.safe_load(result) and args.get('verbose'):
return print(
f'[II] Skipping dependency: {dep_data.get("target")}'
)
Expand All @@ -217,23 +227,25 @@ def _run_command(self, args: dict):
'[EE] `vars` attribute inside the group '
f'{self.group_name} is not a dictionary.'
)
exit(1)
os._exit(1)

variables = {k: v.strip() for k, v in self.group_data['vars'].items()}

args_input = {'makim_file': args['makim_file']}
for k, v in self.target_data.get('args', {}).items():
k_clean = k.replace('-', '_')
action = v.get('action', '').replace('-', '_')
is_store_true = action == 'store_true'
default = v.get('default', False if is_store_true else None)

args_input[k_clean] = v.get(
'default', False if action == 'store_true' else None
)
args_input[k_clean] = default

input_flag = f'--{k}'
if input_flag in args:
if action == 'store_true':
args_input[k_clean] = True
args_input[k_clean] = (
True if args[input_flag] is None else args[input_flag]
)
continue

args_input[k_clean] = (
Expand All @@ -246,7 +258,7 @@ def _run_command(self, args: dict):
f'[EE] The argument `{k}` is set as required. '
'Please, provide that argument to proceed.'
)
exit(1)
os._exit(1)

current_env = deepcopy(os.environ)
env = deepcopy(self.env)
Expand Down Expand Up @@ -291,19 +303,20 @@ def _load_dotenv(self):

if not Path(env_file).exists():
self._print_error('[EE] The given env-file was not found.')
exit(1)
os._exit(1)

self.env = dotenv.dotenv_values(env_file)

# print messages
def _print_error(self, message: str):
print(Fore.RED, message, Fore.RESET)

def _print_info(self, message: str):
print(Fore.BLUE, message, Fore.RESET)

def _print_warning(self, message: str):
print(Fore.YELLOW, message, Fore.RESET)
def _load_target_args(self):
for name, value in self.target_data.get('args', {}).items():
qualified_name = f'--{name}'
if self.args.get(qualified_name):
continue
default = value.get('default')
is_bool = value.get('type', '') == 'bool'
self.args[qualified_name] = (
default if default is not None else False if is_bool else None
)

# public methods

Expand All @@ -321,9 +334,10 @@ def run(self, args: dict):
self._verify_args()
self._change_target(args['target'])
self._load_shell_args()
self._load_target_args()

# commands
if 'if' in self.target_data and not self._verify_target_conditional(
if self.target_data.get('if') and not self._verify_target_conditional(
self.target_data['if']
):
return warnings.warn(
Expand Down
55 changes: 55 additions & 0 deletions tests/.makim-unittest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
version: 1.0.0
env-file: .env
groups:
- name: tests
targets:
test-1:
help: test-1 args `all` should be false
args:
all:
type: bool
action: store_true
help: arg `all`
run: |
assert not {{ args.all }}
test-2:
help: test-2 args `all` should be true
args:
all:
type: bool
action: store_true
help: arg `all`
run: |
assert {{ args.all }}
test-3-a:
help: test-3-a is a dep for test-3-b
run: "true"

test-3-b:
help: test-3-b
dependencies:
- target: test-3-a
run: "true"

test-4-dep:
help: test-4-dep is a dep for test-4
args:
arg1:
help: arg1
type: bool
action: store_true
run: |
assert {{ args.arg1 }}
test-4:
help: test-4
args:
trigger-dep:
type: bool
action: store_true
dependencies:
- target: test-3-a
if: {{ args.trigger_dep }}
run: "true"
29 changes: 21 additions & 8 deletions tests/test_makim.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
"""Tests for `makim` package."""
from pathlib import Path

import pytest

import makim # noqa: F401
import makim


@pytest.fixture
def response():
"""Sample pytest fixture.
@pytest.mark.parametrize(
'args',
[
{'target': 'tests.test-1'},
{'target': 'tests.test-1', '--all': False},
{'target': 'tests.test-2', '--all': True},
{'target': 'tests.test-3-a'},
{'target': 'tests.test-3-b'},
{'target': 'tests.test-4'},
{'target': 'tests.test-4', '--trigger-dep': True},
],
)
def test_success(args):
makim_file = Path(__file__).parent / '.makim-unittest.yaml'

See more at: http://doc.pytest.org/en/latest/fixture.html
"""
m = makim.Makim()
m.load(makim_file)

args.update({'makim_file': makim_file})

def test_content(response):
"""Sample pytest test function with the pytest fixture as an argument."""
m.run(args)

0 comments on commit e03886e

Please sign in to comment.