dyngle 1.0.1__py3-none-any.whl → 1.2.0__py3-none-any.whl

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.

dyngle/__init__.py CHANGED
@@ -9,6 +9,7 @@ from dyngle.command import DyngleCommand
9
9
  from dyngle.error import DyngleError
10
10
  from dyngle.model.expression import expression
11
11
  from dyngle.model.operation import Operation
12
+ from dyngle.model.template import Template
12
13
 
13
14
 
14
15
  class DyngleApp(WizApp):
@@ -53,19 +54,22 @@ class DyngleApp(WizApp):
53
54
  if isinstance(config, list):
54
55
  operation = Operation({}, config)
55
56
  elif isinstance(config, dict):
56
- local_expr_texts = config.get('expressions') or {}
57
- local_expressions = _expressions_from_texts(local_expr_texts)
57
+ expr_texts = config.get('expressions') or {}
58
+ expressions = _expressions_from_texts(expr_texts)
59
+ values = config.get('values') or {}
58
60
  steps = config.get('steps') or []
59
- operation = Operation(local_expressions, steps)
61
+ operation = Operation(expressions | values, steps)
60
62
  else:
61
63
  raise DyngleError(f"Invalid operation configuration for {key}")
62
64
  operations[key] = operation
63
65
  return operations
64
66
 
65
67
  @cached_property
66
- def global_expressions(self):
68
+ def globals(self):
67
69
  expr_texts = self._get_configuration_details('expressions')
68
- return _expressions_from_texts(expr_texts)
70
+ expressions = _expressions_from_texts(expr_texts)
71
+ values = self._get_configuration_details('values')
72
+ return expressions | (values if values else {})
69
73
 
70
74
 
71
75
  def _expressions_from_texts(expr_texts):
@@ -42,6 +42,6 @@ class RunCommand(DyngleCommand):
42
42
  self._validate_operation_exists(operations)
43
43
  operation = operations[self.operation]
44
44
 
45
- operation.run(data, self.app.global_expressions)
45
+ operation.run(data, self.app.globals)
46
46
 
47
47
  return f'Operation "{self.operation}" completed successfully'
@@ -54,6 +54,7 @@ GLOBALS = {
54
54
  "enumerate": enumerate,
55
55
  "zip": zip,
56
56
  "range": range,
57
+ "type": type
57
58
  },
58
59
 
59
60
  # Mathematical operations
@@ -107,11 +108,16 @@ def _evaluate(expression: str, locals: dict) -> str:
107
108
  """
108
109
  try:
109
110
  result = eval(expression, GLOBALS, locals)
110
- except KeyError:
111
+ except KeyError as error:
111
112
  raise DyngleError(f"The following expression contains " +
112
- f"at least one invalid name: {expression}")
113
+ f"invalid name '{error}:\n{expression}")
114
+
115
+ # Allow the use of a comma to separate sub-expressions, which can then use
116
+ # warus to set values, and only the last exxpression in the list returns a
117
+ # value.
113
118
  result = result[-1] if isinstance(result, tuple) else result
114
- return str(result)
119
+
120
+ return result
115
121
 
116
122
 
117
123
  # The 'expression' function returns the expression object itself, which is
@@ -137,7 +143,7 @@ def expression(text: str) -> Callable[[dict], str]:
137
143
  # syntax too
138
144
 
139
145
  def resolve(key):
140
- return live_data.resolve(key)
146
+ return live_data.resolve(key, str_only=False)
141
147
  locals = locals | {'resolve': resolve}
142
148
 
143
149
  # Perform the Python eval, expanded above
dyngle/model/live_data.py CHANGED
@@ -1,11 +1,15 @@
1
1
  from collections import UserDict
2
+ from datetime import date, timedelta
3
+ from numbers import Number
4
+
5
+ from yaml import safe_dump
2
6
 
3
7
  from dyngle.error import DyngleError
4
8
 
5
9
 
6
10
  class LiveData(UserDict):
7
11
 
8
- def resolve(self, key: str):
12
+ def resolve(self, key: str, str_only: bool = True):
9
13
  """Given a key (which might be dot-separated), return
10
14
  the value (which might include evaluating expressions)."""
11
15
 
@@ -16,7 +20,18 @@ class LiveData(UserDict):
16
20
  raise DyngleError(
17
21
  f"Invalid expression or data reference '{key}'")
18
22
  current = current[part]
19
- if callable(current):
20
- return current(self)
21
- else:
22
- return current
23
+ result = current(self) if callable(current) else current
24
+ return _stringify(result) if str_only else result
25
+
26
+
27
+ def _stringify(value) -> str:
28
+ if isinstance(value, bool):
29
+ return '.' if value is True else ''
30
+ elif isinstance(value, (Number, str, date, timedelta)):
31
+ return str(value)
32
+ elif isinstance(value, (list, dict, tuple)):
33
+ return safe_dump(value)
34
+ elif isinstance(value, set):
35
+ return safe_dump(list(value))
36
+ else:
37
+ raise DyngleError(f'Unable to serialize value of type {type(value)}')
dyngle/model/operation.py CHANGED
@@ -12,14 +12,13 @@ from dyngle.model.template import Template
12
12
  @dataclass
13
13
  class Operation:
14
14
 
15
- local_expressions: dict
15
+ # Expressions and values defined within the operation
16
+ locals: dict
16
17
 
17
18
  steps: list
18
19
 
19
- def run(self, data: dict, global_expressions: dict):
20
- expressions = global_expressions | self.local_expressions
21
- # Data takes precedence if names match
22
- live_data = LiveData(expressions) | data
20
+ def run(self, data: dict, globals: dict):
21
+ live_data = LiveData(globals) | self.locals | data
23
22
  for markup in self.steps:
24
23
  step = Step(markup)
25
24
  step.run(live_data)
@@ -1,16 +1,15 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: dyngle
3
- Version: 1.0.1
3
+ Version: 1.2.0
4
4
  Summary: Run lightweight local workflows
5
5
  License: MIT
6
6
  Author: Steampunk Wizard
7
7
  Author-email: dyngle@steamwiz.io
8
- Requires-Python: >=3.11,<4.0
8
+ Requires-Python: >=3.13,<4.0
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.11
12
- Classifier: Programming Language :: Python :: 3.12
13
11
  Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
14
13
  Requires-Dist: requests (>=2.32.3,<3.0.0)
15
14
  Requires-Dist: wizlib (>=3.3.8,<3.4.0)
16
15
  Description-Content-Type: text/markdown
@@ -0,0 +1,15 @@
1
+ dyngle/__init__.py,sha256=ZSBChSHOOTW68vZ-2q4ts8VhmEJ5hssG45jhbTTMvk0,2919
2
+ dyngle/__main__.py,sha256=pYRIwzix_AL8CdJaDDis_8yMBBWO2N72NNwkroo1dQo,95
3
+ dyngle/command/__init__.py,sha256=1S86gbef8MYvG-TWD5JRIWzFg7qV5xKhp9QXx9zEx5c,94
4
+ dyngle/command/run_command.py,sha256=gYTQjATRMu_81HLP-hrMz7GNw9Lcz2VjuhP7h_qYLcE,1514
5
+ dyngle/error.py,sha256=CGcTa8L4O1qsHEYnzp_JBbkvntJTv2Qz46wj_TI8NLk,39
6
+ dyngle/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ dyngle/model/expression.py,sha256=9nwfahjOHtScjdDzjwWIleo60lJjtXGrPGfroCbslvg,4431
8
+ dyngle/model/live_data.py,sha256=yWiTgb9w9KaJ2yynGEudfu89Z3hOoHcLdUXfEJRtZG4,1197
9
+ dyngle/model/operation.py,sha256=nSz-8Eh03xAvQlc6Wzn56t-dMArp9uJWY_8XJJZEIwc,1743
10
+ dyngle/model/safe_path.py,sha256=Hk2AhP6e3yKGh3kKrLLwhvAlMNx-j2jObBYJL-_doAU,3339
11
+ dyngle/model/template.py,sha256=MeXu--ZNtj_ujABU1GjjcQ1Ea_o_M-50LocuXFeOLRE,887
12
+ dyngle-1.2.0.dist-info/METADATA,sha256=0jg6HNybNbzJZZRr6-hEUDDMhHJVDNVrLdBZ3m8P7kA,9710
13
+ dyngle-1.2.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
14
+ dyngle-1.2.0.dist-info/entry_points.txt,sha256=rekiGhtweiHKm9g1jdGb3FhzqDrk1kigJDeSNollZSA,48
15
+ dyngle-1.2.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.3
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,15 +0,0 @@
1
- dyngle/__init__.py,sha256=Mku-FaOXp1HMBoQc6K9ZJfhr9n-CXxvtotRFzSZ042I,2728
2
- dyngle/__main__.py,sha256=pYRIwzix_AL8CdJaDDis_8yMBBWO2N72NNwkroo1dQo,95
3
- dyngle/command/__init__.py,sha256=1S86gbef8MYvG-TWD5JRIWzFg7qV5xKhp9QXx9zEx5c,94
4
- dyngle/command/run_command.py,sha256=yq5VJv3XWtzTf9F_rW-_nANFPGGkIMQO3kiU5atEATo,1525
5
- dyngle/error.py,sha256=CGcTa8L4O1qsHEYnzp_JBbkvntJTv2Qz46wj_TI8NLk,39
6
- dyngle/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- dyngle/model/expression.py,sha256=FqYOfotUzTHDyON9cUCwyO5Cw4jTphY_TuWjQyhvSFY,4220
8
- dyngle/model/live_data.py,sha256=6YdCfCDjhzMoCC5Znuwn_T-UpqeU_3I38M1mOBOLh2U,629
9
- dyngle/model/operation.py,sha256=87TOCGr_ECgWaLOAkJs4xwqChZvE3FQiGU4jf33x8LY,1810
10
- dyngle/model/safe_path.py,sha256=Hk2AhP6e3yKGh3kKrLLwhvAlMNx-j2jObBYJL-_doAU,3339
11
- dyngle/model/template.py,sha256=MeXu--ZNtj_ujABU1GjjcQ1Ea_o_M-50LocuXFeOLRE,887
12
- dyngle-1.0.1.dist-info/METADATA,sha256=jyuumkrmM3J37uXUvlVpssOGN1noeeSkcft8_IS4mwQ,9761
13
- dyngle-1.0.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
14
- dyngle-1.0.1.dist-info/entry_points.txt,sha256=rekiGhtweiHKm9g1jdGb3FhzqDrk1kigJDeSNollZSA,48
15
- dyngle-1.0.1.dist-info/RECORD,,