| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent bcc0916 commit 7725b14
55 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -66,11 +66,10 @@ where = ["src"] | |||
| 66 | 66 | [tool.setuptools] | |
| 67 | 67 | license-files = ["LICENSE*"] | |
| 68 | 68 | ||
| 69 | - # Ensure template zip files are bundled with the wheel so the CLI can run offline. | ||
| 70 | - [tool.setuptools.data-files] | ||
| 71 | - "pythonnative/templates" = [ | ||
| 72 | - "templates/android_template.zip", | ||
| 73 | - "templates/ios_template.zip", | ||
| 69 | + # Include template directories inside the package so importlib.resources can find them | ||
| 70 | + [tool.setuptools.package-data] | ||
| 71 | + pythonnative = [ | ||
| 72 | + "templates/**", | ||
| 74 | 73 | ] | |
| 75 | 74 | ||
| 76 | 75 | [tool.ruff] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,7 +7,6 @@ | |||
| 7 | 7 | import sys | |
| 8 | 8 | import sysconfig | |
| 9 | 9 | import urllib.request | |
| 10 | - import zipfile | ||
| 11 | 10 | from importlib import resources | |
| 12 | 11 | from typing import Any, Dict, List, Optional | |
| 13 | 12 | ||
@@ -97,65 +96,66 @@ def bootstrap(native_instance): | |||
| 97 | 96 | print("Initialized PythonNative project.") | |
| 98 | 97 | ||
| 99 | 98 | ||
| 100 | - def _extract_zip_to_destination(zip_path: str, destination: str) -> None: | ||
| 101 | - with zipfile.ZipFile(zip_path, "r") as zf: | ||
| 102 | - zf.extractall(destination) | ||
| 99 | + def _copy_dir(src: str, dst: str) -> None: | ||
| 100 | + os.makedirs(os.path.dirname(dst), exist_ok=True) | ||
| 101 | + shutil.copytree(src, dst, dirs_exist_ok=True) | ||
| 103 | 102 | ||
| 104 | 103 | ||
| 105 | - def _extract_bundled_template(zip_name: str, destination: str) -> None: | ||
| 104 | + def _copy_bundled_template_dir(template_dir: str, destination: str) -> None: | ||
| 106 | 105 | """ | |
| 107 | - Extract a bundled template zip into the destination directory. | ||
| 108 | - Tries package resources first; falls back to repo root `templates/` at dev time. | ||
| 106 | + Copy a bundled template directory into the destination directory. | ||
| 107 | + Tries the repository `templates/` first during development, then | ||
| 108 | + package resources when installed from a wheel. | ||
| 109 | + The result should be `${destination}/{template_dir}`. | ||
| 109 | 110 | """ | |
| 110 | - # Dev-first: prefer repository templates if running from a checkout (avoid stale packaged zips) | ||
| 111 | + dest_path = os.path.join(destination, template_dir) | ||
| 112 | + | ||
| 113 | + # Dev-first: prefer local source templates if running from a checkout (avoid stale packaged data) | ||
| 111 | 114 | try: | |
| 112 | 115 | # __file__ -> src/pythonnative/cli/pn.py, so go up to src/, then to repo root | |
| 113 | 116 | src_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) | |
| 117 | + # Check templates located inside the source package tree | ||
| 118 | + local_pkg_templates = os.path.join(src_dir, "pythonnative", "templates", template_dir) | ||
| 119 | + if os.path.isdir(local_pkg_templates): | ||
| 120 | + _copy_dir(local_pkg_templates, dest_path) | ||
| 121 | + return | ||
| 114 | 122 | repo_root = os.path.abspath(os.path.join(src_dir, "..")) | |
| 115 | 123 | repo_templates = os.path.join(repo_root, "templates") | |
| 116 | - candidate = os.path.join(repo_templates, zip_name) | ||
| 117 | - if os.path.exists(candidate): | ||
| 118 | - _extract_zip_to_destination(candidate, destination) | ||
| 124 | + candidate_dir = os.path.join(repo_templates, template_dir) | ||
| 125 | + if os.path.isdir(candidate_dir): | ||
| 126 | + _copy_dir(candidate_dir, dest_path) | ||
| 119 | 127 | return | |
| 120 | 128 | except Exception: | |
| 121 | 129 | pass | |
| 122 | 130 | ||
| 123 | - # Try to load from installed package resources next (if templates are packaged inside the module) | ||
| 131 | + # Try to load from installed package resources (templates packaged inside the module) | ||
| 124 | 132 | try: | |
| 125 | - cand = resources.files("pythonnative").joinpath("templates").joinpath(zip_name) | ||
| 133 | + cand = resources.files("pythonnative").joinpath("templates").joinpath(template_dir) | ||
| 126 | 134 | with resources.as_file(cand) as p: | |
| 127 | 135 | resource_path = str(p) | |
| 128 | - if os.path.exists(resource_path): | ||
| 129 | - _extract_zip_to_destination(resource_path, destination) | ||
| 130 | - return | ||
| 131 | - except Exception: | ||
| 132 | - # Not packaged inside the module; try data-files installation locations next | ||
| 133 | - pass | ||
| 134 | - | ||
| 135 | - # Try sysconfig data dir (where data-files are typically installed) | ||
| 136 | - try: | ||
| 137 | - data_dir = sysconfig.get_paths().get("data") | ||
| 138 | - if data_dir: | ||
| 139 | - candidate = os.path.join(data_dir, "pythonnative", "templates", zip_name) | ||
| 140 | - if os.path.exists(candidate): | ||
| 141 | - _extract_zip_to_destination(candidate, destination) | ||
| 136 | + if os.path.isdir(resource_path): | ||
| 137 | + _copy_dir(resource_path, dest_path) | ||
| 142 | 138 | return | |
| 143 | 139 | except Exception: | |
| 144 | 140 | pass | |
| 145 | 141 | ||
| 146 | - # Try site-packages purelib/platlib (some environments place data files here) | ||
| 142 | + # Last resort: check typical data-file locations | ||
| 147 | 143 | try: | |
| 148 | - purelib = sysconfig.get_paths().get("purelib") | ||
| 149 | - platlib = sysconfig.get_paths().get("platlib") | ||
| 150 | - for base in filter(None, [purelib, platlib]): | ||
| 151 | - candidate = os.path.join(base, "pythonnative", "templates", zip_name) | ||
| 152 | - if os.path.exists(candidate): | ||
| 153 | - _extract_zip_to_destination(candidate, destination) | ||
| 144 | + data_paths = sysconfig.get_paths() | ||
| 145 | + search_bases = [ | ||
| 146 | + data_paths.get("data"), | ||
| 147 | + data_paths.get("purelib"), | ||
| 148 | + data_paths.get("platlib"), | ||
| 149 | + ] | ||
| 150 | + for base in filter(None, search_bases): | ||
| 151 | + candidate_dir = os.path.join(base, "pythonnative", "templates", template_dir) | ||
| 152 | + if os.path.isdir(candidate_dir): | ||
| 153 | + _copy_dir(candidate_dir, dest_path) | ||
| 154 | 154 | return | |
| 155 | 155 | except Exception: | |
| 156 | 156 | pass | |
| 157 | 157 | ||
| 158 | - raise FileNotFoundError(f"Could not find bundled template {zip_name}. Ensure templates are packaged.") | ||
| 158 | + raise FileNotFoundError(f"Could not find bundled template directory {template_dir}. Ensure templates are packaged.") | ||
| 159 | 159 | ||
| 160 | 160 | ||
| 161 | 161 | def _github_json(url: str) -> Any: | |
@@ -199,8 +199,8 @@ def create_android_project(project_name: str, destination: str) -> None: | |||
| 199 | 199 | :param project_name: The name of the project. | |
| 200 | 200 | :param destination: The directory where the project will be created. | |
| 201 | 201 | """ | |
| 202 | - # Extract the Android template project from bundled zip | ||
| 203 | - _extract_bundled_template("android_template.zip", destination) | ||
| 202 | + # Copy the Android template project directory | ||
| 203 | + _copy_bundled_template_dir("android_template", destination) | ||
| 204 | 204 | ||
| 205 | 205 | ||
| 206 | 206 | def create_ios_project(project_name: str, destination: str) -> None: | |
@@ -210,8 +210,8 @@ def create_ios_project(project_name: str, destination: str) -> None: | |||
| 210 | 210 | :param project_name: The name of the project. | |
| 211 | 211 | :param destination: The directory where the project will be created. | |
| 212 | 212 | """ | |
| 213 | - # Extract the iOS template project from bundled zip | ||
| 214 | - _extract_bundled_template("ios_template.zip", destination) | ||
| 213 | + # Copy the iOS template project directory | ||
| 214 | + _copy_bundled_template_dir("ios_template", destination) | ||
| 215 | 215 | ||
| 216 | 216 | ||
| 217 | 217 | def run_project(args: argparse.Namespace) -> None: | |
| Back | FazBrowse Home | New Git URL |
0 commit comments