pythonnative 0.17.1__py3-none-any.whl → 0.19.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 CHANGED
@@ -51,7 +51,7 @@ Example:
51
51
  ```
52
52
  """
53
53
 
54
- __version__ = "0.17.1"
54
+ __version__ = "0.19.0"
55
55
 
56
56
  from . import runtime, sdk
57
57
  from .alerts import Alert
@@ -61,11 +61,17 @@ from .components import (
61
61
  ActivityIndicatorProps,
62
62
  Button,
63
63
  ButtonProps,
64
+ Checkbox,
65
+ CheckboxProps,
64
66
  Column,
67
+ DatePicker,
68
+ DatePickerProps,
65
69
  ErrorBoundary,
66
70
  FlatList,
67
71
  Fragment,
68
72
  Image,
73
+ ImageBackground,
74
+ ImageBackgroundProps,
69
75
  ImageProps,
70
76
  KeyboardAvoidingView,
71
77
  KeyboardAvoidingViewProps,
@@ -84,6 +90,8 @@ from .components import (
84
90
  ScrollView,
85
91
  ScrollViewProps,
86
92
  SectionList,
93
+ SegmentedControl,
94
+ SegmentedControlProps,
87
95
  Slider,
88
96
  SliderProps,
89
97
  Spacer,
@@ -96,6 +104,8 @@ from .components import (
96
104
  TextInput,
97
105
  TextInputProps,
98
106
  TextProps,
107
+ TouchableOpacity,
108
+ TouchableOpacityProps,
99
109
  View,
100
110
  ViewProps,
101
111
  WebView,
@@ -126,7 +136,25 @@ from .hooks import (
126
136
  use_state,
127
137
  use_window_dimensions,
128
138
  )
129
- from .native_modules import Camera, FileSystem, Location, Notifications
139
+ from .native_modules import (
140
+ AppState,
141
+ Battery,
142
+ Biometrics,
143
+ Camera,
144
+ Clipboard,
145
+ FileSystem,
146
+ Haptics,
147
+ Linking,
148
+ Location,
149
+ NetInfo,
150
+ Notifications,
151
+ Permissions,
152
+ SecureStore,
153
+ Share,
154
+ Vibration,
155
+ use_app_state,
156
+ use_net_info,
157
+ )
130
158
  from .navigation import (
131
159
  NavigationContainer,
132
160
  create_drawer_navigator,
@@ -178,11 +206,14 @@ __all__ = [
178
206
  # Components
179
207
  "ActivityIndicator",
180
208
  "Button",
209
+ "Checkbox",
181
210
  "Column",
211
+ "DatePicker",
182
212
  "ErrorBoundary",
183
213
  "FlatList",
184
214
  "Fragment",
185
215
  "Image",
216
+ "ImageBackground",
186
217
  "KeyboardAvoidingView",
187
218
  "Modal",
188
219
  "Picker",
@@ -193,17 +224,22 @@ __all__ = [
193
224
  "SafeAreaView",
194
225
  "ScrollView",
195
226
  "SectionList",
227
+ "SegmentedControl",
196
228
  "Slider",
197
229
  "Spacer",
198
230
  "StatusBar",
199
231
  "Switch",
200
232
  "Text",
201
233
  "TextInput",
234
+ "TouchableOpacity",
202
235
  "View",
203
236
  "WebView",
204
237
  # Built-in Props dataclasses
205
238
  "ActivityIndicatorProps",
206
239
  "ButtonProps",
240
+ "CheckboxProps",
241
+ "DatePickerProps",
242
+ "ImageBackgroundProps",
207
243
  "ImageProps",
208
244
  "KeyboardAvoidingViewProps",
209
245
  "ModalProps",
@@ -212,12 +248,14 @@ __all__ = [
212
248
  "ProgressBarProps",
213
249
  "SafeAreaViewProps",
214
250
  "ScrollViewProps",
251
+ "SegmentedControlProps",
215
252
  "SliderProps",
216
253
  "SpacerProps",
217
254
  "StatusBarProps",
218
255
  "SwitchProps",
219
256
  "TextInputProps",
220
257
  "TextProps",
258
+ "TouchableOpacityProps",
221
259
  "ViewProps",
222
260
  "WebViewProps",
223
261
  # Core
@@ -286,10 +324,23 @@ __all__ = [
286
324
  # Imperative
287
325
  "Alert",
288
326
  # Native modules
327
+ "AppState",
328
+ "Battery",
329
+ "Biometrics",
289
330
  "Camera",
331
+ "Clipboard",
290
332
  "FileSystem",
333
+ "Haptics",
334
+ "Linking",
291
335
  "Location",
336
+ "NetInfo",
292
337
  "Notifications",
338
+ "Permissions",
339
+ "SecureStore",
340
+ "Share",
341
+ "Vibration",
342
+ "use_app_state",
343
+ "use_net_info",
293
344
  # Networking + persistence
294
345
  "AsyncStorage",
295
346
  "fetch",
pythonnative/cli/pn.py CHANGED
@@ -1,9 +1,12 @@
1
1
  """`pn` CLI: scaffold, run, and clean PythonNative projects.
2
2
 
3
3
  The console script `pn` (declared in `pyproject.toml` under
4
- `[project.scripts]`) dispatches to one of three subcommands:
4
+ `[project.scripts]`) dispatches to one of four subcommands:
5
5
 
6
6
  - `pn init [name]`: scaffold a new project in the current directory.
7
+ - `pn preview [component]`: render the app in a desktop (Tkinter)
8
+ window with instant Fast Refresh — the fast inner dev loop, no
9
+ device or simulator required.
7
10
  - `pn run android|ios`: stage code into a native template, build it,
8
11
  install it, and stream logs back to the terminal.
9
12
  - `pn clean`: remove the local `build/` directory.
@@ -1119,6 +1122,90 @@ def _run_hot_reload(platform: str, project_dir: str, build_dir: str, show_logs:
1119
1122
  print("\n[hot-reload] Stopped.")
1120
1123
 
1121
1124
 
1125
+ def _entrypoint_to_module(entry_point: str) -> str:
1126
+ """Convert a config ``entryPoint`` path into an importable module path.
1127
+
1128
+ ``"app/main.py"`` → ``"app.main"``. Returns ``"app.main"`` for
1129
+ empty / unusable input so ``pn preview`` always has a sane default.
1130
+ """
1131
+ normalized = entry_point.strip().replace("\\", "/")
1132
+ if normalized.endswith(".py"):
1133
+ normalized = normalized[:-3]
1134
+ normalized = normalized.strip("/").replace("/", ".")
1135
+ return normalized or "app.main"
1136
+
1137
+
1138
+ def preview_project(args: argparse.Namespace) -> None:
1139
+ """Render the project in a desktop preview window (Tkinter).
1140
+
1141
+ Sets ``PN_PLATFORM=desktop`` (so PythonNative selects the Tkinter
1142
+ backend) and hands off to ``pythonnative.preview.run_preview``,
1143
+ which opens a window, mounts the app, and Fast Refreshes on every
1144
+ file save until the window is closed.
1145
+
1146
+ Args:
1147
+ args: Parsed argparse namespace. Recognized attributes:
1148
+
1149
+ - `component` (`str`, optional): Module path like
1150
+ ``"app.main"`` (its ``App`` is used) or a dotted
1151
+ ``module.Component`` path. Defaults to the project's
1152
+ configured ``entryPoint``.
1153
+ - `width` / `height` (`int`): Initial window size in points.
1154
+ - `title` (`str`): Window title.
1155
+ - `no_hot_reload` (`bool`): Disable file watching.
1156
+ """
1157
+ # The desktop backend is selected at *import time* from the
1158
+ # ``PN_PLATFORM`` environment variable (see ``pythonnative.utils`` and
1159
+ # the host selection in ``pythonnative.screen``). Because the ``pn``
1160
+ # console entry point lives inside the ``pythonnative`` package,
1161
+ # importing it already loaded the package under the default,
1162
+ # non-desktop platform before this handler ever runs. Re-exec a fresh
1163
+ # interpreter with the variable set so every module binds to the
1164
+ # Tkinter backend; the re-execed child sees ``PN_PLATFORM=desktop`` and
1165
+ # skips this branch, so there is no exec loop.
1166
+ if os.environ.get("PN_PLATFORM") != "desktop":
1167
+ try:
1168
+ completed = subprocess.run(
1169
+ [sys.executable, "-m", "pythonnative.cli.pn", *sys.argv[1:]],
1170
+ env={**os.environ, "PN_PLATFORM": "desktop"},
1171
+ )
1172
+ except KeyboardInterrupt:
1173
+ sys.exit(130)
1174
+ sys.exit(completed.returncode)
1175
+
1176
+ project_dir = os.getcwd()
1177
+ component: Optional[str] = getattr(args, "component", None)
1178
+ if not component:
1179
+ config = _read_project_config()
1180
+ component = _entrypoint_to_module(config.get("entryPoint", "app/main.py"))
1181
+
1182
+ try:
1183
+ from pythonnative.preview import run_preview
1184
+ except Exception as exc: # pragma: no cover - environment dependent
1185
+ print(f"Error: could not start the desktop preview: {exc}")
1186
+ print(
1187
+ "The desktop preview needs Tkinter (Python's standard GUI toolkit).\n"
1188
+ "On macOS: brew install python-tk\n"
1189
+ "On Debian/Ubuntu: sudo apt-get install python3-tk\n"
1190
+ "On Windows: reinstall Python with the 'tcl/tk' option checked."
1191
+ )
1192
+ sys.exit(1)
1193
+
1194
+ print(f"Starting PythonNative preview for {component} (Ctrl+C or close the window to stop).")
1195
+ try:
1196
+ run_preview(
1197
+ component,
1198
+ project_root=project_dir,
1199
+ width=getattr(args, "width", 390),
1200
+ height=getattr(args, "height", 844),
1201
+ title=getattr(args, "title", "PythonNative Preview"),
1202
+ hot_reload=not getattr(args, "no_hot_reload", False),
1203
+ )
1204
+ except RuntimeError as exc:
1205
+ print(f"Error: {exc}")
1206
+ sys.exit(1)
1207
+
1208
+
1122
1209
  def clean_project(args: argparse.Namespace) -> None:
1123
1210
  """Remove the local `build/` directory.
1124
1211
 
@@ -1152,6 +1239,25 @@ def main() -> None:
1152
1239
  parser_init.add_argument("--force", action="store_true", help="Overwrite existing files if present")
1153
1240
  parser_init.set_defaults(func=init_project)
1154
1241
 
1242
+ # Create a new command 'preview' that calls preview_project
1243
+ parser_preview = subparsers.add_parser("preview")
1244
+ parser_preview.add_argument(
1245
+ "component",
1246
+ nargs="?",
1247
+ help="Module path (e.g. app.main) or dotted component path; defaults to the project entry point",
1248
+ )
1249
+ parser_preview.add_argument("--width", type=int, default=390, help="Initial window width in points (default: 390)")
1250
+ parser_preview.add_argument(
1251
+ "--height", type=int, default=844, help="Initial window height in points (default: 844)"
1252
+ )
1253
+ parser_preview.add_argument("--title", default="PythonNative Preview", help="Preview window title")
1254
+ parser_preview.add_argument(
1255
+ "--no-hot-reload",
1256
+ action="store_true",
1257
+ help="Disable file watching / Fast Refresh",
1258
+ )
1259
+ parser_preview.set_defaults(func=preview_project)
1260
+
1155
1261
  # Create a new command 'run' that calls run_project
1156
1262
  parser_run = subparsers.add_parser("run")
1157
1263
  parser_run.add_argument("platform", choices=["android", "ios"])