pythonnative 0.37.0__py3-none-any.whl → 0.38.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.
- pythonnative/__init__.py +9 -1
- pythonnative/alerts.py +6 -14
- pythonnative/cli/pn.py +96 -10
- pythonnative/components/_base.py +31 -0
- pythonnative/components/controls.py +19 -16
- pythonnative/components/layout.py +5 -8
- pythonnative/components/lists.py +6 -6
- pythonnative/gestures.py +27 -6
- pythonnative/native_modules/__init__.py +19 -0
- pythonnative/native_modules/battery.py +13 -14
- pythonnative/native_modules/biometrics.py +12 -14
- pythonnative/native_modules/camera.py +10 -6
- pythonnative/native_modules/clipboard.py +9 -11
- pythonnative/native_modules/file_system.py +81 -172
- pythonnative/native_modules/haptics.py +14 -10
- pythonnative/native_modules/linking.py +9 -8
- pythonnative/native_modules/location.py +10 -12
- pythonnative/native_modules/net_info.py +1 -4
- pythonnative/native_modules/notifications.py +25 -32
- pythonnative/native_modules/permissions.py +70 -22
- pythonnative/native_modules/secure_store.py +16 -20
- pythonnative/native_modules/share.py +5 -5
- pythonnative/navigation/__init__.py +2 -1
- pythonnative/navigation/hooks.py +46 -7
- pythonnative/navigation/state.py +30 -9
- pythonnative/project/android.py +23 -0
- pythonnative/project/builder.py +64 -35
- pythonnative/project/config.py +84 -24
- pythonnative/project/deps.py +703 -0
- pythonnative/project/doctor.py +53 -4
- pythonnative/project/runtime_assets.py +13 -14
- pythonnative/style.py +94 -44
- pythonnative/templates/android_template/app/build.gradle +5 -2
- pythonnative/templates/android_template/build.gradle +7 -4
- pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +1 -1
- pythonnative/templates/android_template/pythonnative/src/main/java/com/pythonnative/runtime/modules/PermissionsModule.kt +15 -4
- pythonnative/templates/ios_template/PythonNativeKit/Sources/PythonNativeKit/Modules/PermissionModules.swift +25 -10
- pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +3 -2
- pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +35 -9
- pythonnative/utils.py +22 -27
- pythonnative/virtual_rows.py +10 -20
- {pythonnative-0.37.0.dist-info → pythonnative-0.38.0.dist-info}/METADATA +8 -8
- {pythonnative-0.37.0.dist-info → pythonnative-0.38.0.dist-info}/RECORD +47 -46
- {pythonnative-0.37.0.dist-info → pythonnative-0.38.0.dist-info}/WHEEL +0 -0
- {pythonnative-0.37.0.dist-info → pythonnative-0.38.0.dist-info}/entry_points.txt +0 -0
- {pythonnative-0.37.0.dist-info → pythonnative-0.38.0.dist-info}/licenses/LICENSE +0 -0
- {pythonnative-0.37.0.dist-info → pythonnative-0.38.0.dist-info}/top_level.txt +0 -0
pythonnative/project/config.py
CHANGED
|
@@ -18,7 +18,7 @@ name = "myapp" # short project name (required)
|
|
|
18
18
|
display_name = "My App" # home-screen label (defaults to name)
|
|
19
19
|
version = "1.0.0" # marketing version
|
|
20
20
|
build = 1 # integer build number
|
|
21
|
-
python_version = "3.
|
|
21
|
+
python_version = "3.13" # embedded CPython version (3.13 or 3.14)
|
|
22
22
|
orientation = "portrait" # portrait | landscape | all
|
|
23
23
|
entry_point = "app/main.py" # module whose `App` is mounted
|
|
24
24
|
url_schemes = ["myapp"] # custom deep-link URL schemes
|
|
@@ -33,6 +33,9 @@ splash = "assets/splash.png" # splash/launch image
|
|
|
33
33
|
|
|
34
34
|
[requirements]
|
|
35
35
|
packages = ["humanize", "httpx"]
|
|
36
|
+
# Extra package indexes searched after PyPI and the platform wheel
|
|
37
|
+
# repositories (BeeWare for iOS, Chaquopy for Android).
|
|
38
|
+
extra_index_urls = ["https://wheels.example.com/simple"]
|
|
36
39
|
|
|
37
40
|
[plugins]
|
|
38
41
|
paths = ["native/my_plugin"] # local native plugins (pn_plugin.json + ios/ + android/)
|
|
@@ -49,7 +52,7 @@ provisioning_profile = "My App Distribution"
|
|
|
49
52
|
[android]
|
|
50
53
|
min_sdk = 24
|
|
51
54
|
target_sdk = 34
|
|
52
|
-
abi_filters = ["arm64-v8a", "x86_64"] # the default
|
|
55
|
+
abi_filters = ["arm64-v8a", "x86_64"] # the default and the full set (64-bit only)
|
|
53
56
|
|
|
54
57
|
[android.signing]
|
|
55
58
|
keystore = "release.keystore"
|
|
@@ -60,32 +63,62 @@ key_alias = "myapp"
|
|
|
60
63
|
from __future__ import annotations
|
|
61
64
|
|
|
62
65
|
import re
|
|
66
|
+
import tomllib as _toml
|
|
63
67
|
from dataclasses import dataclass, field
|
|
64
68
|
from pathlib import Path
|
|
65
69
|
from typing import Any, Dict, List, Mapping, Optional
|
|
66
70
|
|
|
67
71
|
from . import permissions as _permissions
|
|
68
72
|
|
|
69
|
-
try: # Python 3.11+
|
|
70
|
-
import tomllib as _toml
|
|
71
|
-
except ModuleNotFoundError: # Python 3.10
|
|
72
|
-
import tomli as _toml
|
|
73
|
-
|
|
74
|
-
|
|
75
73
|
CONFIG_FILENAME = "pythonnative.toml"
|
|
76
74
|
"""The fixed config filename looked up at the project root."""
|
|
77
75
|
|
|
78
|
-
SUPPORTED_PYTHON_VERSIONS = ("3.
|
|
76
|
+
SUPPORTED_PYTHON_VERSIONS = ("3.13", "3.14")
|
|
79
77
|
"""CPython versions accepted in ``app.python_version``.
|
|
80
78
|
|
|
81
79
|
Every listed version has a pinned, checksum-verified iOS runtime (see
|
|
82
80
|
``runtime_assets.PINNED_ASSETS``) and is supported by Chaquopy on
|
|
83
|
-
Android.
|
|
81
|
+
Android. The floor is 3.13 because that is the first CPython with
|
|
82
|
+
official iOS (PEP 730) and Android (PEP 738) platform support, which is
|
|
83
|
+
what lets binary wheels from PyPI install on both platforms.
|
|
84
84
|
"""
|
|
85
85
|
|
|
86
|
+
DEFAULT_PYTHON_VERSION = "3.13"
|
|
87
|
+
"""The ``app.python_version`` used when the config leaves it out.
|
|
88
|
+
|
|
89
|
+
3.13 rather than 3.14 because binary wheel coverage (BeeWare's iOS
|
|
90
|
+
index, Chaquopy's Android index, PyPI itself) is far wider for 3.13.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
_URL_RE = re.compile(r"^https?://\S+$")
|
|
94
|
+
|
|
86
95
|
VALID_ORIENTATIONS = ("portrait", "landscape", "all")
|
|
87
96
|
"""Accepted values for ``app.orientation``."""
|
|
88
97
|
|
|
98
|
+
MIN_IOS_DEPLOYMENT_TARGET = "13.0"
|
|
99
|
+
"""Lowest ``[ios].deployment_target`` accepted.
|
|
100
|
+
|
|
101
|
+
BeeWare's CPython builds and every iOS wheel on PyPI target iOS 13.0
|
|
102
|
+
(the ``ios_13_0_*`` platform tags), so lower values can't be satisfied.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
MIN_ANDROID_SDK = 24
|
|
106
|
+
"""Lowest ``[android].min_sdk`` accepted (Chaquopy 17 requirement)."""
|
|
107
|
+
|
|
108
|
+
VALID_ANDROID_ABIS = ("arm64-v8a", "x86_64")
|
|
109
|
+
"""Android ABIs the embedded runtime supports.
|
|
110
|
+
|
|
111
|
+
CPython 3.12+ on Chaquopy ships 64-bit only, and PEP 738 Android wheels
|
|
112
|
+
on PyPI are published for these two ABIs.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
_IOS_VERSION_RE = re.compile(r"^\d+(\.\d+){1,2}$")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _version_tuple(version: str) -> tuple:
|
|
119
|
+
return tuple(int(part) for part in version.split("."))
|
|
120
|
+
|
|
121
|
+
|
|
89
122
|
VALID_IOS_EXPORT_METHODS = ("development", "ad-hoc", "app-store", "enterprise")
|
|
90
123
|
"""Accepted values for ``[ios.signing].export_method``."""
|
|
91
124
|
|
|
@@ -200,9 +233,9 @@ class AndroidConfig:
|
|
|
200
233
|
target_sdk: int = 34
|
|
201
234
|
compile_sdk: int = 34
|
|
202
235
|
application_id: Optional[str] = None
|
|
203
|
-
# arm64 devices plus x86_64 emulators
|
|
204
|
-
#
|
|
205
|
-
abi_filters: List[str] = field(default_factory=lambda:
|
|
236
|
+
# arm64 devices plus x86_64 emulators: the only ABIs CPython 3.12+
|
|
237
|
+
# on Chaquopy (and PEP 738 wheels on PyPI) are built for.
|
|
238
|
+
abi_filters: List[str] = field(default_factory=lambda: list(VALID_ANDROID_ABIS))
|
|
206
239
|
permissions: List[str] = field(default_factory=list)
|
|
207
240
|
signing: AndroidSigning = field(default_factory=AndroidSigning)
|
|
208
241
|
|
|
@@ -238,6 +271,9 @@ class AppConfig:
|
|
|
238
271
|
icon: Optional source icon path (``[assets].icon``).
|
|
239
272
|
splash: Optional splash image path (``[assets].splash``).
|
|
240
273
|
requirements: Third-party pip packages (``[requirements].packages``).
|
|
274
|
+
extra_index_urls: Additional package indexes
|
|
275
|
+
(``[requirements].extra_index_urls``) searched after PyPI and
|
|
276
|
+
the platform wheel repositories.
|
|
241
277
|
plugin_paths: Project-local native plugin directories
|
|
242
278
|
(``[plugins].paths``); installed packages contribute plugins
|
|
243
279
|
through the ``pythonnative.plugins`` entry point group instead.
|
|
@@ -252,7 +288,7 @@ class AppConfig:
|
|
|
252
288
|
display_name: str
|
|
253
289
|
version: str = "1.0.0"
|
|
254
290
|
build: int = 1
|
|
255
|
-
python_version: str =
|
|
291
|
+
python_version: str = DEFAULT_PYTHON_VERSION
|
|
256
292
|
orientation: str = "portrait"
|
|
257
293
|
entry_point: str = "app/main.py"
|
|
258
294
|
url_schemes: List[str] = field(default_factory=list)
|
|
@@ -260,6 +296,7 @@ class AppConfig:
|
|
|
260
296
|
icon: Optional[str] = None
|
|
261
297
|
splash: Optional[str] = None
|
|
262
298
|
requirements: List[str] = field(default_factory=list)
|
|
299
|
+
extra_index_urls: List[str] = field(default_factory=list)
|
|
263
300
|
plugin_paths: List[str] = field(default_factory=list)
|
|
264
301
|
ios: IOSConfig = field(default_factory=IOSConfig)
|
|
265
302
|
android: AndroidConfig = field(default_factory=AndroidConfig)
|
|
@@ -372,7 +409,7 @@ class AppConfig:
|
|
|
372
409
|
display_name=_opt_str(app, "display_name") or _require_str(app, "name", "app"),
|
|
373
410
|
version=_opt_str(app, "version") or "1.0.0",
|
|
374
411
|
build=_opt_int(app, "build", default=1),
|
|
375
|
-
python_version=_opt_str(app, "python_version") or
|
|
412
|
+
python_version=_opt_str(app, "python_version") or DEFAULT_PYTHON_VERSION,
|
|
376
413
|
orientation=(_opt_str(app, "orientation") or "portrait").lower(),
|
|
377
414
|
entry_point=_opt_str(app, "entry_point") or "app/main.py",
|
|
378
415
|
url_schemes=_opt_str_list(app, "url_schemes"),
|
|
@@ -388,6 +425,7 @@ class AppConfig:
|
|
|
388
425
|
|
|
389
426
|
requirements = _expect_table(data, "requirements", optional=True)
|
|
390
427
|
config.requirements = _opt_str_list(requirements, "packages")
|
|
428
|
+
config.extra_index_urls = _opt_str_list(requirements, "extra_index_urls")
|
|
391
429
|
|
|
392
430
|
plugins = _expect_table(data, "plugins", optional=True)
|
|
393
431
|
config.plugin_paths = _opt_str_list(plugins, "paths")
|
|
@@ -440,17 +478,36 @@ class AppConfig:
|
|
|
440
478
|
raise ConfigError("Unknown permission(s): " + ", ".join(unknown) + f".\nValid capabilities: {known}")
|
|
441
479
|
|
|
442
480
|
_validate_requirements(self.requirements)
|
|
481
|
+
for url in self.extra_index_urls:
|
|
482
|
+
if not _URL_RE.match(url):
|
|
483
|
+
raise ConfigError(
|
|
484
|
+
f"[requirements].extra_index_urls entry {url!r} is invalid; use a full http(s) URL "
|
|
485
|
+
"to a PEP 503 simple index (e.g. 'https://wheels.example.com/simple')."
|
|
486
|
+
)
|
|
443
487
|
|
|
444
488
|
if self.ios.signing.export_method not in VALID_IOS_EXPORT_METHODS:
|
|
445
489
|
valid = ", ".join(VALID_IOS_EXPORT_METHODS)
|
|
446
490
|
raise ConfigError(
|
|
447
491
|
f"[ios.signing].export_method {self.ios.signing.export_method!r} is invalid (choose one of: {valid})."
|
|
448
492
|
)
|
|
493
|
+
if not _IOS_VERSION_RE.match(self.ios.deployment_target):
|
|
494
|
+
raise ConfigError(
|
|
495
|
+
f"[ios].deployment_target {self.ios.deployment_target!r} must look like '13.0' or '16.4'."
|
|
496
|
+
)
|
|
497
|
+
if _version_tuple(self.ios.deployment_target) < _version_tuple(MIN_IOS_DEPLOYMENT_TARGET):
|
|
498
|
+
raise ConfigError(
|
|
499
|
+
f"[ios].deployment_target must be at least {MIN_IOS_DEPLOYMENT_TARGET} "
|
|
500
|
+
"(the embedded CPython runtime and iOS binary wheels target that floor)."
|
|
501
|
+
)
|
|
449
502
|
|
|
450
|
-
if self.android.min_sdk <
|
|
451
|
-
raise ConfigError("[android].min_sdk must be at least
|
|
503
|
+
if self.android.min_sdk < MIN_ANDROID_SDK:
|
|
504
|
+
raise ConfigError(f"[android].min_sdk must be at least {MIN_ANDROID_SDK} (Chaquopy requirement).")
|
|
452
505
|
if self.android.target_sdk < self.android.min_sdk:
|
|
453
506
|
raise ConfigError("[android].target_sdk must be >= min_sdk.")
|
|
507
|
+
for abi in self.android.abi_filters:
|
|
508
|
+
if abi not in VALID_ANDROID_ABIS:
|
|
509
|
+
valid = ", ".join(VALID_ANDROID_ABIS)
|
|
510
|
+
raise ConfigError(f"[android].abi_filters entry {abi!r} is invalid (choose from: {valid}).")
|
|
454
511
|
|
|
455
512
|
|
|
456
513
|
# ======================================================================
|
|
@@ -635,7 +692,7 @@ def _toml_escape(value: str) -> str:
|
|
|
635
692
|
return "".join(out)
|
|
636
693
|
|
|
637
694
|
|
|
638
|
-
def render_default_toml(*, name: str, app_id: str, python_version: str =
|
|
695
|
+
def render_default_toml(*, name: str, app_id: str, python_version: str = DEFAULT_PYTHON_VERSION) -> str:
|
|
639
696
|
"""Render a starter ``pythonnative.toml`` for ``pn init``.
|
|
640
697
|
|
|
641
698
|
Every interpolated value is escaped for a TOML basic string, so a
|
|
@@ -686,13 +743,16 @@ entry_point = "app/main.py"
|
|
|
686
743
|
# icon = "assets/icon.png"
|
|
687
744
|
# splash = "assets/splash.png"
|
|
688
745
|
|
|
689
|
-
# Third-party pip packages bundled into the app
|
|
690
|
-
#
|
|
746
|
+
# Third-party pip packages bundled into the app. Pure-Python packages
|
|
747
|
+
# always work; packages with C extensions need a wheel for each device
|
|
748
|
+
# platform. Run `pn deps` to see what resolves before you build.
|
|
749
|
+
# Do NOT list "pythonnative". Docs: https://pythonnative.com/guides/pypi-packages/
|
|
691
750
|
[requirements]
|
|
692
751
|
packages = []
|
|
752
|
+
# extra_index_urls = ["https://wheels.example.com/simple"]
|
|
693
753
|
|
|
694
754
|
[ios]
|
|
695
|
-
deployment_target = "
|
|
755
|
+
deployment_target = "{MIN_IOS_DEPLOYMENT_TARGET}"
|
|
696
756
|
# development_team = "ABCDE12345"
|
|
697
757
|
# bundle_id = "{app_id}"
|
|
698
758
|
|
|
@@ -701,10 +761,10 @@ export_method = "development" # development | ad-hoc | app-store | enterprise
|
|
|
701
761
|
# provisioning_profile = "My App Distribution"
|
|
702
762
|
|
|
703
763
|
[android]
|
|
704
|
-
min_sdk =
|
|
764
|
+
min_sdk = {MIN_ANDROID_SDK}
|
|
705
765
|
target_sdk = 34
|
|
706
|
-
# arm64 devices + x86_64 emulators
|
|
707
|
-
#
|
|
766
|
+
# arm64 devices + x86_64 emulators. These are the only ABIs the embedded
|
|
767
|
+
# CPython (3.12+) and Android wheels on PyPI ship for.
|
|
708
768
|
# abi_filters = ["arm64-v8a", "x86_64"]
|
|
709
769
|
|
|
710
770
|
[android.signing]
|