pace-dotnet 0.1.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.
- pace/__init__.py +6 -0
- pace/cli.py +339 -0
- pace/commands/__init__.py +11 -0
- pace/commands/clean.py +365 -0
- pace/commands/dotnet.py +314 -0
- pace/commands/format.py +12 -0
- pace/commands/git.py +265 -0
- pace/commands/init.py +12 -0
- pace/commands/test.py +12 -0
- pace/commands/upload.py +165 -0
- pace/config.py +270 -0
- pace/console_helpers.py +14 -0
- pace/data/__init__.py +1 -0
- pace/data/pace.toml +8 -0
- pace/rich_demos/__init__.py +1 -0
- pace/rich_demos/columns.py +35 -0
- pace/rich_demos/progress_bar.py +37 -0
- pace_dotnet-0.1.0.dist-info/METADATA +183 -0
- pace_dotnet-0.1.0.dist-info/RECORD +23 -0
- pace_dotnet-0.1.0.dist-info/WHEEL +5 -0
- pace_dotnet-0.1.0.dist-info/entry_points.txt +2 -0
- pace_dotnet-0.1.0.dist-info/licenses/LICENSE +21 -0
- pace_dotnet-0.1.0.dist-info/top_level.txt +1 -0
pace/__init__.py
ADDED
pace/cli.py
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"""CLI entry point for PACE."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
from argparse import Namespace
|
|
7
|
+
from importlib.resources import files
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
# Force UTF-8 encoding for stdout/stderr to avoid encoding issues on Windows
|
|
12
|
+
os.environ["PYTHONIOENCODING"] = "utf-8:replace"
|
|
13
|
+
if sys.platform == "win32":
|
|
14
|
+
# Reconfigure stdout/stderr to use UTF-8 with replace error handling
|
|
15
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace") # type: ignore[attr-defined]
|
|
16
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace") # type: ignore[attr-defined]
|
|
17
|
+
|
|
18
|
+
import rich
|
|
19
|
+
from rich.console import Console
|
|
20
|
+
from rich.traceback import install
|
|
21
|
+
|
|
22
|
+
from pace.commands import clean, dotnet, git, upload
|
|
23
|
+
from pace.config import Config, load_config
|
|
24
|
+
from pace.rich_demos import columns, progress_bar
|
|
25
|
+
|
|
26
|
+
_DEMOS = {
|
|
27
|
+
"columns": columns.run,
|
|
28
|
+
"progress_bar": progress_bar.run,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class _Option:
|
|
33
|
+
def __init__(self, short: str, long: str, description: str, metavar: str | None = None) -> None:
|
|
34
|
+
self.short = short
|
|
35
|
+
self.long = long
|
|
36
|
+
self.metavar = metavar
|
|
37
|
+
self.description = description
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class _Options:
|
|
41
|
+
DEBUG = _Option("", "--debug", "Enable debug mode with full tracebacks")
|
|
42
|
+
CONFIG = _Option(
|
|
43
|
+
"-C",
|
|
44
|
+
"--config",
|
|
45
|
+
"Path to configuration file. Defaults to an internal pace.toml file.",
|
|
46
|
+
metavar="<path>",
|
|
47
|
+
)
|
|
48
|
+
PRINT_CONFIG = _Option("", "--print-config", "Print the configuration and exit")
|
|
49
|
+
PRINT_CONFIG_PATH = _Option(
|
|
50
|
+
"", "--print-config-path", "Print the path to the configuration file and exit"
|
|
51
|
+
)
|
|
52
|
+
VERSION = _Option("-v", "--version", "Print the version and exit")
|
|
53
|
+
FROM_REPO = _Option(
|
|
54
|
+
"",
|
|
55
|
+
"--from",
|
|
56
|
+
"Starting repository name. Only projects in the dependency chain from this repo will be included.",
|
|
57
|
+
metavar="<reponame>",
|
|
58
|
+
)
|
|
59
|
+
TO_REPO = _Option(
|
|
60
|
+
"",
|
|
61
|
+
"--to",
|
|
62
|
+
"Ending repository name. Only projects in the dependency chain up to this repo will be included.",
|
|
63
|
+
metavar="<reponame>",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class PaceFormatter(argparse.HelpFormatter):
|
|
68
|
+
"""Custom help formatter for PACE CLI."""
|
|
69
|
+
|
|
70
|
+
def _format_usage(self, usage: Any, actions: Any, groups: Any, prefix: Any) -> str: # noqa: ARG002
|
|
71
|
+
"""Override usage formatting to match the desired style."""
|
|
72
|
+
return f"usage: [-h] [{_Options.CONFIG.short} {_Options.CONFIG.metavar}] [OPTIONS] command...\n\n"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def main() -> int:
|
|
76
|
+
"""Main entry point for the PACE CLI.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Exit code (0 for success, non-zero for failure)
|
|
80
|
+
"""
|
|
81
|
+
console = Console()
|
|
82
|
+
|
|
83
|
+
parser = argparse.ArgumentParser(
|
|
84
|
+
description="PACE - Project Automation and Configuration Engine",
|
|
85
|
+
formatter_class=PaceFormatter,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
_Options.DEBUG.long,
|
|
90
|
+
action="store_true",
|
|
91
|
+
default=False,
|
|
92
|
+
help="Enable debug mode with full tracebacks",
|
|
93
|
+
)
|
|
94
|
+
parser.add_argument(
|
|
95
|
+
_Options.CONFIG.short,
|
|
96
|
+
_Options.CONFIG.long,
|
|
97
|
+
metavar=_Options.CONFIG.metavar,
|
|
98
|
+
help="Path to configuration file. Defaults to an internal pace.toml file.",
|
|
99
|
+
type=Path,
|
|
100
|
+
)
|
|
101
|
+
parser.add_argument(
|
|
102
|
+
_Options.PRINT_CONFIG.long,
|
|
103
|
+
action="store_true",
|
|
104
|
+
help="Print the loaded configuration",
|
|
105
|
+
default=False,
|
|
106
|
+
)
|
|
107
|
+
parser.add_argument(
|
|
108
|
+
_Options.PRINT_CONFIG_PATH.long,
|
|
109
|
+
action="store_true",
|
|
110
|
+
help="Print the path to the configuration file and exit",
|
|
111
|
+
default=False,
|
|
112
|
+
)
|
|
113
|
+
parser.add_argument(_Options.VERSION.long, action="version", version="pace 0.1.0")
|
|
114
|
+
parser.add_argument(
|
|
115
|
+
_Options.FROM_REPO.long,
|
|
116
|
+
dest="from_repo",
|
|
117
|
+
metavar=_Options.FROM_REPO.metavar,
|
|
118
|
+
help=_Options.FROM_REPO.description,
|
|
119
|
+
default=None,
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
_Options.TO_REPO.long,
|
|
123
|
+
dest="to_repo",
|
|
124
|
+
metavar=_Options.TO_REPO.metavar,
|
|
125
|
+
help=_Options.TO_REPO.description,
|
|
126
|
+
default=None,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
subparsers = parser.add_subparsers(dest="command", metavar="command")
|
|
130
|
+
|
|
131
|
+
clean_parser = subparsers.add_parser(
|
|
132
|
+
"clean", help="Delete build artifacts and NuGet cache for all projects"
|
|
133
|
+
)
|
|
134
|
+
clean_parser.add_argument(
|
|
135
|
+
"--cache",
|
|
136
|
+
action="store_true",
|
|
137
|
+
help="Clean NuGet packages from ~/.nuget/packages",
|
|
138
|
+
default=False,
|
|
139
|
+
)
|
|
140
|
+
clean_parser.add_argument(
|
|
141
|
+
"--custom-cache",
|
|
142
|
+
action="store_true",
|
|
143
|
+
help="Clean NuGet packages from the custom cache path configured in nuget_cache_path",
|
|
144
|
+
default=False,
|
|
145
|
+
)
|
|
146
|
+
clean_parser.add_argument(
|
|
147
|
+
"--project",
|
|
148
|
+
action="store_true",
|
|
149
|
+
help="Clean project bin/ and obj/ directories",
|
|
150
|
+
default=False,
|
|
151
|
+
)
|
|
152
|
+
clean_parser.add_argument(
|
|
153
|
+
"-n",
|
|
154
|
+
"--dry-run",
|
|
155
|
+
action="store_true",
|
|
156
|
+
help="Show what would be deleted without actually deleting",
|
|
157
|
+
default=False,
|
|
158
|
+
)
|
|
159
|
+
dotnet_parser = subparsers.add_parser(
|
|
160
|
+
"dotnet", help="Execute dotnet commands across the project graph"
|
|
161
|
+
)
|
|
162
|
+
dotnet_parser.add_argument(
|
|
163
|
+
"dotnet_args",
|
|
164
|
+
metavar="... <dotnet-args>",
|
|
165
|
+
nargs=argparse.REMAINDER,
|
|
166
|
+
help="Arguments to pass to dotnet (e.g., 'build -c Release')",
|
|
167
|
+
)
|
|
168
|
+
_git_parser = subparsers.add_parser("git", help="Execute git commands across all repositories")
|
|
169
|
+
|
|
170
|
+
# Upload command with arguments
|
|
171
|
+
upload_parser = subparsers.add_parser(
|
|
172
|
+
"upload", help="Upload app packages to the deployment server"
|
|
173
|
+
)
|
|
174
|
+
upload_parser.add_argument(
|
|
175
|
+
"package_path",
|
|
176
|
+
metavar="<path-to-app-package>",
|
|
177
|
+
help="Path to the app package file (.ipa, .msix, .aab, .apk)",
|
|
178
|
+
type=Path,
|
|
179
|
+
)
|
|
180
|
+
upload_parser.add_argument(
|
|
181
|
+
"--username",
|
|
182
|
+
required=True,
|
|
183
|
+
help="Name of the uploader",
|
|
184
|
+
metavar="<username>",
|
|
185
|
+
)
|
|
186
|
+
upload_parser.add_argument(
|
|
187
|
+
"--app-name",
|
|
188
|
+
required=True,
|
|
189
|
+
help="Name of the application",
|
|
190
|
+
metavar="<appname>",
|
|
191
|
+
)
|
|
192
|
+
upload_parser.add_argument(
|
|
193
|
+
"--platform",
|
|
194
|
+
required=True,
|
|
195
|
+
choices=["iOS", "Android", "Windows"],
|
|
196
|
+
help="Target platform",
|
|
197
|
+
metavar="<platform>",
|
|
198
|
+
)
|
|
199
|
+
upload_parser.add_argument(
|
|
200
|
+
"--release-type",
|
|
201
|
+
required=True,
|
|
202
|
+
choices=["Debug", "Release"],
|
|
203
|
+
help="Build configuration",
|
|
204
|
+
metavar="<type>",
|
|
205
|
+
)
|
|
206
|
+
upload_parser.add_argument(
|
|
207
|
+
"--version",
|
|
208
|
+
required=True,
|
|
209
|
+
help="Version number or identifier",
|
|
210
|
+
metavar="<version>",
|
|
211
|
+
)
|
|
212
|
+
upload_parser.add_argument(
|
|
213
|
+
"--endpoint",
|
|
214
|
+
required=True,
|
|
215
|
+
help="Base URL of the deployment server",
|
|
216
|
+
metavar="<url>",
|
|
217
|
+
)
|
|
218
|
+
upload_parser.add_argument(
|
|
219
|
+
"-n",
|
|
220
|
+
"--build-description",
|
|
221
|
+
help="Build notes/description",
|
|
222
|
+
metavar="<description>",
|
|
223
|
+
default=None,
|
|
224
|
+
)
|
|
225
|
+
upload_parser.add_argument(
|
|
226
|
+
"-N",
|
|
227
|
+
"--build-description-from-file",
|
|
228
|
+
help="Read build description from file",
|
|
229
|
+
metavar="<filepath>",
|
|
230
|
+
type=Path,
|
|
231
|
+
default=None,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
demo_parser = subparsers.add_parser("demo", help="Run a built-in demo")
|
|
235
|
+
demo_parser.add_argument(
|
|
236
|
+
"name",
|
|
237
|
+
choices=list(_DEMOS),
|
|
238
|
+
metavar="name",
|
|
239
|
+
help=f"Demo to run. Choices: {', '.join(_DEMOS)}",
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
args: Namespace
|
|
243
|
+
unknownargs: list[str]
|
|
244
|
+
args, unknownargs = parser.parse_known_args()
|
|
245
|
+
|
|
246
|
+
if args.debug:
|
|
247
|
+
install(show_locals=True, suppress=[rich])
|
|
248
|
+
|
|
249
|
+
try:
|
|
250
|
+
return _run(console, args, unknownargs, parser)
|
|
251
|
+
except Exception as e:
|
|
252
|
+
if args.debug:
|
|
253
|
+
raise
|
|
254
|
+
console.print(f"[red]error:[/red] {e}")
|
|
255
|
+
return 1
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def process_options(console: Console, config: Config, args: Namespace) -> bool:
|
|
259
|
+
"""Process configuration options and return True if any were given.
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
console: Rich console for output
|
|
263
|
+
config: Loaded configuration
|
|
264
|
+
args: Parsed command line arguments
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
True if any configuration option was given, False otherwise
|
|
268
|
+
"""
|
|
269
|
+
config_path = args.config or files("pace.data").joinpath("pace.toml")
|
|
270
|
+
|
|
271
|
+
was_option_given = False
|
|
272
|
+
if args.print_config_path:
|
|
273
|
+
console.print(config_path)
|
|
274
|
+
was_option_given = True
|
|
275
|
+
|
|
276
|
+
if args.print_config:
|
|
277
|
+
console.print(config)
|
|
278
|
+
was_option_given = True
|
|
279
|
+
|
|
280
|
+
return was_option_given
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def _run(
|
|
284
|
+
console: Console, args: Namespace, unknownargs: list[str], parser: argparse.ArgumentParser
|
|
285
|
+
) -> int:
|
|
286
|
+
if args.config is not None:
|
|
287
|
+
if args.config.exists():
|
|
288
|
+
config = load_config(args.config, from_repo=args.from_repo, to_repo=args.to_repo)
|
|
289
|
+
else:
|
|
290
|
+
return 1
|
|
291
|
+
else:
|
|
292
|
+
config = load_config(from_repo=args.from_repo, to_repo=args.to_repo)
|
|
293
|
+
|
|
294
|
+
was_option_given = process_options(console, config, args)
|
|
295
|
+
|
|
296
|
+
match args.command:
|
|
297
|
+
case "clean":
|
|
298
|
+
clean.run(
|
|
299
|
+
console,
|
|
300
|
+
config,
|
|
301
|
+
cache=args.cache,
|
|
302
|
+
custom_cache=args.custom_cache,
|
|
303
|
+
project=args.project,
|
|
304
|
+
dry_run=args.dry_run,
|
|
305
|
+
)
|
|
306
|
+
case "dotnet":
|
|
307
|
+
return dotnet.run(console, config, args.dotnet_args)
|
|
308
|
+
case "git":
|
|
309
|
+
return git.run(console, config, unknownargs)
|
|
310
|
+
case "upload":
|
|
311
|
+
# Handle build description from file if provided
|
|
312
|
+
build_description = args.build_description
|
|
313
|
+
if args.build_description_from_file:
|
|
314
|
+
try:
|
|
315
|
+
build_description = args.build_description_from_file.read_text()
|
|
316
|
+
except Exception as e:
|
|
317
|
+
console.print(f"[red]Error reading build description file: {e}[/red]")
|
|
318
|
+
return 1
|
|
319
|
+
upload.run(
|
|
320
|
+
console,
|
|
321
|
+
args.package_path,
|
|
322
|
+
args.username,
|
|
323
|
+
args.app_name,
|
|
324
|
+
args.platform,
|
|
325
|
+
args.release_type,
|
|
326
|
+
args.version,
|
|
327
|
+
args.endpoint,
|
|
328
|
+
build_description,
|
|
329
|
+
)
|
|
330
|
+
case "demo":
|
|
331
|
+
_DEMOS[args.name](console, unknownargs)
|
|
332
|
+
case _:
|
|
333
|
+
if not was_option_given:
|
|
334
|
+
parser.print_help()
|
|
335
|
+
return 0
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
if __name__ == "__main__":
|
|
339
|
+
sys.exit(main())
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""PACE command modules."""
|
|
2
|
+
|
|
3
|
+
from pace.commands import clean as clean_cmd
|
|
4
|
+
from pace.commands import dotnet as dotnet_cmd
|
|
5
|
+
from pace.commands import format as format_cmd
|
|
6
|
+
from pace.commands import git as git_cmd
|
|
7
|
+
from pace.commands import init as init_cmd
|
|
8
|
+
from pace.commands import test as test_cmd
|
|
9
|
+
from pace.commands import upload as upload_cmd
|
|
10
|
+
|
|
11
|
+
__all__ = ["clean_cmd", "dotnet_cmd", "format_cmd", "git_cmd", "init_cmd", "test_cmd", "upload_cmd"]
|