ppqs 2.0.2__tar.gz → 2.1.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ppqs
3
- Version: 2.0.2
3
+ Version: 2.1.0
4
4
  Summary: Python project quick scripts
5
5
  Author-email: Karl Wette <karl.wette@anu.edu.au>
6
6
  License-Expression: MIT
@@ -100,17 +100,30 @@ $ ppqs print-something Hi
100
100
  Hi
101
101
  ```
102
102
 
103
- The following only applies to scripts defined as lists of lists: if a command
104
- argument is itself a list, it is concatenated into a path appropriate for the
105
- current operating system. For example,
103
+ The following only applies to scripts defined as lists of lists:
106
104
 
107
- ```toml
108
- [tool.ppqs.scripts]
109
- do-something = [["do-something-to", ["subdir", "afile"]]]
110
- ```
105
+ * If a command argument is itself a list, it is concatenated into a path
106
+ appropriate for the current operating system. For example,
107
+
108
+ ```toml
109
+ [tool.ppqs.scripts]
110
+ do-something = [["do-something-to", ["subdir", "afile"]]]
111
+ ```
112
+
113
+ would run the command `do-something-to subdir/afile` on a Unix-based operating
114
+ system.
115
+
116
+ If the last element of the path contains a wildcard (`*`), the path is
117
+ expanded at runtime into a list of files/directories matching the wildcard
118
+ expression. For example, if the directory `subdir/` contained the files
119
+ `file1.txt`, `file2.txt`, and `file3.dat`, then:
120
+
121
+ ```toml
122
+ [tool.ppqs.scripts]
123
+ do-something = [["do-something-to", ["subdir", "*.txt"]]]
124
+ ```
111
125
 
112
- would run the command `do-something-to subdir/afile` on a Unix-based operating
113
- system.
126
+ would run the command `do-something-to subdir/file1.txt subdir/file2.txt`
114
127
 
115
128
  Scripts may also be defined in their own section, which permit a few options:
116
129
 
@@ -146,10 +159,9 @@ The default value of some options may be overridden in the
146
159
  print-header = true
147
160
  ```
148
161
 
149
- Note that commands are *not* passed to the shell, so shell features
150
- (e.g. wildcards, conditional statements) are not available. The recommended
151
- solution is to write a helper script, e.g. `scripts/lots-to-do.py`, which may
152
- then be called by `ppqs` as:
162
+ Note that commands are *not* passed to the shell, so shell features are not
163
+ available. The recommended solution is to write a helper script,
164
+ e.g. `scripts/lots-to-do.py`, which may then be called by `ppqs` as:
153
165
 
154
166
  ```toml
155
167
  [tool.ppqs.scripts]
@@ -84,17 +84,30 @@ $ ppqs print-something Hi
84
84
  Hi
85
85
  ```
86
86
 
87
- The following only applies to scripts defined as lists of lists: if a command
88
- argument is itself a list, it is concatenated into a path appropriate for the
89
- current operating system. For example,
87
+ The following only applies to scripts defined as lists of lists:
90
88
 
91
- ```toml
92
- [tool.ppqs.scripts]
93
- do-something = [["do-something-to", ["subdir", "afile"]]]
94
- ```
89
+ * If a command argument is itself a list, it is concatenated into a path
90
+ appropriate for the current operating system. For example,
91
+
92
+ ```toml
93
+ [tool.ppqs.scripts]
94
+ do-something = [["do-something-to", ["subdir", "afile"]]]
95
+ ```
96
+
97
+ would run the command `do-something-to subdir/afile` on a Unix-based operating
98
+ system.
99
+
100
+ If the last element of the path contains a wildcard (`*`), the path is
101
+ expanded at runtime into a list of files/directories matching the wildcard
102
+ expression. For example, if the directory `subdir/` contained the files
103
+ `file1.txt`, `file2.txt`, and `file3.dat`, then:
104
+
105
+ ```toml
106
+ [tool.ppqs.scripts]
107
+ do-something = [["do-something-to", ["subdir", "*.txt"]]]
108
+ ```
95
109
 
96
- would run the command `do-something-to subdir/afile` on a Unix-based operating
97
- system.
110
+ would run the command `do-something-to subdir/file1.txt subdir/file2.txt`
98
111
 
99
112
  Scripts may also be defined in their own section, which permit a few options:
100
113
 
@@ -130,10 +143,9 @@ The default value of some options may be overridden in the
130
143
  print-header = true
131
144
  ```
132
145
 
133
- Note that commands are *not* passed to the shell, so shell features
134
- (e.g. wildcards, conditional statements) are not available. The recommended
135
- solution is to write a helper script, e.g. `scripts/lots-to-do.py`, which may
136
- then be called by `ppqs` as:
146
+ Note that commands are *not* passed to the shell, so shell features are not
147
+ available. The recommended solution is to write a helper script,
148
+ e.g. `scripts/lots-to-do.py`, which may then be called by `ppqs` as:
137
149
 
138
150
  ```toml
139
151
  [tool.ppqs.scripts]
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ppqs"
7
- version = "2.0.2"
7
+ version = "2.1.0"
8
8
  description = "Python project quick scripts"
9
9
  authors = [
10
10
  { name = "Karl Wette", email = "karl.wette@anu.edu.au" },
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ppqs
3
- Version: 2.0.2
3
+ Version: 2.1.0
4
4
  Summary: Python project quick scripts
5
5
  Author-email: Karl Wette <karl.wette@anu.edu.au>
6
6
  License-Expression: MIT
@@ -100,17 +100,30 @@ $ ppqs print-something Hi
100
100
  Hi
101
101
  ```
102
102
 
103
- The following only applies to scripts defined as lists of lists: if a command
104
- argument is itself a list, it is concatenated into a path appropriate for the
105
- current operating system. For example,
103
+ The following only applies to scripts defined as lists of lists:
106
104
 
107
- ```toml
108
- [tool.ppqs.scripts]
109
- do-something = [["do-something-to", ["subdir", "afile"]]]
110
- ```
105
+ * If a command argument is itself a list, it is concatenated into a path
106
+ appropriate for the current operating system. For example,
107
+
108
+ ```toml
109
+ [tool.ppqs.scripts]
110
+ do-something = [["do-something-to", ["subdir", "afile"]]]
111
+ ```
112
+
113
+ would run the command `do-something-to subdir/afile` on a Unix-based operating
114
+ system.
115
+
116
+ If the last element of the path contains a wildcard (`*`), the path is
117
+ expanded at runtime into a list of files/directories matching the wildcard
118
+ expression. For example, if the directory `subdir/` contained the files
119
+ `file1.txt`, `file2.txt`, and `file3.dat`, then:
120
+
121
+ ```toml
122
+ [tool.ppqs.scripts]
123
+ do-something = [["do-something-to", ["subdir", "*.txt"]]]
124
+ ```
111
125
 
112
- would run the command `do-something-to subdir/afile` on a Unix-based operating
113
- system.
126
+ would run the command `do-something-to subdir/file1.txt subdir/file2.txt`
114
127
 
115
128
  Scripts may also be defined in their own section, which permit a few options:
116
129
 
@@ -146,10 +159,9 @@ The default value of some options may be overridden in the
146
159
  print-header = true
147
160
  ```
148
161
 
149
- Note that commands are *not* passed to the shell, so shell features
150
- (e.g. wildcards, conditional statements) are not available. The recommended
151
- solution is to write a helper script, e.g. `scripts/lots-to-do.py`, which may
152
- then be called by `ppqs` as:
162
+ Note that commands are *not* passed to the shell, so shell features are not
163
+ available. The recommended solution is to write a helper script,
164
+ e.g. `scripts/lots-to-do.py`, which may then be called by `ppqs` as:
153
165
 
154
166
  ```toml
155
167
  [tool.ppqs.scripts]
@@ -1,3 +1,4 @@
1
+ import glob
1
2
  import os
2
3
  import re
3
4
  import shutil
@@ -12,7 +13,7 @@ else: # pragma: no cover
12
13
  import tomli as tomllib
13
14
 
14
15
  __author__ = "Karl Wette"
15
- __version__ = "2.0.2"
16
+ __version__ = "2.1.0"
16
17
 
17
18
 
18
19
  class MissingPyProjectError(Exception):
@@ -151,11 +152,14 @@ def parse_scripts(pyproject_path):
151
152
 
152
153
  # List arguments are treated as paths
153
154
  arg_path = Path(*arg)
155
+ if any("*" in a for a in arg[:-1]):
156
+ msg2 = f"path argument '{arg_path}' may contain wildcards only in the last element"
157
+ raise InvalidScriptError(pyproject_path, msg2)
154
158
  if arg_path.is_absolute():
155
159
  msg2 = f"path argument '{arg_path}' must be a relative path"
156
160
  raise InvalidScriptError(pyproject_path, msg2)
157
161
 
158
- script_line.append(str(arg_path))
162
+ script_line.append(arg_path)
159
163
 
160
164
  else:
161
165
  script_line.append(arg)
@@ -211,7 +215,16 @@ def run_script(script_name, script, argv, cwd):
211
215
  cmd = []
212
216
 
213
217
  for arg in command:
214
- if arg == "...":
218
+ if isinstance(arg, Path):
219
+ if "*" in arg.parts[-1]:
220
+
221
+ # Expand wildcards in last path element
222
+ cmd.extend(sorted(glob.glob(str(arg), recursive=False)))
223
+
224
+ else:
225
+ cmd.append(str(arg))
226
+
227
+ elif arg == "...":
215
228
 
216
229
  # Replace "..." in command with arguments
217
230
  cmd.extend(argv)
@@ -222,7 +235,8 @@ def run_script(script_name, script, argv, cwd):
222
235
  # Print header
223
236
  if script["print-header"]:
224
237
  cmd_str = " ".join(cmd)
225
- print(f" ppqs {script_name}: {cmd_str} ".center(col_width, "*"), flush=True)
238
+ header = f"*** ppqs {script_name}: {cmd_str} ***".center(col_width, "*")
239
+ print(header, flush=True)
226
240
 
227
241
  # Run command
228
242
  retn = subprocess.run(cmd, stdin=subprocess.DEVNULL, shell=False, cwd=cwd)
@@ -1,3 +1,5 @@
1
+ import os
2
+
1
3
  import pytest
2
4
 
3
5
  from py_proj_quick_scripts import InvalidScriptError, cli
@@ -24,6 +26,14 @@ def pyproject_path(tmp_path):
24
26
  script = [
25
27
  ["python", "-c", "import sys; print(*sys.argv[1:])", "..."],
26
28
  ]
29
+ [tool.ppqs.scripts.echo-path]
30
+ script = [
31
+ ["python", "-c", "import sys; print(*sys.argv[1:])", ["afile"], ["subdir", "bfile"]],
32
+ ]
33
+ [tool.ppqs.scripts.echo-wildcard]
34
+ script = [
35
+ ["python", "-c", "import sys; print(*sys.argv[1:])", ["subdir", "*.txt"]],
36
+ ]
27
37
  """
28
38
 
29
39
  write_file(pyproject_path, pyproject_toml)
@@ -53,7 +63,7 @@ def test_notest(pyproject_path):
53
63
 
54
64
  def test_exit(pyproject_path):
55
65
  """
56
- Test exit() script.
66
+ Test `exit` script.
57
67
  """
58
68
 
59
69
  with in_dir(pyproject_path.parent):
@@ -63,7 +73,7 @@ def test_exit(pyproject_path):
63
73
 
64
74
  def test_echo(pyproject_path, capfd):
65
75
  """
66
- Test echo() script.
76
+ Test `echo` script.
67
77
  """
68
78
 
69
79
  with in_dir(pyproject_path.parent):
@@ -71,3 +81,31 @@ def test_echo(pyproject_path, capfd):
71
81
  captured = capfd.readouterr()
72
82
  assert captured.out == "Hello\n"
73
83
  assert captured.err == ""
84
+
85
+
86
+ def test_echo_path(pyproject_path, capfd):
87
+ """
88
+ Test `echo-path` script.
89
+ """
90
+
91
+ with in_dir(pyproject_path.parent):
92
+ cli("echo-path")
93
+ captured = capfd.readouterr()
94
+ assert captured.out == "afile subdir/bfile\n".replace("/", os.sep)
95
+ assert captured.err == ""
96
+
97
+
98
+ def test_echo_wildcard(pyproject_path, capfd):
99
+ """
100
+ Test `echo-wildcard` script.
101
+ """
102
+
103
+ with in_dir(pyproject_path.parent) as wd:
104
+ subdir = wd / "subdir"
105
+ subdir.mkdir()
106
+ write_file(subdir / "a.txt", "Some text")
107
+ write_file(subdir / "b.txt", "Some more text")
108
+ cli("echo-wildcard")
109
+ captured = capfd.readouterr()
110
+ assert captured.out == "subdir/a.txt subdir/b.txt\n".replace("/", os.sep)
111
+ assert captured.err == ""
@@ -219,12 +219,43 @@ from . import in_dir, write_file
219
219
  "paths": {
220
220
  "description": "Run paths script",
221
221
  "print-header": False,
222
- "commands": [["echo", str(Path("a", "b"))]],
222
+ "commands": [["echo", Path("a", "b")]],
223
223
  }
224
224
  }
225
225
  ),
226
226
  id="list script with relative path",
227
227
  ),
228
+ pytest.param(
229
+ """
230
+ [tool.ppqs.scripts]
231
+ paths = [
232
+ ["echo", ["*", "b"]],
233
+ ]
234
+ """,
235
+ pytest.raises(
236
+ InvalidScriptError,
237
+ match="may contain wildcards only in the last element",
238
+ ),
239
+ id="list script with path and invalid wildcard",
240
+ ),
241
+ pytest.param(
242
+ """
243
+ [tool.ppqs.scripts]
244
+ paths = [
245
+ ["echo", ["a", "*.txt"]],
246
+ ]
247
+ """,
248
+ nullcontext(
249
+ {
250
+ "paths": {
251
+ "description": "Run paths script",
252
+ "print-header": False,
253
+ "commands": [["echo", Path("a", "*.txt")]],
254
+ }
255
+ }
256
+ ),
257
+ id="list script with path and valid wildcard",
258
+ ),
228
259
  ],
229
260
  )
230
261
  def test_parse_scripts(tmp_path, script_toml, expectation):
File without changes
File without changes
File without changes
File without changes