PyProd 0.3.0__tar.gz → 0.4.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. {pyprod-0.3.0 → pyprod-0.4.0}/PKG-INFO +12 -6
  2. {pyprod-0.3.0 → pyprod-0.4.0}/README.rst +11 -5
  3. {pyprod-0.3.0 → pyprod-0.4.0}/docs/commandline.rst +7 -7
  4. {pyprod-0.3.0 → pyprod-0.4.0}/docs/index.rst +32 -2
  5. {pyprod-0.3.0 → pyprod-0.4.0}/docs/prodfile.rst +62 -24
  6. pyprod-0.4.0/docs/releasenotes.rst +15 -0
  7. {pyprod-0.3.0 → pyprod-0.4.0}/pyproject.toml +2 -1
  8. pyprod-0.3.0/sample/build-c/PRODFILE.py → pyprod-0.4.0/samples/build-c/Prodfile.py +6 -3
  9. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/generate-doc/PRODFILE.py +4 -1
  10. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/md-to-pdf/Prodfile.py +6 -0
  11. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/s3files/Prodfile.py +7 -3
  12. {pyprod-0.3.0 → pyprod-0.4.0}/src/pyprod/main.py +19 -7
  13. {pyprod-0.3.0 → pyprod-0.4.0}/src/pyprod/prod.py +168 -104
  14. {pyprod-0.3.0 → pyprod-0.4.0}/src/pyprod/utils.py +2 -2
  15. {pyprod-0.3.0 → pyprod-0.4.0}/src/pyprod/venv.py +3 -3
  16. pyprod-0.4.0/tests/conftest.py +11 -0
  17. pyprod-0.4.0/tests/test_prod.py +350 -0
  18. {pyprod-0.3.0 → pyprod-0.4.0}/tests/test_prodfuncs.py +35 -3
  19. {pyprod-0.3.0 → pyprod-0.4.0}/tests/test_rule.py +23 -41
  20. pyprod-0.4.0/tests/utils.py +13 -0
  21. {pyprod-0.3.0 → pyprod-0.4.0}/uv.lock +15 -1
  22. pyprod-0.3.0/docs/releasenotes.rst +0 -9
  23. pyprod-0.3.0/tests/conftest.py +0 -3
  24. pyprod-0.3.0/tests/test_prod.py +0 -217
  25. {pyprod-0.3.0 → pyprod-0.4.0}/.github/workflows/publish.yml +0 -0
  26. {pyprod-0.3.0 → pyprod-0.4.0}/.github/workflows/test.yml +0 -0
  27. {pyprod-0.3.0 → pyprod-0.4.0}/.gitignore +0 -0
  28. {pyprod-0.3.0 → pyprod-0.4.0}/.python-version +0 -0
  29. {pyprod-0.3.0 → pyprod-0.4.0}/.readthedocs.yaml +0 -0
  30. {pyprod-0.3.0 → pyprod-0.4.0}/LICENSE +0 -0
  31. {pyprod-0.3.0 → pyprod-0.4.0}/docs/Makefile +0 -0
  32. {pyprod-0.3.0 → pyprod-0.4.0}/docs/conf.py +0 -0
  33. {pyprod-0.3.0 → pyprod-0.4.0}/docs/make.bat +0 -0
  34. {pyprod-0.3.0 → pyprod-0.4.0}/docs/pyprod2.png +0 -0
  35. {pyprod-0.3.0 → pyprod-0.4.0}/docs/quickstart.rst +0 -0
  36. {pyprod-0.3.0 → pyprod-0.4.0}/docs/requirements.txt +0 -0
  37. {pyprod-0.3.0 → pyprod-0.4.0}/pyprod.webp +0 -0
  38. {pyprod-0.3.0 → pyprod-0.4.0}/pyprod2.png +0 -0
  39. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/build-c/Makefile +0 -0
  40. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/build-c/hello.c +0 -0
  41. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/build-c/hello.h +0 -0
  42. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/build-c/main.c +0 -0
  43. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/generate-doc/.gitignore +0 -0
  44. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/generate-doc/a.txt +0 -0
  45. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/generate-doc/b.txt +0 -0
  46. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/generate-doc/c.txt +0 -0
  47. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/generate-doc/inc1.txt +0 -0
  48. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/generate-doc/inc2.txt +0 -0
  49. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/md-to-pdf/doc.md +0 -0
  50. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/md-to-pdf/md_to_html.py +0 -0
  51. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/md-to-pdf/template.html +0 -0
  52. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/s3files/S3TEST.txt +0 -0
  53. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/tutorial-1/Prodfile.py +0 -0
  54. {pyprod-0.3.0/sample → pyprod-0.4.0/samples}/tutorial-2/Prodfile.py +0 -0
  55. {pyprod-0.3.0 → pyprod-0.4.0}/src/pyprod/__init__.py +0 -0
  56. {pyprod-0.3.0 → pyprod-0.4.0}/src/pyprod/__main__.py +0 -0
  57. {pyprod-0.3.0 → pyprod-0.4.0}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyProd
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: PyProd: More Makeable than Make
5
5
  Project-URL: Homepage, https://github.com/atsuoishimoto/pyprod
6
6
  Project-URL: Documentation, https://pyprod.readthedocs.io/en/latest/
@@ -17,7 +17,7 @@ Description-Content-Type: text/x-rst
17
17
  PyProd - More Makeable than Make
18
18
  =================================
19
19
 
20
- PyProd is a Python script that can be used as an alternative to Makefile. By leveraging Python's versatility, it enables you to define build rules and dependencies programmatically, allowing for dynamic configurations, integration with existing Python libraries, and custom build logic not easily achievable with traditional Makefiles. For detailed documentation, please refer to the `official documentation <https://pyprod.readthedocs.io/en/latest/>`_.
20
+ PyProd is a Python script that can be used as an alternative to Makefile. By leveraging Python's versatility, it enables you to define build rules and dependencies programmatically, allowing for dynamic configurations, integration with existing Python libraries, and custom build logic not easily achievable with traditional Makefiles. For detailed documentation, please refer to the `official documentation <https://pyprod.readthedocs.io/en/stable/>`_.
21
21
 
22
22
 
23
23
  Features
@@ -42,22 +42,26 @@ With PyProd, a traditional Makefile for C can be expressed as a Python script li
42
42
  .. code-block:: python
43
43
 
44
44
  CC = "gcc"
45
- CFLAGS = "-I."
45
+ CFLAGS = "-c -I."
46
46
  DEPS = "hello.h"
47
47
  OBJS = "hello.o main.o".split()
48
+ EXE = "hello.exe"
48
49
 
49
50
  @rule("%.o", depends=("%.c", DEPS))
50
51
  def compile(target, src, *deps):
51
- run(CC, "-c -o", target, src, CFLAGS)
52
+ run(CC, "-o", target, src, CFLAGS)
52
53
 
53
- @rule("hello.exe", depends=OBJS)
54
+ @rule(EXE, depends=OBJS)
54
55
  def link(target, *objs):
55
56
  run(CC, "-o", target, objs)
56
57
 
58
+ @task
57
59
  def clean():
58
60
  run("rm -f", OBJS, "hello.exe")
59
61
 
60
- all = "hello.exe"
62
+ @task
63
+ def rebuild():
64
+ build(clean, EXE)
61
65
 
62
66
 
63
67
  To run the build script, simply execute:
@@ -67,6 +71,8 @@ To run the build script, simply execute:
67
71
  $ cd project
68
72
  $ pyprod
69
73
 
74
+ Other examples can be found in the `samples <https://github.com/atsuoishimoto/pyprod/tree/main/samples>`_ directory.
75
+
70
76
  License
71
77
  -------
72
78
  PyProd is licensed under the MIT License. See the `LICENSE <LICENSE>`_ file for more details.
@@ -1,7 +1,7 @@
1
1
  PyProd - More Makeable than Make
2
2
  =================================
3
3
 
4
- PyProd is a Python script that can be used as an alternative to Makefile. By leveraging Python's versatility, it enables you to define build rules and dependencies programmatically, allowing for dynamic configurations, integration with existing Python libraries, and custom build logic not easily achievable with traditional Makefiles. For detailed documentation, please refer to the `official documentation <https://pyprod.readthedocs.io/en/latest/>`_.
4
+ PyProd is a Python script that can be used as an alternative to Makefile. By leveraging Python's versatility, it enables you to define build rules and dependencies programmatically, allowing for dynamic configurations, integration with existing Python libraries, and custom build logic not easily achievable with traditional Makefiles. For detailed documentation, please refer to the `official documentation <https://pyprod.readthedocs.io/en/stable/>`_.
5
5
 
6
6
 
7
7
  Features
@@ -26,22 +26,26 @@ With PyProd, a traditional Makefile for C can be expressed as a Python script li
26
26
  .. code-block:: python
27
27
 
28
28
  CC = "gcc"
29
- CFLAGS = "-I."
29
+ CFLAGS = "-c -I."
30
30
  DEPS = "hello.h"
31
31
  OBJS = "hello.o main.o".split()
32
+ EXE = "hello.exe"
32
33
 
33
34
  @rule("%.o", depends=("%.c", DEPS))
34
35
  def compile(target, src, *deps):
35
- run(CC, "-c -o", target, src, CFLAGS)
36
+ run(CC, "-o", target, src, CFLAGS)
36
37
 
37
- @rule("hello.exe", depends=OBJS)
38
+ @rule(EXE, depends=OBJS)
38
39
  def link(target, *objs):
39
40
  run(CC, "-o", target, objs)
40
41
 
42
+ @task
41
43
  def clean():
42
44
  run("rm -f", OBJS, "hello.exe")
43
45
 
44
- all = "hello.exe"
46
+ @task
47
+ def rebuild():
48
+ build(clean, EXE)
45
49
 
46
50
 
47
51
  To run the build script, simply execute:
@@ -51,6 +55,8 @@ To run the build script, simply execute:
51
55
  $ cd project
52
56
  $ pyprod
53
57
 
58
+ Other examples can be found in the `samples <https://github.com/atsuoishimoto/pyprod/tree/main/samples>`_ directory.
59
+
54
60
  License
55
61
  -------
56
62
  PyProd is licensed under the MIT License. See the `LICENSE <LICENSE>`_ file for more details.
@@ -5,16 +5,16 @@ Command line options
5
5
  ------------------------
6
6
 
7
7
 
8
- usage: pyprod [-h] [-f FILE] [-j JOB] [-v] [-C DIRECTORY] [targets ...]
8
+ usage: pyprod [-h] [-C DIRECTORY] [-f FILE] [-j JOB] [-r] [-v] [targets ...]
9
9
 
10
10
  positional arguments:
11
11
  targets Build targets. If no specific target is provided on the command line, the first target defined in the Prodfile is selected by default. Arguments containing ``=`` specifies the value of a :ref:`params <params>` (e.g., ``key=value``).
12
12
 
13
13
  options:
14
- -f, --file FILE Use FILE as the Prodfile (default: 'PRODFILE.py').
15
- -j, --job JOB Allow up to N jobs to run simultaneously (default: 1).
14
+ -h, --help show this help message and exit
16
15
  -C, --directory DIRECTORY
17
- Change to DIRECTORY before performing any operations.
18
- -v Increase verbosity level (default: 0). Use multiple -v options to increase verbosity, up to a maximum of 3.
19
-
20
-
16
+ Change to DIRECTORY before performing any operations
17
+ -f, --file FILE Use FILE as the Prodfile (default: 'PRODFILE.py')
18
+ -j, --job JOB Allow up to N jobs to run simultaneously (default: 1)
19
+ -r, --rebuild Rebuild all
20
+ -v Increase verbosity level (default: 0)
@@ -1,17 +1,47 @@
1
1
  PyProd - More Makeable than Make
2
2
  ============================================
3
-
4
3
  PyProd is a Python script that can be used as an alternative to Makefile. By leveraging Python's versatility, it enables you to define build rules and dependencies programmatically, allowing for dynamic configurations, integration with existing Python libraries, and custom build logic not easily achievable with traditional Makefiles.
5
4
 
6
5
  Features
7
6
  --------
8
-
9
7
  - Define build rules in Python: Use Python functions to create clear and concise build logic.
10
8
  - Specify dependencies for each rule: Automatically track and resolve dependencies between files, such as source files and headers.
11
9
  - Easily extendable with custom Python functions: Integrate custom logic for specialized tasks, like code linting or deployment.
12
10
  - Manages virtual environments: Automatically create and manage virtual environments for each project, ensuring a clean and isolated build environment.
13
11
 
14
12
 
13
+ Example
14
+ -------
15
+ With PyProd, a traditional Makefile for C can be expressed as a Python script like this:
16
+
17
+ .. code-block:: python
18
+
19
+ CC = "gcc"
20
+ CFLAGS = "-c -I."
21
+ DEPS = "hello.h"
22
+ OBJS = "hello.o main.o".split()
23
+ EXE = "hello.exe"
24
+
25
+ @rule("%.o", depends=("%.c", DEPS))
26
+ def compile(target, src, *deps):
27
+ run(CC, "-o", target, src, CFLAGS)
28
+
29
+ @rule(EXE, depends=OBJS)
30
+ def link(target, *objs):
31
+ run(CC, "-o", target, objs)
32
+
33
+ @task
34
+ def clean():
35
+ run("rm -f", OBJS, "hello.exe")
36
+
37
+ @task
38
+ def rebuild():
39
+ build(clean, EXE)
40
+
41
+
42
+
43
+ Other examples can be found in the `samples <https://github.com/atsuoishimoto/pyprod/tree/main/samples>`_ directory.
44
+
15
45
  Table of Contents
16
46
  --------------------
17
47
 
@@ -10,12 +10,12 @@ Rule definition
10
10
 
11
11
  A rule is defined using the ``@rule`` decorator, which takes the target file as an argument. The target file is the output of the rule, and the function that follows the decorator is the build logic that generates the target file.
12
12
 
13
- .. py:function:: @rule(target, pattern=None, depends=(), uses=())
13
+ .. py:function:: @rule(targets, pattern=None, *, depends=(), uses=())
14
14
 
15
15
  Defines rule to build target files.
16
16
 
17
- :param target: The target file or files to be generated by the rule. Wildcards can be used in filenames, and exactly one % must be included in the filename.
18
- :type target: str | Path|list[str | Path]
17
+ :param targets: The target file or files to be generated by the rule. Wildcards can be used in filenames, and exactly one % must be included in the filename.
18
+ :type target: str | Path | list[str | Path]
19
19
 
20
20
  :param pattern: Specify the pattern used to extract the stem of the target filename.
21
21
 
@@ -85,8 +85,8 @@ The rule decorator can also be used as a standalone function without being tied
85
85
 
86
86
  .. code-block:: python
87
87
 
88
- rule(target=("file1", "file2"), depends="inc1")
89
- rule(target=("file3", "file4"), uses="inc2")
88
+ rule(targets=("file1", "file2"), depends="inc1")
89
+ rule(targets=("file3", "file4"), uses="inc2")
90
90
 
91
91
 
92
92
 
@@ -97,12 +97,12 @@ Checker definition
97
97
  PyProd provides default checkers for common file types for files and directories. For non-file targets requiring specialized checks, you can define a custom checker to determine whether a build is needed.
98
98
  A checker is defined using the ``@check`` decorator, which takes the target file as an argument.
99
99
 
100
- .. py:function:: @check(target)
100
+ .. py:function:: @check(targets)
101
101
 
102
102
  Defines a checker to get last modified time of the target.
103
103
 
104
- :param target: The target file to be checked. Wildcards can be used.
105
- :type target: str | Path
104
+ :param targets: The target file or files to be checked. Wildcards can be used.
105
+ :type target: str | Path | list[str | Path]
106
106
 
107
107
  :return: Last modified time of the file if the target exists. Returns false or raise FileNotFoundError if the target does not exist.
108
108
  :rtype: false|float|datetime.datetime
@@ -137,6 +137,39 @@ For example, a checker to retrieve the last modified timestamp of a file on Amaz
137
137
  return
138
138
  raise
139
139
 
140
+ Task definition
141
+ ^^^^^^^^^^^^^^^^^^
142
+
143
+ A task is similar to a rule but does not have a target and is always executed when it is depended upon.
144
+
145
+ .. py:function:: @task(*, name=None, depends=(), uses=())
146
+
147
+ Defines a task to be executed.
148
+
149
+ :param name: The name of the task. Defaults to the function name.
150
+ :type name: str
151
+
152
+ :param depends: Specify the dependencies of the task. The task is alwayes excused regardless of the timestamp of the dependencies. The dependencies are passed to the task function as arguments.
153
+ :type depends: str | Path | list[str | Path]
154
+
155
+ :param uses: Specify the dependencies of the target file. Unline the ``depends`` parameter, ``uses`` are not passed to the task function.
156
+ :type uses: str | Path | list[str | Path]
157
+
158
+
159
+ .. code-block:: python
160
+
161
+ @task(depends=("file1", "file2"))
162
+ def my_task(*files):
163
+ print("Task executed", files)
164
+
165
+
166
+ `@task` can be used without any arguments if no dependencies are specified.
167
+
168
+ .. code-block:: python
169
+
170
+ @task
171
+ def my_task(*files):
172
+ print("Task executed", files)
140
173
 
141
174
 
142
175
 
@@ -147,6 +180,11 @@ In addition to the ``@rule`` and ``@check`` decorators, PyProd provides several
147
180
 
148
181
  The following built-ins are available:
149
182
 
183
+ .. py:function:: build(*deps):
184
+
185
+ Schedule dependencies. The specified deps are built sequentially after the current build completes.
186
+
187
+ :param args: name or functions to be built.
150
188
 
151
189
  .. py:function:: pip(*args)
152
190
 
@@ -196,8 +234,8 @@ Example:
196
234
  .. code-block:: python
197
235
 
198
236
  run(["echo", "Hello, World!"]) # list style args
199
- run(["echo Hello, World"]) # Shell style args
200
- run(["echo", "Hello,", "World"]) # Shell style args (automactic concatenation)
237
+ run("echo Hello, World") # Shell style args
238
+ run("echo", "Hello,", "World") # Shell style args (automactic concatenation)
201
239
  run("echo", ["hello", ["world"]]) # Shell style args (automactic flattening)
202
240
 
203
241
  files = run("ls", stdout=True).stdout # Capture output
@@ -211,10 +249,10 @@ Example:
211
249
  :param args: Command and arguments to execute. If first argument is a list, the first element is the command and the rest are arguments. Sequences specified for args are automatically flattened.
212
250
  :type args: str | Path | list[str | Path]
213
251
 
214
- :echo: Print the command before executing it (default ``True``).
252
+ :param echo: Print the command before executing it (default ``True``).
215
253
  :type echo: bool
216
254
 
217
- :cwd: Change the current working directory before executing the command.
255
+ :param cwd: Change the current working directory before executing the command.
218
256
  :type shell: str | Path | None
219
257
 
220
258
  :param check: Raise an exception if the command returns a non-zero exit code (default ``True``).
@@ -285,27 +323,27 @@ Example:
285
323
 
286
324
  SRCFILES = glob("**/*.c")
287
325
 
288
- .. py:function:: quote(s)
289
- .. py:function:: q(s)
326
+ .. py:function:: quote(*s)
327
+ .. py:function:: q(*s)
290
328
 
291
- Convert ``s`` to string and quote for use as a shell command argument. This function is a wrapper around `shlex.quote() <https://docs.python.org/3/library/shlex.html#shlex.quote>`_.
329
+ Quote strings in ``s``. Each ``s`` is flattend.
292
330
 
293
331
  :param s: The string to quote.
294
- :type s: str
332
+ :type s: str | list
295
333
 
296
- :return: The quoted string.
297
- :rtype: str
334
+ :return: The list of quoted strings.
335
+ :rtype: list[str]
298
336
 
299
- .. py:function:: squote(*s)
300
- .. py:function:: sq(*s)
337
+ .. py:function:: squote(s)
338
+ .. py:function:: sq(s)
301
339
 
302
- Quote strings in ``s``. Each ``s`` is flattend.
340
+ Convert ``s`` to string and quote for use as a shell command argument. This function is a wrapper around `shlex.quote() <https://docs.python.org/3/library/shlex.html#shlex.quote>`_.
303
341
 
304
- :param s: The string to quote.
342
+ :param s: The string to quote. If ``s`` is sequence, it is flattened and joined with space.
305
343
  :type s: str | list
306
344
 
307
- :return: The list of quoted strings.
308
- :rtype: list[str]
345
+ :return: The quoted string.
346
+ :rtype: str
309
347
 
310
348
  .. py:class:: Path
311
349
 
@@ -0,0 +1,15 @@
1
+ Release Notes
2
+ ================
3
+
4
+ 0.4.0 (2025-1-17)
5
+ -------------------------
6
+ - Swapped the behavior of quote() and squote() to make their naming more intuitive.
7
+ - Add @task decorator.
8
+ - Change the parameter name target to targets.
9
+ - Add --rebuild option.
10
+
11
+ 0.3.0 (2025-01-03)
12
+ ------------------
13
+ - Arguments for build and check function are converted to string.
14
+ - Add built-in functions.
15
+ - Validate rule dependencies.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "PyProd"
3
- version = "0.3.0"
3
+ version = "0.4.0"
4
4
  description = "PyProd: More Makeable than Make"
5
5
  readme = "README.rst"
6
6
  requires-python = ">=3.10"
@@ -29,6 +29,7 @@ build-backend = "hatchling.build"
29
29
  dev = [
30
30
  "pytest>=8.3.4",
31
31
  "pytest-asyncio>=0.25.0",
32
+ "pytest-mock>=3.14.0",
32
33
  "ruff>=0.8.4",
33
34
  "sphinx>=8.1.3",
34
35
  "sphinx-autobuild>=2024.10.3",
@@ -3,7 +3,7 @@
3
3
 
4
4
  APP = "hello.exe"
5
5
  CC = "gcc"
6
- CFLAGS = "-I."
6
+ CFLAGS = "-c -I."
7
7
  DEPS = "hello.h"
8
8
  OBJS = "hello.o main.o".split()
9
9
 
@@ -15,11 +15,14 @@ def link(target, *src):
15
15
 
16
16
  @rule("%.o", depends=("%.c", DEPS))
17
17
  def compile(target, src, *deps):
18
- run(CC, "-c -o", target, src, CFLAGS)
18
+ run(CC, "-o", target, src, CFLAGS)
19
19
 
20
20
 
21
+ @task
21
22
  def clean():
22
23
  run("rm", "-rf", OBJS, APP)
23
24
 
24
25
 
25
- all = APP
26
+ @task
27
+ def rebuild():
28
+ build(clean, APP)
@@ -23,8 +23,11 @@ def build_c(target, src, *commons):
23
23
  run("cat", *commons, src, ">", target)
24
24
 
25
25
 
26
+ @task
26
27
  def clean():
27
28
  run("rm", "-rf", BUILDDIR, BUILDFILES, DOC)
28
29
 
29
30
 
30
- all = DOC
31
+ @task
32
+ def rebuild():
33
+ build(clean, DOC)
@@ -42,6 +42,12 @@ def builds(target):
42
42
  os.makedirs(target)
43
43
 
44
44
 
45
+ @task
45
46
  def clean():
46
47
  shutil.rmtree(BUILD, ignore_errors=True)
47
48
  PDF.unlink(missing_ok=True)
49
+
50
+
51
+ @task
52
+ def rebuild():
53
+ build(clean, PDF)
@@ -1,7 +1,7 @@
1
1
  # ruff: NOQA
2
2
  # type: ignore
3
3
 
4
- pip("boto3") # install boto3
4
+ pip("boto3", "-q") # install boto3
5
5
 
6
6
  import boto3, botocore
7
7
  from urllib.parse import urlparse
@@ -17,7 +17,7 @@ def parse_s3url(s3url):
17
17
  return parsed.netloc, parsed.path.lstrip("/")
18
18
 
19
19
 
20
- @rule(target=TARGET, pattern="*/%.txt", depends="%.txt")
20
+ @rule(targets=TARGET, pattern="*/%.txt", depends="%.txt")
21
21
  def copyfile(target, src):
22
22
  """Copies a file to an S3 bucket."""
23
23
  bucket, key = parse_s3url(target)
@@ -36,16 +36,20 @@ def check_s3file(s3url):
36
36
  raise
37
37
 
38
38
 
39
+ @task
39
40
  def clean():
40
41
  """Deletes an S3 file."""
41
42
  bucket, key = parse_s3url(TARGET)
42
43
  s3.delete_object(Bucket=bucket, Key=key)
43
44
 
44
45
 
46
+ @task
45
47
  def ls():
46
48
  """Lists the contents of an S3 bucket."""
47
49
  bucket, key = parse_s3url(TARGET)
48
50
  run("aws s3 ls", bucket)
49
51
 
50
52
 
51
- rule("S3TEST.txt") # Define target for default goal
53
+ @task
54
+ def rebuild():
55
+ build(clean, TARGET)
@@ -14,6 +14,13 @@ parser = argparse.ArgumentParser(
14
14
  description="""PyProd - More makable than make""",
15
15
  )
16
16
 
17
+ parser.add_argument(
18
+ "-C",
19
+ "--directory",
20
+ dest="directory",
21
+ help="Change to DIRECTORY before performing any operations",
22
+ )
23
+
17
24
  parser.add_argument(
18
25
  "-f", "--file", help="Use FILE as the Prodfile (default: 'PRODFILE.py')"
19
26
  )
@@ -27,12 +34,8 @@ parser.add_argument(
27
34
  )
28
35
 
29
36
  parser.add_argument(
30
- "-C",
31
- "--directory",
32
- dest="directory",
33
- help="Change to DIRECTORY before performing any operations",
37
+ "-r", "--rebuild", dest="rebuild", action="store_true", help="Rebuild all"
34
38
  )
35
-
36
39
  parser.add_argument(
37
40
  "-v",
38
41
  dest="verbose",
@@ -55,8 +58,13 @@ def print_exc(e):
55
58
  logger.exception("Terminated by exception")
56
59
 
57
60
 
61
+ def init_args(args=None):
62
+ args = pyprod.args = parser.parse_args(args)
63
+ return args
64
+
65
+
58
66
  def main():
59
- args = pyprod.args = parser.parse_args()
67
+ args = init_args()
60
68
  pyprod.verbose = args.verbose
61
69
  chdir = args.directory
62
70
  if chdir:
@@ -89,6 +97,7 @@ def main():
89
97
 
90
98
  params = {}
91
99
  targets = []
100
+
92
101
  for target in args.targets:
93
102
  if "=" in target:
94
103
  name, value = target.split("=", 1)
@@ -107,7 +116,10 @@ def main():
107
116
  sys.exit("No default target")
108
117
  targets = [target]
109
118
 
110
- ret = asyncio.run(prod.start(targets))
119
+ ret = 0
120
+ for target in targets:
121
+ ret += asyncio.run(prod.start([target]))
122
+
111
123
  if not ret:
112
124
  print(f"Nothing to be done for {targets}")
113
125