FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pythonnative/src/pythonnative/utils.py at docs/fix-navigation-examples · crux200/pythonnative · GitHub
crux200
pythonnative
Repository navigation
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
pythonnative
/
src
/
pythonnative
/
utils.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
220 lines (171 loc) · 7.42 KB
Breadcrumbs
pythonnative
/
src
/
pythonnative
/
utils.py
Copy path
File metadata and controls
220 lines (171 loc) · 7.42 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
"""Platform detection and shared helpers.
This module is imported early by most other modules, so it avoids
importing platform-specific packages at module level. The detection
results are cached the first time
[`IS_ANDROID`][pythonnative.utils.IS_ANDROID] and
[`IS_IOS`][pythonnative.utils.IS_IOS] are read.
The Android variants also expose a small global registry for the
current `Activity` / `Context` and the screen's fragment container view;
both are populated by the bundled Android template before any
PythonNative code runs.
Attributes:
IS_ANDROID: `True` when running inside an Android process (either
because `ANDROID_*` env vars are present or because Chaquopy's
`java` module imports successfully).
IS_IOS: `True` when running inside an iOS app bundle (signaled by
`PN_PLATFORM=ios`, `sys.platform == "ios"`, or a Simulator
`HOME` path). Importing `rubicon-objc` alone is intentionally
not enough to trigger this flag.
IS_DESKTOP: `True` when running the desktop preview backend
(signaled by `PN_PLATFORM=desktop`, set by ``pn preview``).
This drives the Tkinter native-view registry so a PythonNative
app can render in a real OS window for fast local iteration.
"""
import
os
import
sys
from
typing
import
Any
,
Optional
# ======================================================================
# Platform detection
# ======================================================================
_is_android
:
Optional
[
bool
]
=
None
_is_ios
:
Optional
[
bool
]
=
None
_is_desktop
:
Optional
[
bool
]
=
None
def
_detect_android
()
->
bool
:
"""Return whether we're running inside an Android process."""
env
=
os
.
environ
if
"ANDROID_BOOTLOGO"
in
env
or
"ANDROID_ROOT"
in
env
or
"ANDROID_DATA"
in
env
or
"ANDROID_ARGUMENT"
in
env
:
return
True
try
:
from
java
import
jclass
# noqa: F401
return
True
except
Exception
:
pass
return
False
def
_detect_ios
()
->
bool
:
"""Detect whether we're running inside an iOS app bundle.
Signals, in priority order:
- Explicit `PN_PLATFORM=ios` env var (set by the iOS template's
`ViewController.swift` before Python starts). This is the
canonical signal and survives even on hosts where `sys.platform`
is generic `darwin`.
- `sys.platform == "ios"` (CPython 3.13+ native iOS builds).
- `/CoreSimulator/Devices/` in `$HOME` (iOS Simulator fallback if
the template signal is missing for some reason).
Crucially, having `rubicon-objc` importable is *not* enough:
developers frequently install it on macOS via the `[ios]` extra,
and treating that as iOS would cause subtle side effects
(e.g., stdout redirection) on desktop machines.
"""
if
os
.
environ
.
get
(
"PN_PLATFORM"
)
==
"ios"
:
return
True
if
sys
.
platform
==
"ios"
:
return
True
home
=
os
.
environ
.
get
(
"HOME"
,
""
)
if
"/CoreSimulator/Devices/"
in
home
:
return
True
return
False
def
_detect_desktop
()
->
bool
:
"""Detect whether we're running the desktop (Tkinter) preview backend.
The only signal is the explicit ``PN_PLATFORM=desktop`` env var,
set by ``pn preview`` before importing PythonNative. Desktop is a
*development* target: it renders the app in a native OS window via
the pure-Python Tkinter registry so the inner dev loop doesn't
require a device build. Off-device unit tests deliberately leave
this flag ``False`` so they keep using an injected mock registry
and ``Platform.OS == "test"``.
"""
return
os
.
environ
.
get
(
"PN_PLATFORM"
)
==
"desktop"
def
_ensure_platform_detection
()
->
None
:
"""Populate `_is_android` / `_is_ios` / `_is_desktop` once, then reuse."""
global
_is_android
,
_is_ios
,
_is_desktop
if
_is_android
is
None
:
_is_android
=
_detect_android
()
if
_is_ios
is
None
:
_is_ios
=
(
not
_is_android
)
and
_detect_ios
()
if
_is_desktop
is
None
:
_is_desktop
=
(
not
_is_android
)
and
(
not
_is_ios
)
and
_detect_desktop
()
def
_get_is_android
()
->
bool
:
"""Return the cached Android-detection result."""
_ensure_platform_detection
()
assert
_is_android
is
not
None
return
_is_android
def
_get_is_ios
()
->
bool
:
"""Return the cached iOS-detection result."""
_ensure_platform_detection
()
assert
_is_ios
is
not
None
return
_is_ios
def
_get_is_desktop
()
->
bool
:
"""Return the cached desktop-detection result."""
_ensure_platform_detection
()
assert
_is_desktop
is
not
None
return
_is_desktop
IS_ANDROID
:
bool
=
_get_is_android
()
"""``True`` when running inside an Android process.
The flag is computed once at import time, by checking for `ANDROID_*`
environment variables and trying to import Chaquopy's `java` module.
"""
IS_IOS
:
bool
=
_get_is_ios
()
"""``True`` when running inside an iOS app bundle.
The flag is computed once at import time, by checking
`PN_PLATFORM=ios`, `sys.platform == "ios"`, and the iOS Simulator
`HOME` path.
"""
IS_DESKTOP
:
bool
=
_get_is_desktop
()
"""``True`` when running the desktop (Tkinter) preview backend.
Set by ``pn preview`` via ``PN_PLATFORM=desktop``. Mutually exclusive
with `IS_ANDROID` / `IS_IOS`. Off-device unit tests leave this
``False`` and inject a mock registry instead.
"""
# ======================================================================
# Android context management
# ======================================================================
_android_context
:
Any
=
None
_android_fragment_container
:
Any
=
None
def
set_android_context
(
context
:
Any
)
->
None
:
"""Record the current Android `Activity`/`Context`.
Called by the bundled Android template before any view is created;
most app code should not call this directly.
Args:
context: A Java `android.content.Context` (typically the
current `Activity`).
"""
global
_android_context
_android_context
=
context
def
set_android_fragment_container
(
container_view
:
Any
)
->
None
:
"""Record the current `Fragment` root container `ViewGroup`.
Args:
container_view: A Java `android.view.ViewGroup` that holds the
screen's view tree.
"""
global
_android_fragment_container
_android_fragment_container
=
container_view
def
get_android_context
()
->
Any
:
"""Return the current Android `Activity`/`Context`.
Returns:
The most recently recorded Android context.
Raises:
RuntimeError: If called on a non-Android platform, or before
the template has registered a context.
"""
if
not
IS_ANDROID
:
raise
RuntimeError
(
"get_android_context() called on non-Android platform"
)
if
_android_context
is
None
:
raise
RuntimeError
(
"Android context not set. Ensure the screen host is initialized from an Activity before constructing views."
)
return
_android_context
def
get_android_fragment_container
()
->
Any
:
"""Return the current `Fragment` container `ViewGroup`.
Returns:
The most recently recorded fragment container view.
Raises:
RuntimeError: If called on a non-Android platform, or before
`ScreenFragment` has registered its container.
"""
if
not
IS_ANDROID
:
raise
RuntimeError
(
"get_android_fragment_container() called on non-Android platform"
)
if
_android_fragment_container
is
None
:
raise
RuntimeError
(
"Android fragment container not set. Ensure ScreenFragment has been created before set_root_view."
)
return
_android_fragment_container
Back
|
FazBrowse Home
|
New Git URL