Skip to content

Commit

Permalink
feat: Improve the configuration for the shell app. (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
xmnlab authored Apr 3, 2024
1 parent 152cc24 commit 1647914
Show file tree
Hide file tree
Showing 13 changed files with 1,385 additions and 617 deletions.
19 changes: 19 additions & 0 deletions .makim.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,25 @@ groups:
docs:
targets:
pre-build:
help: pre-build step
shell: bash
run: |
mkdir -p build
# Directory to search for .ipynb files
export SEARCH_DIR="docs/tutorials"
# Find all .ipynb files, excluding .ipynb_checkpoints,
# and convert them to Markdown named 'index.md'
find "$SEARCH_DIR" -path "*/.ipynb_checkpoints/*" -prune -o -name \
"*.ipynb" -exec sh -c \
'jupyter nbconvert --to markdown --output-dir "$(dirname "$0")" "$0"' {} \;
# remove console colors from md files
find "$SEARCH_DIR" -name \
"*.md" -exec sh -c \
'cat "$0" | python docs/scripts/clean-output.py > "$(dirname "$0")/temp_index.md" && mv "$(dirname "$0")/temp_index.md" "$0"' {} \;
build:
help: Build documentation
run: |
Expand Down
1,822 changes: 1,243 additions & 579 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ ruff = ">=0.1.5"
bandit = ">=1.7.5"
vulture = ">=2.7"
compose-go = ">=2.20.2"
jupyterlab = ">=4.1.5"
nox = ">=2024.3.2"
nbconvert = ">=7.16.3"
pymdown-extensions = ">=10.7.1"

[build-system]
requires = ["poetry-core>=1.0.0", "poetry>=1.5.1"]
Expand Down
1 change: 0 additions & 1 deletion src/makim/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Top-level package for makim."""


__author__ = 'Ivan Ogasawara'
__email__ = 'ivan.ogasawara@gmail.com'
__version__ = '1.14.0' # semantic-release
Expand Down
1 change: 1 addition & 0 deletions src/makim/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Makim app to be called from `python -m`."""

from makim.cli import run_app

if __name__ == '__main__':
Expand Down
1 change: 1 addition & 0 deletions src/makim/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Cli functions to define the arguments and to call Makim."""

from __future__ import annotations

import os
Expand Down
1 change: 1 addition & 0 deletions src/makim/console.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Functions about console."""

import os


Expand Down
110 changes: 85 additions & 25 deletions src/makim/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
the way to define targets and dependencies. Instead of using the
`Makefile` format, it uses `yaml` format.
"""

from __future__ import annotations

import copy
Expand All @@ -17,17 +18,20 @@

from copy import deepcopy
from pathlib import Path
from typing import Any, Optional, Union
from typing import Any, Dict, List, Optional, Union, cast

import dotenv
import sh
import yaml # type: ignore

from jinja2 import Environment
from typing_extensions import TypeAlias

from makim.console import get_terminal_size
from makim.logs import MakimError, MakimLogs

AppConfigType: TypeAlias = Dict[str, Union[str, List[str]]]

SCOPE_GLOBAL = 0
SCOPE_GROUP = 1
SCOPE_TARGET = 2
Expand All @@ -36,6 +40,12 @@
KNOWN_SHELL_APP_ARGS = {
'bash': ['-e'],
'php': ['-f'],
'nox': ['-f'],
}

# useful when the program just read specific file extension
KNOWN_SHELL_APP_FILE_SUFFIX = {
'nox': '.makim.py',
}

TEMPLATE = Environment(
Expand Down Expand Up @@ -88,6 +98,7 @@ class Makim:
global_data: dict = {}
shell_app: sh.Command = sh.xonsh
shell_args: list[str] = []
tmp_suffix: str = '.makim'

# temporary variables
env: dict = {} # initial env
Expand All @@ -111,10 +122,14 @@ def __init__(self):
self.file = '.makim.yaml'
self.dry_run = False
self.verbose = False
self.shell_app = sh.xonsh
self.shell_args: list[str] = []
self.tmp_suffix: str = '.makim'

def _call_shell_app(self, cmd):
fd, filepath = tempfile.mkstemp(suffix='.makim', text=True)
self._load_shell_app()

fd, filepath = tempfile.mkstemp(suffix=self.tmp_suffix, text=True)

with open(filepath, 'w') as f:
f.write(cmd)
Expand Down Expand Up @@ -185,9 +200,6 @@ def _change_target(self, target_name: str) -> None:
for target_name, target_data in self.group_data['targets'].items():
if target_name == self.target_name:
self.target_data = target_data
shell_app = target_data.get('shell')
if shell_app:
self._load_shell_app(shell_app)
return

MakimLogs.raise_error(
Expand All @@ -201,20 +213,10 @@ def _change_group_data(self, group_name=None) -> None:

if group_name is not None:
self.group_name = group_name
shell_app_default = self.global_data.get('shell', 'xonsh')
if self.group_name == 'default' and len(groups) == 1:
group = next(iter(groups))
self.group_data = groups[group]

shell_app = self.group_data.get('shell', shell_app_default)
self._load_shell_app(shell_app)
return

for group in groups:
if group == self.group_name:
self.group_data = groups[group]
shell_app = groups[group].get('shell', shell_app_default)
self._load_shell_app(shell_app)
return

MakimLogs.raise_error(
Expand Down Expand Up @@ -269,17 +271,76 @@ def update_working_directory(

return working_dir

def _load_shell_app(self, shell_app: str = '') -> None:
if not shell_app:
shell_app = self.global_data.get('shell', 'xonsh')
return
def _extract_shell_app_config(
self, scoped_config: dict[str, Any]
) -> AppConfigType:
"""Extract the shell app configuration from the scoped config data."""
shell_app_data: AppConfigType = scoped_config.get('shell', {})

cmd = shell_app.split(' ')
cmd_name = cmd[0]
self.shell_app = getattr(sh, cmd_name)
if not shell_app_data:
return {}

shell_app_default = 'xonsh'
tmp_suffix_default = '.makim'

shell_config: AppConfigType = {}

args: list[str] = KNOWN_SHELL_APP_ARGS.get(cmd_name, [])
self.shell_args = args + cmd[1:]
if isinstance(shell_app_data, str):
cmd = shell_app_data.split(' ')
app_name = cmd[0]
args: list[str] = KNOWN_SHELL_APP_ARGS.get(app_name, [])
shell_config['app'] = cmd[0]
shell_config['suffix'] = KNOWN_SHELL_APP_FILE_SUFFIX.get(
app_name, tmp_suffix_default
)
shell_config['args'] = args + cmd[1:]
elif isinstance(shell_app_data, dict):
app_name = str(shell_app_data.get('app', shell_app_default))
shell_config['app'] = app_name
shell_tmp_suffix_default = KNOWN_SHELL_APP_FILE_SUFFIX.get(
app_name, tmp_suffix_default
)
shell_config['suffix'] = shell_app_data.get(
'suffix', shell_tmp_suffix_default
)
shell_config['args'] = shell_app_data.get('args', [])
return shell_config

def _load_shell_app(self) -> None:
"""Load the shell app."""
shell_config: AppConfigType = {
'app': 'xonsh',
'args': [],
'suffix': '.makim',
}
tmp_suffix_default = '.makim'

for scoped_data in [
self.global_data,
self.group_data,
self.target_data,
]:
tmp_config: AppConfigType = self._extract_shell_app_config(
scoped_data
)
if tmp_config:
shell_config = tmp_config

cmd_name = str(shell_config.get('app', ''))
cmd_args: list[str] = cast(List[str], shell_config.get('args', []))
cmd_tmp_suffix: str = str(
shell_config.get('suffix', tmp_suffix_default)
)

if not cmd_name:
MakimLogs.raise_error(
'The shell command is invalid',
MakimError.MAKIM_CONFIG_FILE_INVALID,
)

self.shell_app = getattr(sh, cmd_name)
self.shell_args = cmd_args
self.tmp_suffix = cmd_tmp_suffix

def _load_dotenv(self, data_scope: dict) -> dict[str, str]:
env_file = data_scope.get('env-file')
Expand Down Expand Up @@ -537,7 +598,6 @@ def load(self, file: str, dry_run: bool = False, verbose: bool = False):

self._load_config_data()
self._verify_config()
self._load_shell_app()
self.env = self._load_dotenv(self.global_data)

def run(self, args: dict):
Expand Down
2 changes: 2 additions & 0 deletions src/makim/logs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Classes and function for handling logs."""

import os

from enum import Enum
Expand All @@ -18,6 +19,7 @@ class MakimError(Enum):
MAKIM_VARS_ATTRIBUTE_INVALID = 7
MAKIM_ARGUMENT_REQUIRED = 8
MAKIM_ENV_FILE_NOT_FOUND = 9
MAKIM_CONFIG_FILE_INVALID = 10


class MakimLogs:
Expand Down
27 changes: 21 additions & 6 deletions tests/smoke/.makim-interpreters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ groups:
help: Test using nodejs
shell: node
run: console.log("Hello, World!");

nox:
help: Test using nox
shell:
app: nox
args: ["--noxfile"]
suffix: .nox.py

run: |
import nox
@nox.session
def test(session):
print("Hello, World!")
perl:
help: Test using perl
shell: perl
Expand Down Expand Up @@ -34,10 +49,10 @@ groups:

all:
dependencies:
- target: node
- target: perl
- target: main.node
- target: main.perl
# note: php from conda-forge has conflicts with r-base
# - target: php
- target: python
- target: r
- target: sh
# - target: main.php
- target: main.python
- target: main.r
- target: main.sh
12 changes: 6 additions & 6 deletions tests/smoke/.makim-unittest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ groups:
test-3-b:
help: test-3-b
dependencies:
- target: test-3-a
- target: tests.test-3-a
run: assert True

test-4-dep:
Expand All @@ -48,7 +48,7 @@ groups:
type: bool
action: store_true
dependencies:
- target: test-4-dep
- target: tests.test-4-dep
if: ${{ args.trigger_dep }}
args:
arg1: ${{ args.trigger_dep }}
Expand All @@ -66,7 +66,7 @@ groups:
type: bool
action: store_true
dependencies:
- target: test-5-dep
- target: tests.test-5-dep
if: ${{ args.trigger_dep }}
run: assert True

Expand All @@ -90,11 +90,11 @@ groups:
type: bool
action: store_true
dependencies:
- target: test-6-dep-1
- target: tests.test-6-dep-1
if: ${{ True }}
- target: test-6-dep-2
- target: tests.test-6-dep-2
if: ${{ False }}
- target: test-6-dep-3
- target: tests.test-6-dep-3
if: ${{ True }}
run: |
cat /tmp/makim-test.txt | grep "OK"
Expand Down
1 change: 1 addition & 0 deletions tests/test_failure.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Tests for `makim` package."""

import os
import sys

Expand Down
1 change: 1 addition & 0 deletions tests/test_success.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Tests for `makim` package."""

from pathlib import Path

import makim
Expand Down

0 comments on commit 1647914

Please sign in to comment.