PyObjC Framework NetworkExtension
PyObjC Framework NetworkExtension provides Python wrappers for Apple's NetworkExtension framework on macOS. It enables Python applications to interact with system-level networking features, such as VPN configuration and management. Currently at version 12.1, this library is part of the larger PyObjC project, which generally aligns its release cadence with new macOS SDK versions.
Warnings
- breaking PyObjC 12.0 (and thus pyobjc-framework-networkextension 12.0) dropped support for Python 3.9. PyObjC 11.0 dropped support for Python 3.8. Ensure your Python version meets the `requires_python` specification (currently >=3.10).
- breaking Starting with PyObjC 11.1, the core bridge's Automatic Reference Counting (ARC) behavior for Objective-C initializer methods (`init` family) was aligned with `clang`'s documentation. This means `init` methods now correctly 'steal' a reference to `self` and return a new one. This can affect custom Objective-C classes implemented in Python, particularly in how references are managed during initialization.
- gotcha PyObjC 10.3 initially removed support for calling `__init__` when a user-defined `__new__` was present in an Objective-C class implemented in Python. While 10.3.1 re-enabled this for user-implemented `__new__`, `__init__` still cannot be used when relying on PyObjC's *default* `__new__` implementation.
- breaking Framework bindings can be removed following Apple's deprecation schedule. For example, `IMServicePlugIn` bindings were removed in PyObjC 10.0 because the framework was deprecated in macOS 10.13 and removed in macOS 14.
- gotcha As of PyObjC 10.1, `os.fspath(someURL)` will raise a `TypeError` if the provided Cocoa `NSURL` or `CFURLRef` object does *not* refer to a local filesystem path. It correctly works for local filesystem paths, enabling their use with Python's filesystem APIs.
- gotcha Experimental free-threading support (PEP 703) introduced in Python 3.13 is *experimentally* supported by PyObjC 11.0. Older versions like 10.3 explicitly stated they did not support it. While `pyobjc-core` 12.1 is listed as compatible with 'Python :: Free Threading :: 3 - Stable' on PyPI, users should exercise caution with experimental features.
Install
-
pip install pyobjc-framework-NetworkExtension
Imports
- NetworkExtension
import NetworkExtension
- NEVPNManager
from NetworkExtension import NEVPNManager
Quickstart
import NetworkExtension
import objc
from Foundation import NSLog
import threading
# Note: Accessing NetworkExtension APIs typically requires specific
# entitlements in your application's Info.plist and proper code signing.
# This script may require root privileges or fail without them.
def completion_handler(managers, error):
if error:
NSLog('Error loading VPN configurations: %@', error)
elif managers:
NSLog('Found %d VPN configurations:', len(managers))
for manager in managers:
NSLog(' - Name: %@, Enabled: %@', manager.localizedDescription(), 'Yes' if manager.enabled() else 'No')
else:
NSLog('No VPN configurations found.')
# Signal that the async operation is complete
completion_event.set()
NSLog('Attempting to load VPN configurations...')
# Use a threading.Event to wait for the asynchronous callback in a script
completion_event = threading.Event()
manager_class = NetworkExtension.NEVPNManager
manager = manager_class.sharedManager()
# loadAllFromPreferencesWithCompletionHandler_ is an asynchronous call.
# The Objective-C block is automatically translated to a Python callable.
manager.loadAllFromPreferencesWithCompletionHandler_(completion_handler)
# Wait for the completion handler to be called (max 5 seconds)
completion_event.wait(5.0)
NSLog('Quickstart finished.')