Skip to content
This repository was archived by the owner on Jul 29, 2024. It is now read-only.

Commit 1b6c5ac

Browse files
Minor updates (#26)
2 parents 489dc2e + 0b06191 commit 1b6c5ac

File tree

8 files changed

+128
-65
lines changed

8 files changed

+128
-65
lines changed

.github/workflows/standard.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
# ----------------------------------------------------------------------
2424
action_contexts:
2525
name: "Display GitHub Action Contexts"
26-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_display_action_contexts.yaml@CI-v0.15.3
26+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_display_action_contexts.yaml@CI-v0.15.4
2727

2828
# ----------------------------------------------------------------------
2929
validate:
@@ -45,7 +45,7 @@ jobs:
4545

4646
name: Validate
4747

48-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python.yaml@CI-v0.15.3
48+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python.yaml@CI-v0.15.4
4949
with:
5050
operating_system: ${{ matrix.os }}
5151
python_version: ${{ matrix.python_version }}
@@ -57,7 +57,7 @@ jobs:
5757
name: Postprocess Coverage Info
5858
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
5959

60-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_package_python_coverage.yaml@CI-v0.15.3
60+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_package_python_coverage.yaml@CI-v0.15.4
6161
with:
6262
gist_id: 2f9d770d13e3a148424f374f74d41f4b
6363
gist_filename: PythonProjectBootstrapper_coverage.json
@@ -86,7 +86,7 @@ jobs:
8686

8787
name: Create Package
8888

89-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_package.yaml@CI-v0.15.3
89+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_package.yaml@CI-v0.15.4
9090
with:
9191
operating_system: ${{ matrix.os }}
9292
python_version: ${{ matrix.python_version }}
@@ -113,7 +113,7 @@ jobs:
113113

114114
name: Validate Package
115115

116-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_package.yaml@CI-v0.15.3
116+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_package.yaml@CI-v0.15.4
117117
with:
118118
operating_system: ${{ matrix.os }}
119119
python_version: ${{ matrix.python_version }}
@@ -137,7 +137,7 @@ jobs:
137137

138138
name: Create Binary
139139

140-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_binary.yaml@CI-v0.15.3
140+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_binary.yaml@CI-v0.15.4
141141
with:
142142
operating_system: ${{ matrix.os }}
143143
python_version: ${{ matrix.python_version }}
@@ -160,7 +160,7 @@ jobs:
160160

161161
name: Validate Binary
162162

163-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_binary.yaml@CI-v0.15.3
163+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_binary.yaml@CI-v0.15.4
164164
with:
165165
operating_system: ${{ matrix.os }}
166166
python_version: ${{ matrix.python_version }}
@@ -174,7 +174,7 @@ jobs:
174174

175175
name: Publish
176176

177-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_publish_python.yaml@CI-v0.15.3
177+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_publish_python.yaml@CI-v0.15.4
178178
with:
179179
release_sources_configuration_filename: .github/release_sources.yaml
180180
secrets:

src/PythonProjectBootstrapper/EntryPoint.py

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
from cookiecutter.main import cookiecutter
2121
from dbrownell_Common.ContextlibEx import ExitStack
2222
from dbrownell_Common import PathEx
23+
from dbrownell_Common.Streams.DoneManager import DoneManager
24+
2325
from PythonProjectBootstrapper import __version__
2426
from PythonProjectBootstrapper.ProjectGenerationUtils import (
2527
CopyToOutputDir,
@@ -51,10 +53,31 @@ def list_commands(self, *args, **kwargs): # pylint: disable=unused-argument
5153

5254

5355
# ----------------------------------------------------------------------
54-
class ProjectType(str, Enum):
55-
"""Defines the different types of projects that can be specified on the command line."""
56+
# Dynamically create the ProjectType enumeration based on the directories found in this dir.
57+
58+
59+
def _CreateProjectType():
60+
project_types: list[str] = []
61+
62+
if getattr(sys, "frozen", False):
63+
template_dir = Path(sys.executable).parent / "lib" / "PythonProjectBootstrapper"
64+
else:
65+
template_dir = Path(__file__).parent
66+
67+
PathEx.EnsureDir(template_dir)
68+
69+
for file_item in template_dir.iterdir():
70+
if not file_item.is_dir():
71+
continue
72+
73+
project_types.append(file_item.name)
5674

57-
package = "package"
75+
assert project_types
76+
return Enum("ProjectType", {project_type: project_type for project_type in project_types})
77+
78+
79+
ProjectType = _CreateProjectType()
80+
del _CreateProjectType
5881

5982

6083
# ----------------------------------------------------------------------
@@ -88,6 +111,11 @@ def _VersionCallback(value: bool) -> None:
88111
is_eager=True,
89112
)
90113

114+
_skip_prompts_option = typer.Option(
115+
"--skip-prompts",
116+
help="Do not display prompts after generating content.",
117+
)
118+
91119

92120
# ----------------------------------------------------------------------
93121
# The cookiecutter project dir must be accessed in different ways depending on whether the code is:
@@ -113,6 +141,7 @@ def FrozenExecute(
113141
configuration_filename: Annotated[Optional[Path], _configuration_filename_option] = None,
114142
replay: Annotated[bool, _replay_option] = False,
115143
yes: Annotated[bool, _yes_option] = False,
144+
skip_prompts: Annotated[bool, _skip_prompts_option] = False,
116145
version: Annotated[bool, _version_option] = False, # pylint: disable=unused-argument
117146
) -> None:
118147
if output_dir.is_file():
@@ -128,6 +157,7 @@ def FrozenExecute(
128157
configuration_filename,
129158
replay=replay,
130159
yes=yes,
160+
skip_prompts=skip_prompts,
131161
)
132162

133163
# ----------------------------------------------------------------------
@@ -145,6 +175,7 @@ def StandardExecute(
145175
configuration_filename: Annotated[Optional[Path], _configuration_filename_option] = None,
146176
replay: Annotated[bool, _replay_option] = False,
147177
yes: Annotated[bool, _yes_option] = False,
178+
skip_prompts: Annotated[bool, _skip_prompts_option] = False,
148179
version: Annotated[bool, _version_option] = False, # pylint: disable=unused-argument
149180
) -> None:
150181
_ExecuteOutputDir(
@@ -153,6 +184,7 @@ def StandardExecute(
153184
configuration_filename,
154185
replay=replay,
155186
yes=yes,
187+
skip_prompts=skip_prompts,
156188
)
157189

158190

@@ -169,6 +201,7 @@ def _ExecuteOutputDir(
169201
*,
170202
replay: bool,
171203
yes: bool,
204+
skip_prompts: bool,
172205
) -> None:
173206
if not (output_dir / ".git").is_dir():
174207
raise Exception(f"{output_dir} is not a git repository.")
@@ -190,18 +223,21 @@ def _ExecuteOutputDir(
190223
if execute_func(project_dir, tmp_dir, yes=yes) is False:
191224
return
192225

193-
# generate project in temporary directory so we can avoid overwriting files without user approval
194-
cookiecutter(
195-
str(project_dir),
196-
output_dir=str(tmp_dir),
197-
config_file=str(configuration_filename) if configuration_filename is not None else None,
198-
replay=replay,
199-
overwrite_if_exists=True,
200-
accept_hooks=True,
201-
)
226+
with DoneManager.Create(sys.stdout, "\nGenerating content..."):
227+
# generate project in temporary directory so we can avoid overwriting files without user approval
228+
cookiecutter(
229+
str(project_dir),
230+
output_dir=str(tmp_dir),
231+
config_file=str(configuration_filename) if configuration_filename is not None else None,
232+
replay=replay,
233+
overwrite_if_exists=True,
234+
accept_hooks=True,
235+
)
202236

203237
CopyToOutputDir(src_dir=tmp_dir, dest_dir=output_dir)
204-
DisplayPrompt(output_dir=output_dir)
238+
239+
if not skip_prompts:
240+
DisplayPrompt(output_dir=output_dir)
205241

206242

207243
if __name__ == "__main__":

src/PythonProjectBootstrapper/package/{{ cookiecutter.__empty_dir }}/.github/workflows/standard.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
# ----------------------------------------------------------------------
1919
action_contexts:
2020
name: "Display GitHub Action Contexts"
21-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_display_action_contexts.yaml@CI-v0.15.3
21+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_display_action_contexts.yaml@CI-v0.15.4
2222

2323
# ----------------------------------------------------------------------
2424
validate:
@@ -40,7 +40,7 @@ jobs:
4040

4141
name: Validate
4242

43-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python.yaml@CI-v0.15.3
43+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python.yaml@CI-v0.15.4
4444
with:
4545
operating_system: {% raw %}${{ matrix.os }}{% endraw %}
4646
python_version: {% raw %}${{ matrix.python_version }}{% endraw %}
@@ -52,7 +52,7 @@ jobs:
5252
name: Postprocess Coverage Info
5353
if: {% raw %}${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}{% endraw %}
5454

55-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_package_python_coverage.yaml@CI-v0.15.3
55+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_package_python_coverage.yaml@CI-v0.15.4
5656
with:
5757
gist_id: {{ cookiecutter.gist_id }}
5858
gist_filename: {{ cookiecutter.github_project_name }}_coverage.json
@@ -81,7 +81,7 @@ jobs:
8181

8282
name: Create Package
8383

84-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_package.yaml@CI-v0.15.3
84+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_package.yaml@CI-v0.15.4
8585
with:
8686
operating_system: {% raw %}${{ matrix.os }}{% endraw %}
8787
python_version: {% raw %}${{ matrix.python_version }}{% endraw %}
@@ -108,7 +108,7 @@ jobs:
108108

109109
name: Validate Package
110110

111-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_package.yaml@CI-v0.15.3
111+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_package.yaml@CI-v0.15.4
112112
with:
113113
operating_system: {% raw %}${{ matrix.os }}{% endraw %}
114114
python_version: {% raw %}${{ matrix.python_version }}{% endraw %}
@@ -132,7 +132,7 @@ jobs:
132132

133133
name: Create Binary
134134

135-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_binary.yaml@CI-v0.15.3
135+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_binary.yaml@CI-v0.15.4
136136
with:
137137
operating_system: {% raw %}${{ matrix.os }}{% endraw %}
138138
python_version: {% raw %}${{ matrix.python_version }}{% endraw %}
@@ -155,7 +155,7 @@ jobs:
155155

156156
name: Validate Binary
157157

158-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_binary.yaml@CI-v0.15.3
158+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_binary.yaml@CI-v0.15.4
159159
with:
160160
operating_system: {% raw %}${{ matrix.os }}{% endraw %}
161161
python_version: {% raw %}${{ matrix.python_version }}{% endraw %}
@@ -179,7 +179,7 @@ jobs:
179179

180180
name: Create Docker Image
181181

182-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_docker_image.yaml@CI-v0.15.3
182+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_docker_image.yaml@CI-v0.15.4
183183
with:
184184
operating_system: ubuntu-latest
185185
python_version: {% raw %}${{ matrix.python_version }}{% endraw %}
@@ -201,7 +201,7 @@ jobs:
201201

202202
name: Publish
203203

204-
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_publish_python.yaml@CI-v0.15.3
204+
uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_publish_python.yaml@CI-v0.15.4
205205
with:
206206
release_sources_configuration_filename: .github/release_sources.yaml
207207
secrets:
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import json
2+
import os
3+
import sys
4+
5+
from pathlib import Path
6+
7+
with (Path(os.environ["PYTHON_BOOTSTRAPPER_GENERATED_DIR"]) / "bootstrap_flags.json").open() as f:
8+
flags = json.load(f)
9+
10+
if flags:
11+
sys.stdout.write("\nBootstrapped with {}.\n".format(", ".join(f"'{flag}'" for flag in flags)))

src/PythonProjectBootstrapper/package/{{ cookiecutter.__empty_dir }}/BootstrapEpilog.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
{%- include "python_header.py" -%}
22
# pylint: disable=missing-module-docstring
33

4+
import os
45
import subprocess
56
import sys
67

8+
from pathlib import Path
9+
710

811
# Parse the arguments
912
is_debug = False
@@ -12,6 +15,8 @@
1215
is_package = False
1316
no_cache = False
1417

18+
display_flags: list[str] = []
19+
1520
# First arg is the script name, second arg is the name of the shell script to write to
1621
for arg in sys.argv[2:]:
1722
if arg == "--debug":
@@ -22,6 +27,7 @@
2227
is_verbose = True
2328
elif arg == "--package":
2429
is_package = True
30+
display_flags.append("package")
2531
elif arg == "--no-cache":
2632
no_cache = True
2733
else:
@@ -38,3 +44,8 @@
3844
check=True,
3945
shell=True,
4046
)
47+
48+
with (
49+
Path(__file__).parent / os.environ["PYTHON_BOOTSTRAPPER_GENERATED_DIR"] / "bootstrap_flags.json"
50+
).open("w") as f:
51+
f.write("[{}]".format(", ".join(f'"{flag}"' for flag in display_flags)))
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
## Local Development
2+
3+
Follow these steps to prepare the repository for local development activities.
4+
5+
1) Clone this repository
6+
2) Bootstrap the local repository by running...
7+
| Operating System | Command |
8+
| --- | --- |
9+
| Linux / MacOS | <p>Standard:<br/>`Bootstrap.sh`</p><p>Standard + packaging:<br/>`Bootstrap.sh --package`</p> |
10+
| Windows | <p>Standard:<br/>`Bootstrap.cmd`</p><p>Standard + packaging:<br/>`Bootstrap.cmd --package`</p> |
11+
3) Activate the development environment by running...
12+
| Operating System | Command |
13+
| --- | --- |
14+
| Linux / MacOS | `. ./Activate.sh` |
15+
| Windows | `Activate.cmd` |
16+
4) Invoke `Build.py`
17+
| Command | Description | Example | Notes |
18+
| --- | --- | --- | --- |
19+
| `black` | Validates that the source code is formatted by [black](https://github.com/psf/black). | <p>Validation:<br/>`python Build.py black`</p><p>Perform formatting:<br/>`python Build.py black --format`</p> | |
20+
| `pylint` | Validates the source code using [pylint](https://github.com/pylint-dev/pylint). | `python Build.py pylint` | |
21+
| `pytest` | Runs automated tests using [pytest](https://docs.pytest.org/). | <p>Without Code Coverage:<br/>`python Build.py pytest`</p><p>With Code Coverage:<br/>`python Build.py pytest --code-coverage`</p> | |
22+
| `update_version` | Updates the [semantic version](https://semver.org/) of the package based on git commits using [AutoGitSemVer](https://github.com/davidbrownell/AutoGitSemVer). | `python Build.py update_version` | |
23+
| `package` | Creates a Python wheel package for distribution; outputs to the `/dist` directory. | `python Build.py package` | Requires `--package` when bootstrapping in step #2. |
24+
| `publish` | Publishes a Python wheel package to [PyPi](https://pypi.org/). | <p>https://test.pypi.org:<br/>`python Build.py publish`</p><p>https://pypi.org:<br/>`python Build.py publish --production`</p> | Requires `--package` when bootstrapping in step #2. |
25+
| `build_binary` | Builds an executable for your package that can be run on machines without a python installation; outputs to the `/build` directory. | `python Build.py build_binary` | Requires `--package` when bootstrapping in step #2. |
26+
{%- if cookiecutter.create_docker_image %}
27+
| `create_docker_image` | Creates a [Docker](https://www.docker.com/) image based on the current development environment. This supports the "Reusable" aspect of [FAIR principles](https://www.go-fair.org/fair-principles/) by creating a snapshot of the repository and all of its dependencies as they exist in a single moment in time. | `python Build.py create_docker_image` | Requires docker. |
28+
{% endif %}
29+
30+
5) [Optional] Deactivate the development environment by running...
31+
| Operating System | Command |
32+
| --- | --- |
33+
| Linux / MacOS | `. ./Deactivate.sh` |
34+
| Windows | `Deactivate.cmd` |

0 commit comments

Comments
 (0)