pythonnative 0.25.0__py3-none-any.whl → 0.26.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.
Files changed (44) hide show
  1. pythonnative/__init__.py +1 -1
  2. pythonnative/cli/pn.py +172 -12
  3. pythonnative/diagnostics.py +27 -0
  4. pythonnative/native_modules/app_state.py +2 -1
  5. pythonnative/native_modules/battery.py +3 -2
  6. pythonnative/native_modules/biometrics.py +2 -1
  7. pythonnative/native_modules/camera.py +16 -7
  8. pythonnative/native_modules/clipboard.py +3 -2
  9. pythonnative/native_modules/file_system.py +3 -2
  10. pythonnative/native_modules/haptics.py +7 -6
  11. pythonnative/native_modules/linking.py +62 -6
  12. pythonnative/native_modules/location.py +11 -8
  13. pythonnative/native_modules/net_info.py +2 -1
  14. pythonnative/native_modules/notifications.py +97 -6
  15. pythonnative/native_modules/permissions.py +3 -2
  16. pythonnative/native_modules/share.py +2 -1
  17. pythonnative/native_views/android.py +142 -122
  18. pythonnative/native_views/desktop.py +50 -49
  19. pythonnative/native_views/ios.py +228 -160
  20. pythonnative/project/android.py +15 -3
  21. pythonnative/project/builder.py +172 -70
  22. pythonnative/project/config.py +28 -6
  23. pythonnative/project/devices.py +291 -0
  24. pythonnative/project/doctor.py +5 -4
  25. pythonnative/project/ios.py +51 -77
  26. pythonnative/project/permissions.py +19 -1
  27. pythonnative/project/runtime_assets.py +78 -166
  28. pythonnative/templates/android_template/app/build.gradle +5 -0
  29. pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +1 -0
  30. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +88 -12
  31. pythonnative/templates/ios_template/ios_template/AppDelegate.swift +41 -17
  32. pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
  33. pythonnative/templates/ios_template/ios_template/Info.plist +0 -2
  34. pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +397 -0
  35. pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +31 -20
  36. pythonnative/templates/ios_template/ios_template/ViewController.swift +77 -198
  37. pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +72 -47
  38. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/METADATA +1 -1
  39. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/RECORD +43 -41
  40. pythonnative/templates/ios_template/ios_template/Base.lproj/Main.storyboard +0 -24
  41. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/WHEEL +0 -0
  42. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/entry_points.txt +0 -0
  43. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/licenses/LICENSE +0 -0
  44. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/top_level.txt +0 -0
@@ -2,163 +2,80 @@
2
2
  // ViewController.swift
3
3
  // ios_template
4
4
  //
5
- // Created by Owen Carey on 6/19/23.
5
+ // Hosts one PythonNative screen. Python is initialized through
6
+ // PythonRuntime (linked CPython, no PythonKit); a bootstrap failure
7
+ // shows a full-screen error report instead of a silent fallback.
6
8
  //
7
9
 
8
10
  import UIKit
9
- // PythonKit isn't available on iOS by default; guard its use so the
10
- // template builds out of the box and falls back to a native label.
11
- #if canImport(PythonKit)
12
- import PythonKit
13
- #endif
14
- #if canImport(Python)
15
- import Python
16
- #endif
17
-
18
- #if canImport(PythonKit)
19
- private func drainPythonNativeScheduledRenders() {
20
- do {
21
- let pn = try Python.attemptImport("pythonnative.screen")
22
- _ = try pn.drain_ios_scheduled_renders.throwing.dynamicallyCall(withArguments: [])
23
- } catch {
24
- NSLog("[PN] swift.renderScheduler -> drain_ios_scheduled_renders failed: \(error)")
25
- }
26
- }
27
- #endif
28
-
29
- @_cdecl("pn_schedule_render_drain")
30
- public func pn_schedule_render_drain() {
31
- DispatchQueue.main.async {
32
- #if canImport(PythonKit)
33
- drainPythonNativeScheduledRenders()
34
- #endif
35
- }
36
- }
37
11
 
38
12
  class ViewController: UIViewController {
39
- // Ensure Python.framework is configured only once per process
40
- private static var hasInitializedPython: Bool = false
41
- // Optional keys for dynamic screen navigation
13
+ // Optional keys for dynamic screen navigation. Push navigation sets
14
+ // these before presenting the controller; nil means "app.main".
42
15
  @objc dynamic var requestedScreenPath: String? = nil
43
16
  @objc dynamic var requestedScreenArgsJSON: String? = nil
44
- private var pythonReady: Bool = false
45
- #if canImport(PythonKit)
46
- private var screen: PythonObject? = nil
47
- #endif
17
+
18
+ private var screen: PyRef? = nil
19
+ #if DEBUG
48
20
  private var hotReloadTimer: Timer? = nil
21
+ #endif
49
22
 
50
23
  override func viewDidLoad() {
51
24
  super.viewDidLoad()
52
- // Ensure a visible background when created programmatically (storyboards set this automatically)
53
25
  view.backgroundColor = .systemBackground
54
26
 
55
- let firstInit = !ViewController.hasInitializedPython
56
-
57
- // Signal to pythonnative that we're running on iOS. Read on the
58
- // Python side (pythonnative.utils.IS_IOS) to gate iOS-only setup
59
- // like sys.stdout redirection. Set before Python starts so it's
60
- // visible to the very first import.
61
- setenv("PN_PLATFORM", "ios", 1)
62
-
63
- // Configure embedded Python if available in bundle. PYTHONHOME /
64
- // PYTHONPATH only need to be set once per process, but setting them
65
- // again is harmless and keeps the flow simple.
66
- if let resourcePath = Bundle.main.resourcePath {
67
- let pyStd = "\(resourcePath)/python-stdlib"
68
- let pyDyn = "\(resourcePath)/python-stdlib/lib-dynload"
69
- let devRoot = "\(NSHomeDirectory())/Documents/pythonnative_dev"
70
- var pyPath = "\(devRoot):\(pyStd):\(pyDyn):\(resourcePath):\(resourcePath)/app"
71
- let platSite = "\(resourcePath)/platform-site"
72
- if FileManager.default.fileExists(atPath: platSite) {
73
- pyPath += ":\(platSite)"
74
- }
75
- setenv("PYTHONHOME", pyStd, 1)
76
- setenv("PYTHONPATH", pyPath, 1)
77
- }
78
- #if canImport(PythonKit)
79
- // Ensure PythonKit knows where to load the Python library from when using an embedded framework.
80
- if let bundlePath = Bundle.main.bundlePath as String? {
81
- let frameworkLib = "\(bundlePath)/Frameworks/Python.framework/Python"
82
- setenv("PYTHON_LIBRARY", frameworkLib, 1)
83
- if FileManager.default.fileExists(atPath: frameworkLib) {
84
- if firstInit {
85
- PythonLibrary.useLibrary(at: frameworkLib)
86
- ViewController.hasInitializedPython = true
87
- }
88
- pythonReady = true
89
- } else {
90
- NSLog("[PN] Embedded Python library not found at: \(frameworkLib)")
91
- }
92
- }
93
- let sys = Python.import("sys")
94
- if firstInit {
95
- // One concise bootstrap line per process; per-screen detail is left
96
- // to Python-side print() statements streamed via pn run ios.
97
- let shortVersion = "\(sys.version)".split(separator: "\n").first.map(String.init) ?? "\(sys.version)"
98
- NSLog("[PN] Python \(shortVersion) initialized")
99
- }
100
- if let resourcePath = Bundle.main.resourcePath {
101
- let devRoot = "\(NSHomeDirectory())/Documents/pythonnative_dev"
102
- sys.path.insert(0, devRoot)
103
- sys.path.append(resourcePath)
104
- sys.path.append("\(resourcePath)/app")
105
- do {
106
- let hotReload = try Python.attemptImport("pythonnative.hot_reload")
107
- let docsPath = "\(NSHomeDirectory())/Documents"
108
- _ = try hotReload.configure_dev_environment.throwing.dynamicallyCall(withArguments: [docsPath])
109
- } catch {
110
- NSLog("[PN] Hot reload setup skipped: \(error)")
111
- }
27
+ do {
28
+ try PythonRuntime.shared.ensureStarted()
29
+ } catch {
30
+ showBootstrapError("Python failed to start.\n\n\(error)")
31
+ return
112
32
  }
113
- // Determine which Python module to load. PythonNative's
114
- // convention is "import the module and grab its top-level
115
- // `App` attribute", so the default is just the module path
33
+
34
+ // PythonNative's convention is "import the module and grab its
35
+ // top-level `App` attribute", so the default is the module path
116
36
  // "app.main". Push navigation overrides this via
117
37
  // `requestedScreenPath`, which may also be a dotted-attribute
118
38
  // path like "app.main.RootScreen".
119
39
  let screenPath: String = requestedScreenPath ?? "app.main"
40
+ let addr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
120
41
  do {
121
- let pnScreen = try Python.attemptImport("pythonnative.screen")
122
- let ptr = Unmanaged.passUnretained(self).toOpaque()
123
- let addr = UInt(bitPattern: ptr)
124
- let argsJson: PythonObject = (requestedScreenArgsJSON != nil)
125
- ? PythonObject(requestedScreenArgsJSON!)
126
- : Python.None
127
- let screen = try pnScreen.create_screen.throwing.dynamicallyCall(
128
- withArguments: [screenPath, addr, argsJson]
129
- )
42
+ let screen: PyRef
43
+ if let argsJSON = requestedScreenArgsJSON {
44
+ screen = try PythonRuntime.shared.call(
45
+ module: "pythonnative.screen", function: "create_screen", screenPath, addr, argsJSON
46
+ )
47
+ } else {
48
+ screen = try PythonRuntime.shared.call(
49
+ module: "pythonnative.screen", function: "create_screen", screenPath, addr
50
+ )
51
+ }
130
52
  self.screen = screen
53
+ #if DEBUG
131
54
  let devRoot = "\(NSHomeDirectory())/Documents/pythonnative_dev"
132
- let manifestPath = "\(devRoot)/reload.json"
133
- _ = try screen.enable_hot_reload.throwing.dynamicallyCall(withArguments: [manifestPath, devRoot])
134
- _ = try screen.on_create.throwing.dynamicallyCall(withArguments: [])
55
+ try screen.call("enable_hot_reload", "\(devRoot)/reload.json", devRoot)
56
+ #endif
57
+ try screen.call("on_create")
58
+ #if DEBUG
135
59
  startHotReloadPolling()
136
- return
60
+ #endif
137
61
  } catch {
138
- NSLog("[PN] Python bootstrap failed: \(error)")
62
+ showBootstrapError("The PythonNative screen failed to mount.\n\n\(error)")
139
63
  }
140
- #endif
64
+ }
65
+
66
+ // MARK: - Lifecycle forwarding
141
67
 
142
- // Fallback UI if Python import/bootstrap fails
143
- NSLog("[PN] Python unavailable or bootstrap failed; showing fallback UILabel")
144
- let label = UILabel(frame: view.bounds)
145
- label.text = "Hello from PythonNative (iOS template)"
146
- label.textAlignment = .center
147
- label.autoresizingMask = [.flexibleWidth, .flexibleHeight]
148
- view.addSubview(label)
68
+ private func forwardLifecycle(_ event: String) {
69
+ guard screen != nil else { return }
70
+ let addr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
71
+ PythonRuntime.shared.notify(
72
+ module: "pythonnative.screen", function: "forward_lifecycle", addr, event
73
+ )
149
74
  }
150
75
 
151
76
  override func viewWillAppear(_ animated: Bool) {
152
77
  super.viewWillAppear(animated)
153
- #if canImport(PythonKit)
154
- if pythonReady {
155
- let ptr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
156
- do {
157
- let pn = try Python.attemptImport("pythonnative.screen")
158
- _ = try pn.forward_lifecycle.throwing.dynamicallyCall(withArguments: [ptr, "on_start"])
159
- } catch {}
160
- }
161
- #endif
78
+ forwardLifecycle("on_start")
162
79
  }
163
80
 
164
81
  override func viewDidLayoutSubviews() {
@@ -167,112 +84,74 @@ class ViewController: UIViewController {
167
84
  // positioned the view in its window; forward every layout pass
168
85
  // to Python so the reconciler can re-run layout against the
169
86
  // correct viewport (initial mount, rotation, multitasking, etc.).
170
- #if canImport(PythonKit)
171
- if pythonReady {
172
- let ptr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
173
- do {
174
- let pn = try Python.attemptImport("pythonnative.screen")
175
- _ = try pn.forward_lifecycle.throwing.dynamicallyCall(withArguments: [ptr, "on_layout"])
176
- } catch {
177
- NSLog("[PN] swift.viewDidLayoutSubviews -> on_layout failed: \(error)")
178
- }
179
- }
180
- #endif
87
+ forwardLifecycle("on_layout")
181
88
  }
182
89
 
183
90
  override func viewDidAppear(_ animated: Bool) {
184
91
  super.viewDidAppear(animated)
185
- #if canImport(PythonKit)
186
- if pythonReady {
187
- let ptrAddr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
188
- do {
189
- let pn = try Python.attemptImport("pythonnative.screen")
190
- _ = try pn.forward_lifecycle.throwing.dynamicallyCall(withArguments: [ptrAddr, "on_resume"])
191
- } catch {
192
- NSLog("[PN] swift.viewDidAppear -> on_resume failed: \(error)")
193
- }
194
- }
195
- #endif
92
+ forwardLifecycle("on_resume")
196
93
  }
197
94
 
198
95
  override func viewWillDisappear(_ animated: Bool) {
199
96
  super.viewWillDisappear(animated)
200
- #if canImport(PythonKit)
201
- if pythonReady {
202
- let ptr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
203
- do {
204
- let pn = try Python.attemptImport("pythonnative.screen")
205
- _ = try pn.forward_lifecycle.throwing.dynamicallyCall(withArguments: [ptr, "on_pause"])
206
- } catch {}
207
- }
208
- #endif
97
+ forwardLifecycle("on_pause")
209
98
  }
210
99
 
211
100
  override func viewDidDisappear(_ animated: Bool) {
212
101
  super.viewDidDisappear(animated)
213
- #if canImport(PythonKit)
214
- if pythonReady {
215
- let ptr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
216
- do {
217
- let pn = try Python.attemptImport("pythonnative.screen")
218
- _ = try pn.forward_lifecycle.throwing.dynamicallyCall(withArguments: [ptr, "on_stop"])
219
- } catch {}
220
- }
221
- #endif
102
+ forwardLifecycle("on_stop")
222
103
  }
223
104
 
224
105
  override func encodeRestorableState(with coder: NSCoder) {
225
106
  super.encodeRestorableState(with: coder)
226
- #if canImport(PythonKit)
227
- if pythonReady {
228
- let ptr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
229
- do {
230
- let pn = try Python.attemptImport("pythonnative.screen")
231
- _ = try pn.forward_lifecycle.throwing.dynamicallyCall(withArguments: [ptr, "on_save_instance_state"])
232
- } catch {}
233
- }
234
- #endif
107
+ forwardLifecycle("on_save_instance_state")
235
108
  }
236
109
 
237
110
  override func decodeRestorableState(with coder: NSCoder) {
238
111
  super.decodeRestorableState(with: coder)
239
- #if canImport(PythonKit)
240
- if pythonReady {
241
- let ptr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
242
- do {
243
- let pn = try Python.attemptImport("pythonnative.screen")
244
- _ = try pn.forward_lifecycle.throwing.dynamicallyCall(withArguments: [ptr, "on_restore_instance_state"])
245
- } catch {}
246
- }
247
- #endif
112
+ forwardLifecycle("on_restore_instance_state")
248
113
  }
249
114
 
250
115
  deinit {
116
+ #if DEBUG
251
117
  hotReloadTimer?.invalidate()
252
- #if canImport(PythonKit)
253
- if pythonReady {
254
- let ptr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
255
- do {
256
- let pn = try Python.attemptImport("pythonnative.screen")
257
- _ = try pn.forward_lifecycle.throwing.dynamicallyCall(withArguments: [ptr, "on_destroy"])
258
- } catch {}
259
- }
260
118
  #endif
119
+ if screen != nil {
120
+ let addr = UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque())
121
+ PythonRuntime.shared.notify(
122
+ module: "pythonnative.screen", function: "forward_lifecycle", addr, "on_destroy"
123
+ )
124
+ }
261
125
  }
262
126
 
127
+ // MARK: - Hot reload (dev builds only)
128
+
129
+ #if DEBUG
263
130
  private func startHotReloadPolling() {
264
- #if canImport(PythonKit)
265
131
  hotReloadTimer?.invalidate()
266
132
  hotReloadTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in
267
133
  guard let screen = self?.screen else { return }
268
134
  do {
269
- _ = try screen.hot_reload_tick.throwing.dynamicallyCall(withArguments: [])
135
+ try screen.call("hot_reload_tick")
270
136
  } catch {
271
137
  NSLog("[PN] hot_reload_tick failed: \(error)")
272
138
  }
273
139
  }
274
- #endif
275
140
  }
141
+ #endif
276
142
 
143
+ // MARK: - Bootstrap error UI
144
+
145
+ private func showBootstrapError(_ message: String) {
146
+ NSLog("[PN] %@", message)
147
+ let text = UITextView(frame: view.bounds)
148
+ text.autoresizingMask = [.flexibleWidth, .flexibleHeight]
149
+ text.isEditable = false
150
+ text.backgroundColor = UIColor(red: 0.75, green: 0.10, blue: 0.10, alpha: 1.0)
151
+ text.textColor = .white
152
+ text.font = UIFont.monospacedSystemFont(ofSize: 13, weight: .regular)
153
+ text.textContainerInset = UIEdgeInsets(top: 60, left: 16, bottom: 40, right: 16)
154
+ text.text = "PythonNative could not start\n\n\(message)"
155
+ view.addSubview(text)
156
+ }
277
157
  }
278
-
@@ -10,13 +10,16 @@
10
10
  146EBB822A40CCC900E4A2B3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 146EBB812A40CCC900E4A2B3 /* AppDelegate.swift */; };
11
11
  146EBB842A40CCC900E4A2B3 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 146EBB832A40CCC900E4A2B3 /* SceneDelegate.swift */; };
12
12
  146EBB862A40CCC900E4A2B3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 146EBB852A40CCC900E4A2B3 /* ViewController.swift */; };
13
- 146EBB892A40CCC900E4A2B3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 146EBB872A40CCC900E4A2B3 /* Main.storyboard */; };
14
13
  146EBB8B2A40CCCE00E4A2B3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 146EBB8A2A40CCCE00E4A2B3 /* Assets.xcassets */; };
15
14
  146EBB8E2A40CCCE00E4A2B3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 146EBB8C2A40CCCE00E4A2B3 /* LaunchScreen.storyboard */; };
16
15
  146EBB992A40CCCE00E4A2B3 /* ios_templateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 146EBB982A40CCCE00E4A2B3 /* ios_templateTests.swift */; };
17
16
  146EBBA32A40CCCE00E4A2B3 /* ios_templateUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 146EBBA22A40CCCE00E4A2B3 /* ios_templateUITests.swift */; };
18
- 146EBBA52A40CCCE00E4A2B3 /* ios_templateUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 146EBBA42A40CCCE00E4A2B3 /* ios_templateUITestsLaunchTests.swift */; };
19
- A1B2C3D42B2F000000000012 /* PythonKit in Frameworks */ = {isa = PBXBuildFile; productRef = A1B2C3D42B2F000000000011 /* PythonKit */; };
17
+ 146EBBA52A40CCCE00E4A2B3 /* ios_templateUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 146EBBA42A40CCCE00E4A2B3 /* ios_templateUITestsLaunchTests.swift */; };
18
+ AA0000000000000000000002 /* PythonRuntime.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA0000000000000000000001 /* PythonRuntime.swift */; };
19
+ AA0000000000000000000004 /* Python.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA0000000000000000000003 /* Python.xcframework */; };
20
+ AA0000000000000000000005 /* Python.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = AA0000000000000000000003 /* Python.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
21
+ AA0000000000000000000007 /* app in Resources */ = {isa = PBXBuildFile; fileRef = AA0000000000000000000006 /* app */; };
22
+ AA0000000000000000000009 /* app_packages in Resources */ = {isa = PBXBuildFile; fileRef = AA0000000000000000000008 /* app_packages */; };
20
23
  /* End PBXBuildFile section */
21
24
 
22
25
  /* Begin PBXContainerItemProxy section */
@@ -41,7 +44,6 @@
41
44
  146EBB812A40CCC900E4A2B3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
42
45
  146EBB832A40CCC900E4A2B3 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
43
46
  146EBB852A40CCC900E4A2B3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
44
- 146EBB882A40CCC900E4A2B3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
45
47
  146EBB8A2A40CCCE00E4A2B3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
46
48
  146EBB8D2A40CCCE00E4A2B3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
47
49
  146EBB8F2A40CCCE00E4A2B3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -49,16 +51,21 @@
49
51
  146EBB982A40CCCE00E4A2B3 /* ios_templateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ios_templateTests.swift; sourceTree = "<group>"; };
50
52
  146EBB9E2A40CCCE00E4A2B3 /* ios_templateUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ios_templateUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
51
53
  146EBBA22A40CCCE00E4A2B3 /* ios_templateUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ios_templateUITests.swift; sourceTree = "<group>"; };
52
- 146EBBA42A40CCCE00E4A2B3 /* ios_templateUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ios_templateUITestsLaunchTests.swift; sourceTree = "<group>"; };
54
+ 146EBBA42A40CCCE00E4A2B3 /* ios_templateUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ios_templateUITestsLaunchTests.swift; sourceTree = "<group>"; };
55
+ AA0000000000000000000001 /* PythonRuntime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PythonRuntime.swift; sourceTree = "<group>"; };
56
+ AA0000000000000000000003 /* Python.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python.xcframework; sourceTree = "<group>"; };
57
+ AA0000000000000000000006 /* app */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app; sourceTree = "<group>"; };
58
+ AA0000000000000000000008 /* app_packages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app_packages; sourceTree = "<group>"; };
59
+ AA000000000000000000000B /* BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = "<group>"; };
53
60
  /* End PBXFileReference section */
54
61
 
55
62
  /* Begin PBXFrameworksBuildPhase section */
56
63
  146EBB7B2A40CCC900E4A2B3 /* Frameworks */ = {
57
64
  isa = PBXFrameworksBuildPhase;
58
65
  buildActionMask = 2147483647;
59
- files = (
60
- A1B2C3D42B2F000000000012 /* PythonKit in Frameworks */,
61
- );
66
+ files = (
67
+ AA0000000000000000000004 /* Python.xcframework in Frameworks */,
68
+ );
62
69
  runOnlyForDeploymentPostprocessing = 0;
63
70
  };
64
71
  146EBB912A40CCCE00E4A2B3 /* Frameworks */ = {
@@ -80,10 +87,13 @@
80
87
  /* Begin PBXGroup section */
81
88
  146EBB752A40CCC900E4A2B3 = {
82
89
  isa = PBXGroup;
83
- children = (
84
- 146EBB802A40CCC900E4A2B3 /* ios_template */,
90
+ children = (
91
+ 146EBB802A40CCC900E4A2B3 /* ios_template */,
85
92
  146EBB972A40CCCE00E4A2B3 /* ios_templateTests */,
86
93
  146EBBA12A40CCCE00E4A2B3 /* ios_templateUITests */,
94
+ AA0000000000000000000003 /* Python.xcframework */,
95
+ AA0000000000000000000006 /* app */,
96
+ AA0000000000000000000008 /* app_packages */,
87
97
  146EBB7F2A40CCC900E4A2B3 /* Products */,
88
98
  );
89
99
  sourceTree = "<group>";
@@ -104,7 +114,8 @@
104
114
  146EBB812A40CCC900E4A2B3 /* AppDelegate.swift */,
105
115
  146EBB832A40CCC900E4A2B3 /* SceneDelegate.swift */,
106
116
  146EBB852A40CCC900E4A2B3 /* ViewController.swift */,
107
- 146EBB872A40CCC900E4A2B3 /* Main.storyboard */,
117
+ AA0000000000000000000001 /* PythonRuntime.swift */,
118
+ AA000000000000000000000B /* BridgingHeader.h */,
108
119
  146EBB8A2A40CCCE00E4A2B3 /* Assets.xcassets */,
109
120
  146EBB8C2A40CCCE00E4A2B3 /* LaunchScreen.storyboard */,
110
121
  146EBB8F2A40CCCE00E4A2B3 /* Info.plist */,
@@ -139,15 +150,13 @@
139
150
  146EBB7A2A40CCC900E4A2B3 /* Sources */,
140
151
  146EBB7B2A40CCC900E4A2B3 /* Frameworks */,
141
152
  146EBB7C2A40CCC900E4A2B3 /* Resources */,
153
+ AA000000000000000000000A /* Install Python runtime */,
142
154
  146EBC002A40CCCE00E4A2B3 /* Embed Frameworks */,
143
155
  );
144
156
  buildRules = (
145
157
  );
146
158
  dependencies = (
147
159
  );
148
- packageProductDependencies = (
149
- A1B2C3D42B2F000000000011 /* PythonKit */,
150
- );
151
160
  name = ios_template;
152
161
  productName = ios_template;
153
162
  productReference = 146EBB7E2A40CCC900E4A2B3 /* ios_template.app */;
@@ -221,9 +230,6 @@
221
230
  Base,
222
231
  );
223
232
  mainGroup = 146EBB752A40CCC900E4A2B3;
224
- packageReferences = (
225
- A1B2C3D42B2F000000000010 /* XCRemoteSwiftPackageReference "PythonKit" */,
226
- );
227
233
  productRefGroup = 146EBB7F2A40CCC900E4A2B3 /* Products */;
228
234
  projectDirPath = "";
229
235
  projectRoot = "";
@@ -242,31 +248,13 @@
242
248
  dstPath = "";
243
249
  dstSubfolderSpec = 10;
244
250
  files = (
251
+ AA0000000000000000000005 /* Python.xcframework in Embed Frameworks */,
245
252
  );
246
253
  name = "Embed Frameworks";
247
254
  runOnlyForDeploymentPostprocessing = 0;
248
255
  };
249
256
  /* End PBXCopyFilesBuildPhase section */
250
257
 
251
- /* Begin XCRemoteSwiftPackageReference section */
252
- A1B2C3D42B2F000000000010 /* XCRemoteSwiftPackageReference "PythonKit" */ = {
253
- isa = XCRemoteSwiftPackageReference;
254
- repositoryURL = "https://github.com/pvieito/PythonKit";
255
- requirement = {
256
- kind = upToNextMinorVersion;
257
- minimumVersion = 0.5.1;
258
- };
259
- };
260
- /* End XCRemoteSwiftPackageReference section */
261
-
262
- /* Begin XCSwiftPackageProductDependency section */
263
- A1B2C3D42B2F000000000011 /* PythonKit */ = {
264
- isa = XCSwiftPackageProductDependency;
265
- package = A1B2C3D42B2F000000000010 /* XCRemoteSwiftPackageReference "PythonKit" */;
266
- productName = PythonKit;
267
- };
268
- /* End XCSwiftPackageProductDependency section */
269
-
270
258
  /* Begin PBXResourcesBuildPhase section */
271
259
  146EBB7C2A40CCC900E4A2B3 /* Resources */ = {
272
260
  isa = PBXResourcesBuildPhase;
@@ -274,7 +262,8 @@
274
262
  files = (
275
263
  146EBB8E2A40CCCE00E4A2B3 /* LaunchScreen.storyboard in Resources */,
276
264
  146EBB8B2A40CCCE00E4A2B3 /* Assets.xcassets in Resources */,
277
- 146EBB892A40CCC900E4A2B3 /* Main.storyboard in Resources */,
265
+ AA0000000000000000000007 /* app in Resources */,
266
+ AA0000000000000000000009 /* app_packages in Resources */,
278
267
  );
279
268
  runOnlyForDeploymentPostprocessing = 0;
280
269
  };
@@ -294,12 +283,36 @@
294
283
  };
295
284
  /* End PBXResourcesBuildPhase section */
296
285
 
286
+ /* Begin PBXShellScriptBuildPhase section */
287
+ AA000000000000000000000A /* Install Python runtime */ = {
288
+ isa = PBXShellScriptBuildPhase;
289
+ alwaysOutOfDate = 1;
290
+ buildActionMask = 2147483647;
291
+ files = (
292
+ );
293
+ inputFileListPaths = (
294
+ );
295
+ inputPaths = (
296
+ );
297
+ name = "Install Python runtime";
298
+ outputFileListPaths = (
299
+ );
300
+ outputPaths = (
301
+ );
302
+ runOnlyForDeploymentPostprocessing = 0;
303
+ shellPath = /bin/sh;
304
+ shellScript = "set -e\nif [ ! -d \"$PROJECT_DIR/Python.xcframework\" ]; then\n echo \"error: Python.xcframework is missing from the project. Build with 'pn run ios' or 'pn build ios' so the PythonNative CLI links the embedded runtime; the raw template cannot be built directly.\"\n exit 1\nfi\nif [ ! -d \"$PROJECT_DIR/app\" ] || [ ! -d \"$PROJECT_DIR/app_packages\" ]; then\n echo \"error: app/ or app_packages/ has not been staged. Build with 'pn run ios' or 'pn build ios' so the PythonNative CLI stages the Python sources.\"\n exit 1\nfi\nif [ ! -d \"$PROJECT_DIR/app_packages/pythonnative\" ]; then\n echo \"error: the pythonnative package is missing from app_packages/. Re-run 'pn run ios' or 'pn build ios'.\"\n exit 1\nfi\nsource \"$PROJECT_DIR/Python.xcframework/build/utils.sh\"\ninstall_python Python.xcframework app app_packages\n";
305
+ showEnvVarsInLog = 0;
306
+ };
307
+ /* End PBXShellScriptBuildPhase section */
308
+
297
309
  /* Begin PBXSourcesBuildPhase section */
298
310
  146EBB7A2A40CCC900E4A2B3 /* Sources */ = {
299
311
  isa = PBXSourcesBuildPhase;
300
312
  buildActionMask = 2147483647;
301
313
  files = (
302
314
  146EBB862A40CCC900E4A2B3 /* ViewController.swift in Sources */,
315
+ AA0000000000000000000002 /* PythonRuntime.swift in Sources */,
303
316
  146EBB822A40CCC900E4A2B3 /* AppDelegate.swift in Sources */,
304
317
  146EBB842A40CCC900E4A2B3 /* SceneDelegate.swift in Sources */,
305
318
  );
@@ -338,14 +351,6 @@
338
351
  /* End PBXTargetDependency section */
339
352
 
340
353
  /* Begin PBXVariantGroup section */
341
- 146EBB872A40CCC900E4A2B3 /* Main.storyboard */ = {
342
- isa = PBXVariantGroup;
343
- children = (
344
- 146EBB882A40CCC900E4A2B3 /* Base */,
345
- );
346
- name = Main.storyboard;
347
- sourceTree = "<group>";
348
- };
349
354
  146EBB8C2A40CCCE00E4A2B3 /* LaunchScreen.storyboard */ = {
350
355
  isa = PBXVariantGroup;
351
356
  children = (
@@ -476,14 +481,22 @@
476
481
  buildSettings = {
477
482
  ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
478
483
  ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
484
+ CLANG_ENABLE_MODULES = NO;
479
485
  CODE_SIGN_STYLE = Automatic;
480
486
  CURRENT_PROJECT_VERSION = 1;
481
487
  DEVELOPMENT_TEAM = "";
488
+ "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = (
489
+ "$(inherited)",
490
+ "$(PROJECT_DIR)/Python.xcframework/ios-arm64",
491
+ );
492
+ "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = (
493
+ "$(inherited)",
494
+ "$(PROJECT_DIR)/Python.xcframework/ios-arm64_x86_64-simulator",
495
+ );
482
496
  GENERATE_INFOPLIST_FILE = YES;
483
497
  INFOPLIST_FILE = ios_template/Info.plist;
484
498
  INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
485
499
  INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
486
- INFOPLIST_KEY_UIMainStoryboardFile = Main;
487
500
  INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
488
501
  INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
489
502
  LD_RUNPATH_SEARCH_PATHS = (
@@ -494,6 +507,8 @@
494
507
  PRODUCT_BUNDLE_IDENTIFIER = "com.pythonnative.ios-template";
495
508
  PRODUCT_NAME = "$(TARGET_NAME)";
496
509
  SWIFT_EMIT_LOC_STRINGS = YES;
510
+ SWIFT_OBJC_BRIDGING_HEADER = "ios_template/BridgingHeader.h";
511
+ SWIFT_PRECOMPILE_BRIDGING_HEADER = NO;
497
512
  SWIFT_VERSION = 5.0;
498
513
  TARGETED_DEVICE_FAMILY = "1,2";
499
514
  };
@@ -504,14 +519,22 @@
504
519
  buildSettings = {
505
520
  ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
506
521
  ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
522
+ CLANG_ENABLE_MODULES = NO;
507
523
  CODE_SIGN_STYLE = Automatic;
508
524
  CURRENT_PROJECT_VERSION = 1;
509
525
  DEVELOPMENT_TEAM = "";
526
+ "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = (
527
+ "$(inherited)",
528
+ "$(PROJECT_DIR)/Python.xcframework/ios-arm64",
529
+ );
530
+ "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = (
531
+ "$(inherited)",
532
+ "$(PROJECT_DIR)/Python.xcframework/ios-arm64_x86_64-simulator",
533
+ );
510
534
  GENERATE_INFOPLIST_FILE = YES;
511
535
  INFOPLIST_FILE = ios_template/Info.plist;
512
536
  INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
513
537
  INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
514
- INFOPLIST_KEY_UIMainStoryboardFile = Main;
515
538
  INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
516
539
  INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
517
540
  LD_RUNPATH_SEARCH_PATHS = (
@@ -522,6 +545,8 @@
522
545
  PRODUCT_BUNDLE_IDENTIFIER = "com.pythonnative.ios-template";
523
546
  PRODUCT_NAME = "$(TARGET_NAME)";
524
547
  SWIFT_EMIT_LOC_STRINGS = YES;
548
+ SWIFT_OBJC_BRIDGING_HEADER = "ios_template/BridgingHeader.h";
549
+ SWIFT_PRECOMPILE_BRIDGING_HEADER = NO;
525
550
  SWIFT_VERSION = 5.0;
526
551
  TARGETED_DEVICE_FAMILY = "1,2";
527
552
  };
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonnative
3
- Version: 0.25.0
3
+ Version: 0.26.0
4
4
  Summary: Cross-platform native UI toolkit for Android and iOS
5
5
  Author: Owen Carey
6
6
  License: MIT License