unity-devkit 0.1.9__py3-none-any.whl → 0.1.11__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.
@@ -10,7 +10,9 @@ app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
10
10
 
11
11
  @app.command()
12
12
  def compile_unity(
13
- project: Annotated[str, typer.Option(help="Unity project name (directory containing unity-build.json)")],
13
+ project: Annotated[
14
+ str, typer.Option(help="Unity project name (directory containing ProjectSettings/ProjectVersion.txt)")
15
+ ],
14
16
  build: Annotated[str, typer.Option(help="Build target from the project's builds list (e.g. android-mobile)")],
15
17
  ) -> None:
16
18
  for artifact in build_unity_project(project, build):
unity_devkit/matrix.py CHANGED
@@ -26,6 +26,10 @@ def main() -> None:
26
26
  "editor-image": f"unityci/editor:{version}-{module}-{UNITYCI_IMAGE_REVISION}",
27
27
  })
28
28
 
29
+ if not editor_versions:
30
+ raise SystemExit(
31
+ "No projects with builds declared — unity-matrix needs at least one unity-build.json with a 'builds' list"
32
+ )
29
33
  license_version = max(editor_versions)
30
34
  print(f"matrix={json.dumps({'include': matrix})}")
31
35
  print(f"license-image=unityci/editor:{license_version}-{LICENSE_MODULE}-{UNITYCI_IMAGE_REVISION}")
unity_devkit/projects.py CHANGED
@@ -1,10 +1,12 @@
1
1
  import json
2
2
  import os
3
+ from collections.abc import Iterator
3
4
  from pathlib import Path
4
5
 
5
6
  from pydantic import BaseModel
6
7
 
7
8
  MANIFEST_FILENAME = "unity-build.json"
9
+ PROJECT_MARKER = Path("ProjectSettings") / "ProjectVersion.txt"
8
10
  PRUNE_DIRECTORIES = {".git", "Library", "Temp", "obj", "Build", "node_modules", "__pycache__"}
9
11
 
10
12
 
@@ -21,33 +23,46 @@ class UnityProject(UnityBuildManifest):
21
23
 
22
24
 
23
25
  def load_unity_projects() -> dict[str, UnityProject]:
26
+ root = Path.cwd()
27
+ project_directories = {directory.resolve() for directory in unity_project_directories(root)}
28
+ manifest_directories = {directory.resolve() for directory in directories_containing(root, MANIFEST_FILENAME)}
29
+
24
30
  projects: dict[str, UnityProject] = {}
25
- for directory in directories_containing(Path.cwd(), MANIFEST_FILENAME):
26
- project_path = directory.resolve()
27
- name = project_path.name
28
- version_file = project_path / "ProjectSettings" / "ProjectVersion.txt"
29
- if not version_file.exists():
31
+ for project_path in sorted(project_directories | manifest_directories):
32
+ if project_path not in project_directories:
30
33
  raise SystemExit(
31
- f"{project_path / MANIFEST_FILENAME} is not inside a Unity project: missing {version_file}"
34
+ f"{project_path / MANIFEST_FILENAME} is not inside a Unity project: missing {PROJECT_MARKER}"
32
35
  )
36
+
37
+ manifest_path = project_path / MANIFEST_FILENAME
38
+ if manifest_path.exists():
39
+ manifest = UnityBuildManifest(**json.loads(manifest_path.read_text()))
40
+ else:
41
+ manifest = UnityBuildManifest()
42
+
43
+ name = project_path.name
33
44
  if name in projects:
34
45
  raise SystemExit(f"Duplicate Unity project name '{name}': {projects[name].path} and {project_path}")
35
-
36
- manifest = UnityBuildManifest(**json.loads((project_path / MANIFEST_FILENAME).read_text()))
37
46
  projects[name] = UnityProject(path=project_path, **manifest.model_dump())
38
47
 
39
48
  if not projects:
40
- raise SystemExit(f"No {MANIFEST_FILENAME} manifests found under {Path.cwd()} — run from the repo root")
41
-
49
+ raise SystemExit(
50
+ f"No Unity projects found under {root} — a project is a directory containing {PROJECT_MARKER}. Run from the repo root"
51
+ )
42
52
  return projects
43
53
 
44
54
 
45
- def directories_containing(root: Path, filename: str) -> list[Path]:
46
- directories: list[Path] = []
47
- for directory, subdirectories, filenames in os.walk(root):
55
+ def visible_directories(root: Path) -> Iterator[Path]:
56
+ for directory, subdirectories, _filenames in os.walk(root):
48
57
  subdirectories[:] = sorted(
49
58
  name for name in subdirectories if name not in PRUNE_DIRECTORIES and not name.startswith(".")
50
59
  )
51
- if filename in filenames:
52
- directories.append(Path(directory))
53
- return directories
60
+ yield Path(directory)
61
+
62
+
63
+ def unity_project_directories(root: Path) -> list[Path]:
64
+ return [directory for directory in visible_directories(root) if (directory / PROJECT_MARKER).is_file()]
65
+
66
+
67
+ def directories_containing(root: Path, filename: str) -> list[Path]:
68
+ return [directory for directory in visible_directories(root) if (directory / filename).is_file()]
@@ -13,7 +13,9 @@ app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
13
13
 
14
14
  @app.command()
15
15
  def main(
16
- project: Annotated[str, typer.Option(help="Unity project name (directory containing unity-build.json)")],
16
+ project: Annotated[
17
+ str, typer.Option(help="Unity project name (directory containing ProjectSettings/ProjectVersion.txt)")
18
+ ],
17
19
  test_platform: Annotated[str, typer.Option(help="Unity test platform (EditMode or PlayMode)")] = "EditMode",
18
20
  results: Annotated[Path, typer.Option(help="Output path for NUnit XML results")] = Path(
19
21
  "artifacts/unity-test-results.xml"
unity_devkit/unity.py CHANGED
@@ -141,13 +141,18 @@ def resolve_unity_build(project: str, build: str) -> tuple[UnityProject, str, st
141
141
 
142
142
  project_config = projects[project]
143
143
  valid_builds = project_config.builds or []
144
+ if not valid_builds:
145
+ raise SystemExit(
146
+ f"Project '{project}' declares no builds — add a unity-build.json with a 'builds' list to {project_config.path}"
147
+ )
144
148
  if build not in valid_builds:
145
- valid = ", ".join(valid_builds) or "(none defined)"
146
- raise SystemExit(f"Unknown build '{build}' for project '{project}'. Valid: {valid}")
149
+ raise SystemExit(f"Unknown build '{build}' for project '{project}'. Valid: {', '.join(valid_builds)}")
147
150
 
148
151
  execute_method = (project_config.execute_methods or {}).get(build)
149
152
  if not execute_method:
150
- raise SystemExit(f"No execute method for project '{project}' build '{build}'")
153
+ raise SystemExit(
154
+ f"No execute method for '{build}' — declare 'execute_methods' in {project_config.path / 'unity-build.json'}"
155
+ )
151
156
 
152
157
  if build not in PLATFORM_CONFIGS:
153
158
  raise SystemExit(f"No platform config for build '{build}'. Valid: {', '.join(PLATFORM_CONFIGS)}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: unity-devkit
3
- Version: 0.1.9
3
+ Version: 0.1.11
4
4
  Summary: Unity project discovery, build, license, and CI tooling
5
5
  License-File: LICENSE
6
6
  License-File: NOTICE
@@ -0,0 +1,18 @@
1
+ unity_devkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ unity_devkit/build_unity.py,sha256=2DWbaI8UROzGS_iKa-mXjD7jzNxPNyQvHSa6F_2t-c0,4197
3
+ unity_devkit/compile_unity.py,sha256=PgLiHLiaFFXAuFsu2NLjVSJcvs_QFUyiHVp47nFDwdY,1821
4
+ unity_devkit/install.py,sha256=k0AXeFt-B1yj-Aq5vgvcol9X1KnNa3x74tQNjV1-XSc,6961
5
+ unity_devkit/license.py,sha256=iiMdos8kMk4p5uYYroIWUzxvusXtcMRdPkIDXsYTC9c,1484
6
+ unity_devkit/license_restore.py,sha256=Tbt2Kt1axszqj4H6K5Fx9_nqRL-dpL5XTVnxnmP4PZw,1077
7
+ unity_devkit/lock_unity.py,sha256=9UNMTj5ekFqqyXpRZ4fSru6SeyTda23jqtJ48rb0HOs,1009
8
+ unity_devkit/matrix.py,sha256=fveZkT7O2Q9UD9SW4fL59X6dTfk87RswWLuIs9NwKUM,1343
9
+ unity_devkit/projects.py,sha256=4JJimKo6-GB0EhhVddO-DbbYfNYPKRJfMFbw8_ZgpQY,2577
10
+ unity_devkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ unity_devkit/test_unity.py,sha256=DaWItN6CqEaPHJRg8fkGTVx9whZt-rLzR1pY9Qhj9DE,1100
12
+ unity_devkit/unity.py,sha256=KtWxy9P6E_56DjQcB_84qDx7EpN6ax2o3HIjYtLlOOY,6717
13
+ unity_devkit-0.1.11.dist-info/METADATA,sha256=LrSUAwksVfkdnuoS449iJDc-SZXwX-X-V7NDDg2OBlQ,352
14
+ unity_devkit-0.1.11.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
15
+ unity_devkit-0.1.11.dist-info/entry_points.txt,sha256=RKjFLiz02NSodLcgVDp8pnYX6zEa7VhrH_1GXnnt9d8,381
16
+ unity_devkit-0.1.11.dist-info/licenses/LICENSE,sha256=RFhQPdSOiMTguUX7JSoIuTxA7HVzCbj_p8WU36HjUQQ,10947
17
+ unity_devkit-0.1.11.dist-info/licenses/NOTICE,sha256=jvglZza3GCdN7v4_TLuXUqX9C_uABlwAKUkcIeKwk_8,26
18
+ unity_devkit-0.1.11.dist-info/RECORD,,
@@ -1,18 +0,0 @@
1
- unity_devkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- unity_devkit/build_unity.py,sha256=2DWbaI8UROzGS_iKa-mXjD7jzNxPNyQvHSa6F_2t-c0,4197
3
- unity_devkit/compile_unity.py,sha256=bSXLwuvMmgT9Uc5l8UTjVJvgYPiEpwFaOFL6iyems8k,1789
4
- unity_devkit/install.py,sha256=k0AXeFt-B1yj-Aq5vgvcol9X1KnNa3x74tQNjV1-XSc,6961
5
- unity_devkit/license.py,sha256=iiMdos8kMk4p5uYYroIWUzxvusXtcMRdPkIDXsYTC9c,1484
6
- unity_devkit/license_restore.py,sha256=Tbt2Kt1axszqj4H6K5Fx9_nqRL-dpL5XTVnxnmP4PZw,1077
7
- unity_devkit/lock_unity.py,sha256=9UNMTj5ekFqqyXpRZ4fSru6SeyTda23jqtJ48rb0HOs,1009
8
- unity_devkit/matrix.py,sha256=wb8hkEx6f8wnoEjSZszM9lpPofh5a5LspCTtsKqKKQ0,1158
9
- unity_devkit/projects.py,sha256=pWk6klQJ5_cdT8gcwQTkB1dK7y7UuNTk5NHYUCLvBuI,1941
10
- unity_devkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- unity_devkit/test_unity.py,sha256=Zdr-e2Qx_OgC1huAT_ZgL_YgKnu4FjCRJEhTW7pXMyQ,1068
12
- unity_devkit/unity.py,sha256=tTxpP4Dq_ThiL4Z6nEyeLdPMI0V8IBLVG_o1tkq1hjE,6499
13
- unity_devkit-0.1.9.dist-info/METADATA,sha256=gpjUxK9zj905H5aDg1apuUfesOp68hBgCIai21NADjU,351
14
- unity_devkit-0.1.9.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
15
- unity_devkit-0.1.9.dist-info/entry_points.txt,sha256=RKjFLiz02NSodLcgVDp8pnYX6zEa7VhrH_1GXnnt9d8,381
16
- unity_devkit-0.1.9.dist-info/licenses/LICENSE,sha256=RFhQPdSOiMTguUX7JSoIuTxA7HVzCbj_p8WU36HjUQQ,10947
17
- unity_devkit-0.1.9.dist-info/licenses/NOTICE,sha256=jvglZza3GCdN7v4_TLuXUqX9C_uABlwAKUkcIeKwk_8,26
18
- unity_devkit-0.1.9.dist-info/RECORD,,