dyngle 0.4.0__tar.gz → 0.4.2__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.

Potentially problematic release.


This version of dyngle might be problematic. Click here for more details.

@@ -37,30 +37,45 @@ Dyngle reads configuration from YAML files. You can specify the config file loca
37
37
  - `.dyngle.yml` in current directory
38
38
  - `~/.dyngle.yml` in home directory
39
39
 
40
- ## Workflow structure
40
+ The configuration has 2 parts: `operations:` and `expressions`.
41
41
 
42
- Each operation is defined as a list of tasks under `dyngle.operations`. Tasks are executed sequentially using Python's subprocess module for security.
42
+ ## Data
43
43
 
44
- Example with multiple operations:
44
+ Dyngle maintains a block of data throughout operations, which is parsed from YAML in stdin.
45
+
46
+ ## Operations
47
+
48
+ Operations contain steps as a YAML array. The lifecycle of an operation is:
49
+
50
+ 1. Load input data if it exists from YAML on stdin (if no tty)
51
+ 2. Perform template rendering on a step, using data and expressions (see below)
52
+ 3. Execute the step in a subprocess
53
+ 4. Continue with the next step
54
+
55
+ Note that operations in the config are _not_ full shell lines. They are passed directly to the system.
56
+
57
+ ## Templates
58
+
59
+ Prior to running commands, the line containing that command is processed as a template. Entries from the data set can be substituted into the command line using Jinja-like expressions in double-curly brackets (`{{` and `}}`).
60
+
61
+ For example, if stdin contains the following data:
45
62
 
46
63
  ```yaml
47
- dyngle:
48
- operations:
49
- test:
50
- - python -m unittest discover
51
- - python -m coverage report
52
- docs:
53
- - sphinx-build docs docs/_build
54
- - open docs/_build/index.html
55
- setup:
56
- - python -m venv venv
57
- - source venv/bin/activate
58
- - pip install -r requirements.txt
64
+ name: Francis
65
+ ```
66
+
67
+ And the command looks like:
68
+
69
+ ``` yaml
70
+ - echo "Hello {{name}}!"
59
71
  ```
60
72
 
73
+ Then the command will output "Hello Francis!".
74
+
75
+
61
76
  ## Expressions
62
77
 
63
- Configs can also contain expressions.
78
+ Configs can also contain expressions, written in Python, that can also be referenced in operation steps.
64
79
 
65
80
  ```yaml
66
81
  dyngle:
@@ -70,6 +85,7 @@ dyngle:
70
85
  operations:
71
86
  say-hello: echo {{say-hello}}
72
87
  ```
88
+
73
89
  Expressions can use a controlled subset of the Python standard library, including:
74
90
 
75
91
  - Built-in data types such as `str()`
@@ -77,10 +93,11 @@ Expressions can use a controlled subset of the Python standard library, includin
77
93
  - The core modules from the `datetime` package (but some methods such as `strftime()` will fail)
78
94
  - A specialized function called `formatted()` to perform string formatting operations on a `datetime` object
79
95
  - A restricted version of `Path()` that only operates within the current working directory
96
+ - Various other useful utilities, mostly read-only, such as the `math` module
80
97
 
81
98
  ## Security
82
99
 
83
- Commands are executed using Python's `subprocess.run()` with arguments split in a shell-like fashion. The shell is not used, which reduces the likelihood of shell injection attacks. However, note that Dyngle is not robust to malicious configuration.
100
+ Commands are executed using Python's `subprocess.run()` with arguments split in a shell-like fashion. The shell is not used, which reduces the likelihood of shell injection attacks. However, note that Dyngle is not robust to malicious configuration. Use with caution.
84
101
 
85
102
  ## Quick installation (MacOS)
86
103
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dyngle
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Run lightweight local workflows
5
5
  License: MIT
6
6
  Author: Steampunk Wizard
@@ -52,30 +52,45 @@ Dyngle reads configuration from YAML files. You can specify the config file loca
52
52
  - `.dyngle.yml` in current directory
53
53
  - `~/.dyngle.yml` in home directory
54
54
 
55
- ## Workflow structure
55
+ The configuration has 2 parts: `operations:` and `expressions`.
56
56
 
57
- Each operation is defined as a list of tasks under `dyngle.operations`. Tasks are executed sequentially using Python's subprocess module for security.
57
+ ## Data
58
58
 
59
- Example with multiple operations:
59
+ Dyngle maintains a block of data throughout operations, which is parsed from YAML in stdin.
60
+
61
+ ## Operations
62
+
63
+ Operations contain steps as a YAML array. The lifecycle of an operation is:
64
+
65
+ 1. Load input data if it exists from YAML on stdin (if no tty)
66
+ 2. Perform template rendering on a step, using data and expressions (see below)
67
+ 3. Execute the step in a subprocess
68
+ 4. Continue with the next step
69
+
70
+ Note that operations in the config are _not_ full shell lines. They are passed directly to the system.
71
+
72
+ ## Templates
73
+
74
+ Prior to running commands, the line containing that command is processed as a template. Entries from the data set can be substituted into the command line using Jinja-like expressions in double-curly brackets (`{{` and `}}`).
75
+
76
+ For example, if stdin contains the following data:
60
77
 
61
78
  ```yaml
62
- dyngle:
63
- operations:
64
- test:
65
- - python -m unittest discover
66
- - python -m coverage report
67
- docs:
68
- - sphinx-build docs docs/_build
69
- - open docs/_build/index.html
70
- setup:
71
- - python -m venv venv
72
- - source venv/bin/activate
73
- - pip install -r requirements.txt
79
+ name: Francis
80
+ ```
81
+
82
+ And the command looks like:
83
+
84
+ ``` yaml
85
+ - echo "Hello {{name}}!"
74
86
  ```
75
87
 
88
+ Then the command will output "Hello Francis!".
89
+
90
+
76
91
  ## Expressions
77
92
 
78
- Configs can also contain expressions.
93
+ Configs can also contain expressions, written in Python, that can also be referenced in operation steps.
79
94
 
80
95
  ```yaml
81
96
  dyngle:
@@ -85,6 +100,7 @@ dyngle:
85
100
  operations:
86
101
  say-hello: echo {{say-hello}}
87
102
  ```
103
+
88
104
  Expressions can use a controlled subset of the Python standard library, including:
89
105
 
90
106
  - Built-in data types such as `str()`
@@ -92,10 +108,11 @@ Expressions can use a controlled subset of the Python standard library, includin
92
108
  - The core modules from the `datetime` package (but some methods such as `strftime()` will fail)
93
109
  - A specialized function called `formatted()` to perform string formatting operations on a `datetime` object
94
110
  - A restricted version of `Path()` that only operates within the current working directory
111
+ - Various other useful utilities, mostly read-only, such as the `math` module
95
112
 
96
113
  ## Security
97
114
 
98
- Commands are executed using Python's `subprocess.run()` with arguments split in a shell-like fashion. The shell is not used, which reduces the likelihood of shell injection attacks. However, note that Dyngle is not robust to malicious configuration.
115
+ Commands are executed using Python's `subprocess.run()` with arguments split in a shell-like fashion. The shell is not used, which reduces the likelihood of shell injection attacks. However, note that Dyngle is not robust to malicious configuration. Use with caution.
99
116
 
100
117
  ## Quick installation (MacOS)
101
118
 
@@ -11,15 +11,17 @@ class Template:
11
11
 
12
12
  template: str
13
13
 
14
- def render(self, data: dict, expressions: dict = None) -> str:
14
+ def render(self, data: dict = None, expressions: dict = None) -> str:
15
15
  """Render the template with the provided data."""
16
+ data = data if data else {}
17
+ expressions = expressions if expressions else {}
16
18
  resolver = partial(self._resolve, data=data, expressions=expressions)
17
19
  return PATTERN.sub(resolver, self.template)
18
20
 
19
21
  def _resolve(self, match, *, data: dict, expressions: dict):
20
22
  """Resolve a single name/path from the template."""
21
23
  key = match.group(1).strip()
22
- if expressions and (key in expressions):
24
+ if key in expressions:
23
25
  return expressions[key](data)
24
26
  else:
25
27
  parts = key.split('.')
@@ -8,7 +8,7 @@ description = "Run lightweight local workflows"
8
8
  authors = ["Steampunk Wizard <dyngle@steamwiz.io>"]
9
9
  license = "MIT"
10
10
  readme = "PACKAGE.md"
11
- version = "0.4.0"
11
+ version = "0.4.2"
12
12
 
13
13
  [tool.poetry.dependencies]
14
14
  python = "~3.11"
File without changes
File without changes
File without changes
File without changes
File without changes