Managing Site Packages
Overview
This guide covers how to add Python packages to your PSProject using both uv commands and manual pyproject.toml editing. These packages will be included when you run psproject update site-packages to sync dependencies to your iOS/macOS Xcode project.
Using UV Commands
The uv package manager provides convenient commands to add dependencies to your project.
Add by Package Name
Add the latest version of a package:
This adds the package to [project.dependencies] in pyproject.toml:
Add by Specific Version
Add a package with a specific version constraint:
# Exact version
uv add "pillow==10.0.0"
# Minimum version
uv add "kivy>=2.3.1"
# Version range
uv add "numpy>=1.24.0,<2.0.0"
Results in:
Add by Git Branch
Add a package directly from a Git branch:
# From main branch
uv add "git+https://github.com/kivy/kivy.git@main"
# From specific branch
uv add "git+https://github.com/username/package.git@feature-branch"
# With subdirectory
uv add "git+https://github.com/username/monorepo.git@main#subdirectory=packages/mypackage"
Results in:
[project]
dependencies = [
"kivy @ git+https://github.com/kivy/kivy.git@main",
"package @ git+https://github.com/username/package.git@feature-branch",
]
Add by Git Tag or Commit
Add a package from a specific tag or commit hash:
# By tag
uv add "git+https://github.com/username/package.git@v1.2.3"
# By commit hash
uv add "git+https://github.com/username/package.git@abc123def"
Add by URL
Add a package from a direct URL:
# From archive URL
uv add "https://github.com/username/package/archive/refs/tags/v1.0.0.tar.gz"
# From zip file
uv add "https://example.com/packages/mypackage-1.0.0.zip"
Results in:
[project]
dependencies = [
"package @ https://github.com/username/package/archive/refs/tags/v1.0.0.tar.gz",
]
Add by Wheel URL
Add a pre-built wheel directly:
# From direct wheel URL
uv add "https://example.com/wheels/mypackage-1.0.0-py3-none-any.whl"
# Platform-specific wheel
uv add "https://example.com/wheels/numpy-1.24.0-cp313-cp313-macosx_11_0_arm64.whl"
Results in:
[project]
dependencies = [
"mypackage @ https://example.com/wheels/mypackage-1.0.0-py3-none-any.whl",
]
Add Development Dependencies
Add packages only needed for development:
Results in:
Add Platform-Specific Dependencies
Add dependencies for specific platforms:
# Add to iOS group
uv add --group iphoneos pyobjus
# Add to Android group (if using buildozer)
uv add --group android pyjnius
Results in:
Manual pyproject.toml Editing
You can also manually edit pyproject.toml to add or modify dependencies. This is useful for complex version constraints or when you need fine-grained control.
Basic Dependencies
Edit the [project.dependencies] section:
[project]
dependencies = [
"kivy>=2.3.1",
"pillow>=10.0.0",
"requests>=2.31.0,<3.0.0",
"python-dotenv==1.0.0",
]
Git Repository Dependencies
Specify Git repositories with various options:
[project]
dependencies = [
# From branch
"mypackage @ git+https://github.com/username/mypackage.git@main",
# From tag
"anotherpackage @ git+https://github.com/username/anotherpackage.git@v1.2.3",
# From commit hash
"thirdpackage @ git+https://github.com/username/thirdpackage.git@abc123def456",
# With subdirectory
"subpackage @ git+https://github.com/username/monorepo.git@main#subdirectory=packages/subpackage",
# SSH URL (requires SSH keys)
"privatepackage @ git+ssh://git@github.com/username/privatepackage.git@main",
]
Direct URL Dependencies
Specify packages from direct URLs:
[project]
dependencies = [
# Archive URLs
"package1 @ https://github.com/user/pkg/archive/refs/tags/v1.0.0.tar.gz",
"package2 @ https://example.com/downloads/package2-2.1.0.zip",
# Wheel URLs
"package3 @ https://example.com/wheels/package3-1.0.0-py3-none-any.whl",
# Platform-specific wheels
"numpy @ https://files.pythonhosted.org/packages/.../numpy-1.24.0-cp313-cp313-macosx_11_0_arm64.whl",
]
Local Path Dependencies
Reference local packages during development:
[project]
dependencies = [
# Relative path
"mylocalpackage @ file:../mylocalpackage",
# Absolute path
"anotherlocal @ file:///Users/username/projects/anotherlocal",
# Editable install (development mode)
"mydevpackage @ file:../mydevpackage#egg=mydevpackage&editable=true",
]
Local paths are not portable
Local path dependencies won't work on other machines or in CI/CD. Use them only for local development and testing.
Dependency Groups
Organize dependencies by purpose:
[dependency-groups]
dev = [
"pytest>=7.0.0",
"pytest-cov>=4.0.0",
"black>=23.0.0",
"mypy>=1.0.0",
"ruff>=0.1.0",
]
iphoneos = [
"pyobjus>=1.2.0",
"rubicon-objc>=0.4.0",
]
android = [
"pyjnius>=1.4.0",
]
docs = [
"mkdocs>=1.5.0",
"mkdocs-material>=9.0.0",
]
Optional Dependencies
Define optional feature sets:
[project.optional-dependencies]
audio = [
"pyaudio>=0.2.13",
"sounddevice>=0.4.6",
]
video = [
"opencv-python>=4.8.0",
"ffmpeg-python>=0.2.0",
]
all = [
"pyaudio>=0.2.13",
"sounddevice>=0.4.6",
"opencv-python>=4.8.0",
"ffmpeg-python>=0.2.0",
]
Install optional dependencies:
# Install specific feature
uv sync --extra audio
# Install all optional dependencies
uv sync --extra all
Platform-Specific Markers
Use environment markers for platform-specific dependencies:
[project]
dependencies = [
"pywin32>=305; platform_system == 'Windows'",
"pyobjc-framework-Cocoa>=9.0; platform_system == 'Darwin'",
"python-xlib>=0.33; platform_system == 'Linux'",
]
Common markers:
- platform_system: 'Windows', 'Darwin', 'Linux'
- sys_platform: 'win32', 'darwin', 'linux'
- python_version: '3.13', '3.12', etc.
- platform_machine: 'x86_64', 'arm64', etc.
Syncing Dependencies
After adding dependencies, sync them to your project:
Sync All Dependencies
Sync with Development Dependencies
Sync with Specific Groups
Update Site Packages for iOS/macOS
After syncing, update your Xcode project:
This copies the installed packages to your iOS/macOS project's site-packages directory.
Complete Example
Here's a complete pyproject.toml with various dependency types:
[project]
name = "MyKivyApp"
version = "1.0.0"
requires-python = ">=3.13"
dependencies = [
# PyPI packages
"kivy>=2.3.1",
"kivymd>=1.1.1",
"pillow>=10.0.0",
"requests>=2.31.0,<3.0.0",
# Git repository
"custom-lib @ git+https://github.com/username/custom-lib.git@main",
# Specific version from Git
"experimental @ git+https://github.com/username/experimental.git@v0.5.0-beta",
# Direct URL
"special-package @ https://example.com/packages/special-package-1.2.0.tar.gz",
# Wheel URL
"optimized-lib @ https://example.com/wheels/optimized_lib-2.0.0-cp313-cp313-macosx_11_0_arm64.whl",
# Platform-specific
"pyobjus>=1.2.0; platform_system == 'Darwin'",
]
[project.optional-dependencies]
audio = ["pyaudio>=0.2.13"]
video = ["opencv-python>=4.8.0"]
all = ["pyaudio>=0.2.13", "opencv-python>=4.8.0"]
[dependency-groups]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"mypy>=1.0.0",
]
iphoneos = [
"rubicon-objc>=0.4.0",
]
[build-system]
requires = ["uv_build>=0.9.2,<0.10.0"]
build-backend = "uv_build"
Workflow Example
Here's a typical workflow for adding and managing dependencies:
# 1. Initialize project
psproject init MyApp
cd MyApp
# 2. Add main dependencies
uv add kivy
uv add kivymd
uv add pillow
# 3. Add from Git repository
uv add "git+https://github.com/username/custom-widget.git@main"
# 4. Add development tools
uv add --dev pytest
uv add --dev black
# 5. Add iOS-specific dependency
uv add --group iphoneos pyobjus
# 6. Sync all dependencies
uv sync --all-groups
# 7. Create Xcode project
psproject create xcode
# 8. Update site-packages in Xcode project
psproject update site-packages
# 9. Build in Xcode
# Open project_dist/xcode/MyApp.xcodeproj and build
Best Practices
Version Pinning
For production apps, use specific version constraints to ensure reproducible builds:
Use UV Lock File
The uv.lock file ensures all developers use the same dependency versions. Commit it to version control:
Separate Development Dependencies
Keep development tools separate from production dependencies:
Test After Adding Dependencies
Always test after adding new dependencies:
Wheel Compatibility
When using wheel URLs, ensure they match your target platform:
- iOS: Use wheels built for the iOS platform (if available)
- Check wheel tags: cp313 (Python 3.13), abi3 (stable ABI), macosx_11_0_arm64 (macOS ARM64)
Troubleshooting
Dependency Conflicts
If you encounter version conflicts:
Missing Packages in Xcode
If packages don't appear in your iOS project:
# Force update site-packages
psproject update site-packages --force
# Check package installation
uv list
Git Authentication Issues
For private repositories:
# Use SSH instead of HTTPS
uv add "git+ssh://git@github.com/username/private-repo.git@main"
# Or use personal access token in URL
uv add "git+https://TOKEN@github.com/username/private-repo.git@main"
Wheel Not Found
If a wheel isn't available for your platform:
# Install from source
uv add --no-binary mypackage mypackage
# Or build wheel locally
uv build /path/to/package
uv add ./dist/mypackage-1.0.0-py3-none-any.whl