Skip to content

Commit 2ecf72f

Browse files
committed
Tweak Python integration
1 parent fbadfda commit 2ecf72f

File tree

12 files changed

+132
-111
lines changed

12 files changed

+132
-111
lines changed

Copilot for Xcode.xcodeproj/project.pbxproj

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
C8216B782980370100AD38C7 /* ReloadLaunchAgent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8216B772980370100AD38C7 /* ReloadLaunchAgent.swift */; };
2323
C8216B7D2980374300AD38C7 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = C8216B7C2980374300AD38C7 /* ArgumentParser */; };
2424
C8216B802980378300AD38C7 /* Helper in Embed XPCService */ = {isa = PBXBuildFile; fileRef = C8216B70298036EC00AD38C7 /* Helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
25+
C83E5DEB2A38CD000071506D /* site-packages in Resources */ = {isa = PBXBuildFile; fileRef = C83E5DE92A38CD000071506D /* site-packages */; };
26+
C83E5DEC2A38CD000071506D /* python-stdlib in Resources */ = {isa = PBXBuildFile; fileRef = C83E5DEA2A38CD000071506D /* python-stdlib */; };
2527
C8520301293C4D9000460097 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8520300293C4D9000460097 /* Helpers.swift */; };
2628
C861A6A329E5503F005C41A3 /* PromptToCodeCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = C861A6A229E5503F005C41A3 /* PromptToCodeCommand.swift */; };
2729
C861E6112994F6070056CB02 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C861E6102994F6070056CB02 /* AppDelegate.swift */; };
@@ -38,7 +40,6 @@
3840
C87B03AC293B2CF300C77EAE /* XcodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C81458902939EFDC00135263 /* XcodeKit.framework */; };
3941
C87B03AD293B2CF300C77EAE /* XcodeKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C81458902939EFDC00135263 /* XcodeKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
4042
C882175C294187EF00A22FD3 /* Client in Frameworks */ = {isa = PBXBuildFile; productRef = C882175B294187EF00A22FD3 /* Client */; };
41-
C8A3AE592A2885A70046E809 /* InitializePython.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8A3AE582A2885A70046E809 /* InitializePython.swift */; };
4243
C8C8B60929AFA35F00034BEE /* CopilotForXcodeExtensionService.app in Embed XPCService */ = {isa = PBXBuildFile; fileRef = C861E60E2994F6070056CB02 /* CopilotForXcodeExtensionService.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4344
C8DCF00029CE11D500FDDDD7 /* ChatWithSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DCEFFF29CE11D500FDDDD7 /* ChatWithSelection.swift */; };
4445
/* End PBXBuildFile section */
@@ -150,6 +151,10 @@
150151
C8216B72298036EC00AD38C7 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
151152
C8216B772980370100AD38C7 /* ReloadLaunchAgent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReloadLaunchAgent.swift; sourceTree = "<group>"; };
152153
C82E38492A1F025F00D4EADF /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
154+
C83E3F3E2A38C66D0071506D /* Python */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Python; sourceTree = "<group>"; };
155+
C83E5DE92A38CD000071506D /* site-packages */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "site-packages"; path = "Python/site-packages"; sourceTree = "<group>"; };
156+
C83E5DEA2A38CD000071506D /* python-stdlib */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "python-stdlib"; path = "Python/python-stdlib"; sourceTree = "<group>"; };
157+
C83E5DED2A38CD8C0071506D /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
153158
C8520300293C4D9000460097 /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
154159
C8520308293D805800460097 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
155160
C861A6A229E5503F005C41A3 /* PromptToCodeCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromptToCodeCommand.swift; sourceTree = "<group>"; };
@@ -166,10 +171,6 @@
166171
C87B03A8293B262600C77EAE /* NextSuggestionCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextSuggestionCommand.swift; sourceTree = "<group>"; };
167172
C87B03AA293B262E00C77EAE /* PreviousSuggestionCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviousSuggestionCommand.swift; sourceTree = "<group>"; };
168173
C887BC832965D96000931567 /* DEVELOPMENT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = DEVELOPMENT.md; sourceTree = "<group>"; };
169-
C8A3AE512A2883430046E809 /* Python.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Python.xcframework; sourceTree = "<group>"; };
170-
C8A3AE582A2885A70046E809 /* InitializePython.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitializePython.swift; sourceTree = "<group>"; };
171-
C8A3AE5A2A288AF90046E809 /* site-packages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "site-packages"; sourceTree = "<group>"; };
172-
C8A3B1762A288FA90046E809 /* python-stdlib */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "python-stdlib"; sourceTree = "<group>"; };
173174
C8CD828229B88006008D044D /* TestPlan.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TestPlan.xctestplan; sourceTree = "<group>"; };
174175
C8DCEFFF29CE11D500FDDDD7 /* ChatWithSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatWithSelection.swift; sourceTree = "<group>"; };
175176
/* End PBXFileReference section */
@@ -250,17 +251,20 @@
250251
C887BC832965D96000931567 /* DEVELOPMENT.md */,
251252
C8520308293D805800460097 /* README.md */,
252253
C82E38492A1F025F00D4EADF /* LICENSE */,
254+
C83E5DED2A38CD8C0071506D /* Makefile */,
253255
C81E867D296FE4420026E908 /* Version.xcconfig */,
254256
C81458AD293A009600135263 /* Config.xcconfig */,
255257
C81458AE293A009800135263 /* Config.debug.xcconfig */,
256258
C8CD828229B88006008D044D /* TestPlan.xctestplan */,
259+
C83E3F3E2A38C66D0071506D /* Python */,
257260
C81D181E2A1B509B006C1B70 /* Tool */,
258261
C8189B282938979000C9DCDA /* Core */,
259262
C8189B182938972F00C9DCDA /* Copilot for Xcode */,
260263
C81458922939EFDC00135263 /* EditorExtension */,
261264
C8216B71298036EC00AD38C7 /* Helper */,
262265
C861E60F2994F6070056CB02 /* ExtensionService */,
263-
C81BBF5A2A2CA0B8000B4F61 /* Python */,
266+
C83E5DEA2A38CD000071506D /* python-stdlib */,
267+
C83E5DE92A38CD000071506D /* site-packages */,
264268
C814588D2939EFDC00135263 /* Frameworks */,
265269
C8189B172938972F00C9DCDA /* Products */,
266270
);
@@ -297,16 +301,6 @@
297301
path = "Preview Content";
298302
sourceTree = "<group>";
299303
};
300-
C81BBF5A2A2CA0B8000B4F61 /* Python */ = {
301-
isa = PBXGroup;
302-
children = (
303-
C8A3AE512A2883430046E809 /* Python.xcframework */,
304-
C8A3B1762A288FA90046E809 /* python-stdlib */,
305-
C8A3AE5A2A288AF90046E809 /* site-packages */,
306-
);
307-
path = Python;
308-
sourceTree = "<group>";
309-
};
310304
C8216B71298036EC00AD38C7 /* Helper */ = {
311305
isa = PBXGroup;
312306
children = (
@@ -322,7 +316,6 @@
322316
C81291D92994FE7900196E12 /* Info.plist */,
323317
C861E61F2994F6390056CB02 /* ServiceDelegate.swift */,
324318
C861E6102994F6070056CB02 /* AppDelegate.swift */,
325-
C8A3AE582A2885A70046E809 /* InitializePython.swift */,
326319
C81291D52994FE6900196E12 /* Main.storyboard */,
327320
C861E6142994F6080056CB02 /* Assets.xcassets */,
328321
C861E6192994F6080056CB02 /* ExtensionService.entitlements */,
@@ -493,6 +486,8 @@
493486
files = (
494487
C861E6152994F6080056CB02 /* Assets.xcassets in Resources */,
495488
C81291D72994FE6900196E12 /* Main.storyboard in Resources */,
489+
C83E5DEB2A38CD000071506D /* site-packages in Resources */,
490+
C83E5DEC2A38CD000071506D /* python-stdlib in Resources */,
496491
);
497492
runOnlyForDeploymentPostprocessing = 0;
498493
};
@@ -516,7 +511,7 @@
516511
);
517512
runOnlyForDeploymentPostprocessing = 0;
518513
shellPath = /bin/sh;
519-
shellScript = "#set -e\n#echo \"Signing as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)\"\n#find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python-stdlib/lib-dynload\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n";
514+
shellScript = "set -e\necho \"Signing as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)\"\nfind \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python-stdlib/lib-dynload\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n";
520515
};
521516
C8A3B1782A2894E10046E809 /* Sign Python Site Packages */ = {
522517
isa = PBXShellScriptBuildPhase;
@@ -535,7 +530,7 @@
535530
);
536531
runOnlyForDeploymentPostprocessing = 0;
537532
shellPath = /bin/sh;
538-
shellScript = "#set -e\n#echo \"Signing as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)\"\n#find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/site-packages\" -type f \\( -name \"*.so\" -o -name \"*.dylib\" \\) -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n";
533+
shellScript = "set -e\necho \"Signing as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)\"\nfind \"$CODESIGNING_FOLDER_PATH/Contents/Resources/site-packages\" -type f \\( -name \"*.so\" -o -name \"*.dylib\" \\) -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n";
539534
};
540535
/* End PBXShellScriptBuildPhase section */
541536

@@ -582,7 +577,6 @@
582577
isa = PBXSourcesBuildPhase;
583578
buildActionMask = 2147483647;
584579
files = (
585-
C8A3AE592A2885A70046E809 /* InitializePython.swift in Sources */,
586580
C861E6202994F63A0056CB02 /* ServiceDelegate.swift in Sources */,
587581
C861E6112994F6070056CB02 /* AppDelegate.swift in Sources */,
588582
);

ExtensionService/AppDelegate.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import FileChangeChecker
44
import LaunchAgentManager
55
import Logger
66
import Preferences
7+
import PythonHelper
78
import Service
89
import ServiceManagement
910
import ServiceUpdateMigration
@@ -43,10 +44,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
4344
NSApp.setActivationPolicy(.accessory)
4445
buildStatusBarMenu()
4546
DependencyUpdater().update()
46-
initializePython()
47+
4748
Task {
4849
do {
4950
try await ServiceUpdateMigrator().migrate()
51+
await initializePython()
5052
} catch {
5153
Logger.service.error(error.localizedDescription)
5254
}

ExtensionService/InitializePython.swift

Lines changed: 0 additions & 38 deletions
This file was deleted.

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ setup-langchain:
55
curl -L https://github.com/beeware/Python-Apple-support/releases/download/3.11-b1/Python-3.11-macOS-support.b1.tar.gz -o Python-3.11-macOS-support.b1.tar.gz; \
66
tar -xzvf Python-3.11-macOS-support.b1.tar.gz; \
77
rm Python-3.11-macOS-support.b1.tar.gz; \
8-
cp module.modulemap Python.xcframework/macos-arm64_x86_64/Headers/module.modulemap
8+
cp module.modulemap.copy Python.xcframework/macos-arm64_x86_64/Headers/module.modulemap
99
cd Python/site-packages; \
1010
sh ./install.sh
1111

12-
.PHONY: setup setup-langchain
12+
.PHONY: setup setup-langchain

Python/Package.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// swift-tools-version: 5.7
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "Python",
8+
platforms: [.macOS(.v12)],
9+
products: [
10+
.library(name: "Python", targets: ["Python", "PythonResources"]),
11+
],
12+
dependencies: [],
13+
targets: [
14+
.binaryTarget(name: "Python", path: "Python.xcframework"),
15+
.target(name: "PythonResources")
16+
]
17+
)
18+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import Foundation
2+
3+
let containingBundle: Bundle? = {
4+
if Bundle.main.path(forResource: "site-packages", ofType: nil) != nil {
5+
return Bundle.main
6+
}
7+
let path = Bundle.main.bundleURL
8+
.appendingPathComponent("Contents")
9+
.appendingPathComponent("Applications")
10+
.appendingPathComponent("CopilotForXcodeExtensionService.app").path
11+
12+
return Bundle(path: path)
13+
}()
14+
15+
public let sitePackagePath = containingBundle?.path(
16+
forResource: "site-packages",
17+
ofType: nil
18+
)
19+
public let stdLibPath = containingBundle?.path(
20+
forResource: "python-stdlib",
21+
ofType: nil
22+
)
23+
public let libDynloadPath = containingBundle?.path(
24+
forResource: "python-stdlib/lib-dynload",
25+
ofType: nil
26+
)
27+

Tool/Package.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ let package = Package(
1414
.library(name: "OpenAIService", targets: ["OpenAIService"]),
1515
],
1616
dependencies: [
17+
.package(path: "../Python"),
1718
.package(url: "https://github.com/pvieito/PythonKit.git", branch: "master"),
1819
.package(url: "https://github.com/alfianlosari/GPTEncoder", from: "1.0.4"),
1920
.package(url: "https://github.com/apple/swift-async-algorithms", from: "0.1.0"),
20-
.package(url: "https://github.com/pointfreeco/swift-parsing", from: "0.12.1")
21+
.package(url: "https://github.com/pointfreeco/swift-parsing", from: "0.12.1"),
2122
],
2223
targets: [
2324
// MARK: - Helpers
@@ -47,6 +48,7 @@ let package = Package(
4748
.target(
4849
name: "PythonHelper",
4950
dependencies: [
51+
.product(name: "Python", package: "Python"),
5052
.product(name: "PythonKit", package: "PythonKit"),
5153
]
5254
),

Tool/Sources/Logger/Logger.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public final class Logger {
1818
public static let gitHubCopilot = Logger(category: "GitHubCopilot")
1919
public static let codeium = Logger(category: "Codeium")
2020
public static let langchain = Logger(category: "LangChain")
21+
public static let python = Logger(category: "Python")
2122
#if DEBUG
2223
public static let temp = Logger(category: "Temp")
2324
#endif
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import Foundation
2+
import Logger
3+
import Python
4+
import PythonKit
5+
import PythonResources
6+
7+
@PythonActor
8+
var isPythonInitialized = false
9+
10+
/// Initialize Python.
11+
@PythonActor
12+
public func initializePython() {
13+
guard !isPythonInitialized else { return }
14+
guard let sitePackagePath, let stdLibPath, let libDynloadPath else {
15+
assertionFailure("Python is not installed! Please run `make setup` to install Python.")
16+
Logger.python.info("Python is not installed!")
17+
return
18+
}
19+
setenv("PYTHONHOME", stdLibPath, 1)
20+
setenv("PYTHONPATH", "\(stdLibPath):\(libDynloadPath):\(sitePackagePath)", 1)
21+
setenv("PYTHONIOENCODING", "utf-8", 1)
22+
// Initialize python
23+
Py_Initialize()
24+
isPythonInitialized = true
25+
// Immediately release the thread, so that we can ensure the GIL state later.
26+
_ = PyEval_SaveThread()
27+
28+
Task {
29+
// All future task should run inside runPython.
30+
try runPython {
31+
let sys = Python.import("sys")
32+
Logger.service
33+
.info("Python Version: \(sys.version_info.major).\(sys.version_info.minor)")
34+
}
35+
}
36+
}
37+

0 commit comments

Comments
 (0)