import __pyto_ui_garbage_collector__ as _gc c = ctypes.CDLL(None) def raise_exception(script, exception): for tid, tobj in threading._active.items(): try: if tobj.script_path == script: stopit.async_raise(tid, exception) break except: continue NSAutoreleasePool = ObjCClass("NSAutoreleasePool") class Thread(threading.Thread): # Pass the 'script_path' attribute def start(self): if "script_path" not in dir(self): try: self.script_path = threading.current_thread().script_path except AttributeError: pass super().start() def run(self):
def test_partial_method_one_arg(self): Example = ObjCClass("Example") self.assertEqual(Example.overloaded(42), 42)
def test_interface(self): "An ObjC protocol implementation can be defined in Python." Callback = ObjCProtocol('Callback') results = {} class Handler(NSObject, protocols=[Callback]): @objc_method def initWithValue_(self, value: int): self.value = value return self @objc_method def peek_withValue_(self, example, value: int) -> None: results['string'] = example.toString() + " peeked" results['int'] = value + self.value @objc_method def poke_withValue_(self, example, value: int) -> None: results['string'] = example.toString() + " poked" results['int'] = value + self.value @objc_method def reverse_(self, input): return ''.join(reversed(input)) @objc_method def message(self): return "Alea iacta est." @objc_classmethod def fiddle_(cls, value: int) -> None: results['string'] = "Fiddled with it" results['int'] = value # Check that the protocol is adopted. self.assertSequenceEqual(Handler.protocols, (Callback,)) # Create two handler instances so we can check the right one # is being invoked. handler1 = Handler.alloc().initWithValue_(5) handler2 = Handler.alloc().initWithValue_(10) # Create an Example object, and register a handler with it. Example = ObjCClass('Example') example = Example.alloc().init() example.callback = handler2 # Check some Python-side attributes self.assertEqual(handler1.value, 5) self.assertEqual(handler2.value, 10) # Invoke the callback; check that the results have been peeked as expected example.testPeek_(42) self.assertEqual(results['string'], 'This is an ObjC Example object peeked') self.assertEqual(results['int'], 52) example.testPoke_(37) self.assertEqual(results['string'], 'This is an ObjC Example object poked') self.assertEqual(results['int'], 47) self.assertEqual(example.getMessage(), 'Alea iacta est.') self.assertEqual(example.reverseIt_('Alea iacta est.'), '.tse atcai aelA') Handler.fiddle_(99) self.assertEqual(results['string'], 'Fiddled with it') self.assertEqual(results['int'], 99)
def test_float_method(self): "A method with a float argument can be handled." Example = ObjCClass('Example') example = Example.alloc().init() self.assertEqual(example.areaOfSquare_(1.5), 2.25)
def test_double_method(self): "A method with a double argument can be handled." Example = ObjCClass('Example') example = Example.alloc().init() self.assertAlmostEqual(example.areaOfCircle_(1.5), 1.5 * math.pi, 5)
def test_string_argument(self): "A method with a string argument can be passed." Example = ObjCClass('Example') example = Example.alloc().init() self.assertEqual(example.duplicateString_("Wagga"), "WaggaWagga")
def test_string_return(self): "If a method or field returns a string, you get a Python string back" Example = ObjCClass('Example') example = Example.alloc().init() self.assertEqual(example.toString(), "This is an ObjC Example object")
# local imports from . import factory from .constants import ( NSStackViewGravityBottom, NSUserInterfaceLayoutOrientationVertical, NSWindowAnimationBehaviorAlertPanel, ) alert_style_for_level_str = { "info": NSAlertStyle.Informational, "warning": NSAlertStyle.Warning, "error": NSAlertStyle.Critical, } NSStackView = ObjCClass("NSStackView") def _construct_alert( title, message, details=None, details_title="Traceback", button_labels=("Ok", ), checkbox_text=None, level="info", icon=None, ): a = NSAlert.alloc().init() a.alertStyle = alert_style_for_level_str[level] a.messageText = title
""" Save values on disk This module makes possible to save values on disk. Values are shared between the Today Widget and the main app. Values are stored in a JSON dictionary, so it's not possible to save every type of data. """ from rubicon.objc import ObjCClass import json NSUserDefaults = ObjCClass("NSUserDefaults") userDefaults = NSUserDefaults.alloc().initWithSuiteName("group.pyto") if userDefaults.valueForKey("userKeys") is None: userDefaults.setValue("{}", forKey="userKeys") def __dictionary__(): return json.loads(str(userDefaults.valueForKey("userKeys"))) def get(key: str): """ Returns the value stored with the given key. :param key: The key identifying the value. """ return __dictionary__()[key]
class NSArrayMixinTest(unittest.TestCase): nsarray = ObjCClass('NSArray') nsmutablearray = ObjCClass('NSMutableArray') py_list = ['one', 'two', 'three'] def make_array(self, contents=None): a = self.nsmutablearray.alloc().init() if contents is not None: for value in contents: a.addObject(value) return self.nsarray.arrayWithArray(a) def test_getitem(self): a = self.make_array(self.py_list) for pos, value in enumerate(self.py_list): self.assertEqual(a[pos], value) with self.assertRaises(IndexError): a[len(self.py_list) + 10] def test_len(self): a = self.make_array(self.py_list) self.assertEqual(len(a), len(self.py_list)) def test_iter(self): a = self.make_array(self.py_list) keys = list(self.py_list) for k in a: self.assertTrue(k in keys) keys.remove(k) self.assertTrue(len(keys) == 0) def test_contains(self): a = self.make_array(self.py_list) for value in self.py_list: self.assertTrue(value in a) def test_index(self): a = self.make_array(self.py_list) self.assertEqual(a.index('two'), 1) with self.assertRaises(ValueError): a.index('umpteen') def test_count(self): a = self.make_array(self.py_list) self.assertEqual(a.count('one'), 1) def test_copy(self): a = self.make_array(self.py_list) b = a.copy() self.assertEqual(b, a) self.assertEqual(b, self.py_list) with self.assertRaises(AttributeError): b.append('four') def test_equivalence(self): a = self.make_array(self.py_list) b = self.make_array(self.py_list) self.assertEqual(a, self.py_list) self.assertEqual(b, self.py_list) self.assertEqual(a, b) self.assertEqual(self.py_list, a) self.assertEqual(self.py_list, b) self.assertEqual(b, a) def test_slice_access(self): a = self.make_array(self.py_list * 2) self.assertEqual(a[1:4], ['two', 'three', 'one']) self.assertEqual(a[:-2], ['one', 'two', 'three', 'one']) self.assertEqual(a[4:], ['two', 'three']) self.assertEqual(a[1:5:2], ['two', 'one'])
def test_double_method_send(self): "A method with a double argument can be handled by send_message." Example = ObjCClass('Example') example = Example.alloc().init() self.assertAlmostEqual(send_message(example, "areaOfCircle:", 1.5, restype=c_double, argtypes=[c_double]), 1.5 * math.pi, 5)
def test_block_receiver_lambda(self): BlockReceiverExample = ObjCClass("BlockReceiverExample") instance = BlockReceiverExample.alloc().init() with self.assertRaises(ValueError): instance.receiverMethod_(lambda a, b: a + b)
def test_block_property_pytypes(self): BlockPropertyExample = ObjCClass("BlockPropertyExample") instance = BlockPropertyExample.alloc().init() result = ObjCBlock(instance.blockProperty, int, int, int)(1, 2) self.assertEqual(result, 3)
class NSDictionaryMixinTest(unittest.TestCase): nsdict = ObjCClass('NSDictionary') nsmutabledict = ObjCClass('NSMutableDictionary') py_dict = { 'one': 'ONE', 'two': 'TWO', 'three': 'THREE', } def make_dictionary(self, contents=None): d = self.nsmutabledict.alloc().init() if contents is not None: for key, value in contents.items(): d.setObject_forKey_(value, key) return self.nsdict.dictionaryWithDictionary(d) def test_getitem(self): d = self.make_dictionary(self.py_dict) for key, value in self.py_dict.items(): self.assertEqual(d[key], value) with self.assertRaises(KeyError): d['NO SUCH KEY'] def test_iter(self): d = self.make_dictionary(self.py_dict) keys = set(self.py_dict) for k in d: self.assertTrue(k in keys) keys.remove(k) self.assertTrue(len(keys) == 0) def test_len(self): d = self.make_dictionary(self.py_dict) self.assertEqual(len(d), len(self.py_dict)) def test_get(self): d = self.make_dictionary(self.py_dict) self.assertEqual(d.get('one'), 'ONE') self.assertEqual(d.get('two', None), 'TWO') self.assertEqual(d.get('four', None), None) self.assertEqual(d.get('five', 5), 5) self.assertEqual(d.get('six', None), None) def test_contains(self): d = self.make_dictionary(self.py_dict) for key in self.py_dict: self.assertTrue(key in d) def test_copy(self): d = self.make_dictionary(self.py_dict) e = d.copy() self.assertEqual(e, d) self.assertEqual(e, self.py_dict) with self.assertRaises(TypeError): e['four'] = 'FOUR' def test_keys(self): a = self.make_dictionary(self.py_dict) for k1, k2 in zip(sorted(a.keys()), sorted(self.py_dict.keys())): self.assertEqual(k1, k2) def test_values(self): a = self.make_dictionary(self.py_dict) for v1, v2 in zip(sorted(a.values()), sorted(self.py_dict.values())): self.assertEqual(v1, v2) def test_items(self): d = self.make_dictionary(self.py_dict) for i1, i2 in zip(sorted(d.items()), sorted(self.py_dict.items())): self.assertEqual(i1[0], i2[0]) self.assertEqual(i1[1], i2[1])
def test_class_by_name(self): """An Objective-C class can be looked up by name.""" Example = ObjCClass("Example") self.assertEqual(Example.name, "Example")
import logging from typing import Type, Optional, Dict, Tuple # external imports from packaging.version import Version from rubicon.objc import ObjCClass, objc_method, py_from_ns # type: ignore from rubicon.objc.runtime import load_library, objc_id # type: ignore # local imports from .notify_base import Notification, DesktopNotifierBase from ..constants import FROZEN logger = logging.getLogger(__name__) foundation = load_library("Foundation") NSObject = ObjCClass("NSObject") macos_version, *_ = platform.mac_ver() Impl: Optional[Type[DesktopNotifierBase]] = None if FROZEN and Version(macos_version) >= Version("10.14.0"): # use UNUserNotificationCenter in macOS Mojave and higher if we are in an app bundle uns = load_library("UserNotifications") UNUserNotificationCenter = ObjCClass("UNUserNotificationCenter") UNMutableNotificationContent = ObjCClass("UNMutableNotificationContent") UNNotificationRequest = ObjCClass("UNNotificationRequest") UNNotificationAction = ObjCClass("UNNotificationAction")
def test_class_by_pointer(self): """An Objective-C class can be created from a pointer.""" example_ptr = libobjc.objc_getClass(b"Example") Example = ObjCClass(example_ptr) self.assertEqual(Example, ObjCClass("Example"))
""" Module used internally by Pyto for importing C extension. """ import sys import importlib import traceback import os import warnings from rubicon.objc import ObjCClass import _extensionsimporter import ctypes from importlib import util, __import__ from importlib.machinery import ExtensionFileLoader, ModuleSpec, PathFinder NSBundle = ObjCClass("NSBundle") class __UpgradeException__(Exception): pass if "widget" not in os.environ: from sharing import open_url import urllib.parse from pyto import Python, __Class__ def have_internet(): return __Class__("InternetConnection").isReachable def update_mods():
def test_nonexistant_class(self): """A NameError is raised if a class doesn't exist.""" with self.assertRaises(NameError): ObjCClass('DoesNotExist')
import threading import base64 import os from typing import List try: from rubicon.objc import ObjCClass from rubicon.objc.api import NSString except ValueError: def ObjCClass(class_name): return None __PySharingHelper__ = pyto.PySharingHelper NSURL = ObjCClass("NSURL") def share_items(items: object): """ Opens a share sheet with given items. :param items: Items to be shared with the sheet. """ __PySharingHelper__.share(items) if "widget" not in os.environ: def quick_look(path: str, remove_previous: bool = False):
def test_constant_string_return(self): "If a method or field returns a *constant* string, you get a Python string back" Example = ObjCClass('Example') example = Example.alloc().init() self.assertEqual(example.smiley(), "%-)")
try: import sys import importlib from rubicon.objc import ObjCClass ObjCClass("ExtensionsInitializer").alloc().init().initialize_cv2() modname = "__cv2_cv2" if modname not in sys.builtin_module_names: sys.builtin_module_names += (modname,) import __cv2_cv2 as cv2 from . import data from .data import * # wildcard import above does not import "private" variables like __version__ # this makes them available globals().update(cv2.__dict__) except ImportError as e: # For documentation print(e) except AttributeError as e: print(e) def autorotate(frame, cam): """ Returns an auto rotated frame captured with hardware camera. By default, frames captured by hardware camera will be rotated correctly only if the device is in portrait mode. By calling this function, you can make sure things like face detection will work on any device orientation. :param frame: The frame captured by the camera. :param cam: The camera used to capture the frame. ``0`` for back and ``1`` for front.
def test_float_method_send(self): "A method with a float argument can be handled by send_message." Example = ObjCClass('Example') example = Example.alloc().init() self.assertEqual(send_message(example, "areaOfSquare:", 1.5, restype=c_float, argtypes=[c_float]), 2.25)
Use the ``notifications`` to schedule notifications that can be delivered even if Pyto isn't opened. """ from pyto import __Class__ from typing import List from __check_type__ import check try: from rubicon.objc import ObjCClass except ValueError: pass __PyNotificationCenter__ = __Class__("PyNotificationCenter") try: UNUserNotificationCenter = ObjCClass("UNUserNotificationCenter") """ The 'UNUserNotificationCenter' class from the ``UserNotifications`` framework. """ except NameError: UNUserNotificationCenter = None """ The 'UNUserNotificationCenter' class from the ``UserNotifications`` framework. """ class Notification: """ A class representing a notification. """
def test_partial_method_no_args(self): Example = ObjCClass("Example") self.assertEqual(Example.overloaded(), 0)
def test_interface_return_struct(self): "An ObjC protocol implementation that returns values by struct can be defined in Python." results = {} Thing = ObjCClass("Thing") class StructReturnHandler(Thing): @objc_method def initWithValue_(self, value): self.value = py_from_ns(value) return self @objc_method def computeSize_(self, input: NSSize) -> NSSize: results['size'] = True sup = send_super(__class__, self, 'computeSize:', input, restype=NSSize, argtypes=[NSSize]) return NSSize(input.width + self.value, sup.height) @objc_method def computeRect_(self, input: NSRect) -> NSRect: results['rect'] = True sup = send_super(__class__, self, 'computeRect:', input, restype=NSRect, argtypes=[NSRect]) return NSMakeRect( input.origin.y + self.value, sup.origin.x, input.size.height + self.value, sup.size.width ) # Register a second method returning NSSize. Don't # have to use it - just have to register that it exists. @objc_method def origin(self) -> NSSize: return NSSize(0, 0) # Create two handler instances so we can check the right one # is being invoked. handler1 = StructReturnHandler.alloc().initWithValue_(5) handler2 = StructReturnHandler.alloc().initWithValue_(10) outSize = handler1.computeSize(NSSize(20, 30)) self.assertEqual(outSize.width, 25) self.assertEqual(outSize.height, 90) self.assertTrue(results.get('size')) outRect = handler2.computeRect(NSMakeRect(10, 20, 30, 40)) self.assertEqual(outRect.origin.x, 30) self.assertEqual(outRect.origin.y, 110) self.assertEqual(outRect.size.width, 50) self.assertEqual(outRect.size.height, 60) self.assertTrue(results.get('rect')) # Invoke a method through an interface. Example = ObjCClass("Example") obj = Example.alloc().init() # Test the base class directly thing1 = Thing.alloc().init() obj.thing = thing1 outSize = obj.testThing(10) self.assertEqual(outSize.width, 0) self.assertEqual(outSize.height, 30) # Test the python handler obj.thing = handler1 outSize = obj.testThing(15) self.assertEqual(outSize.width, 5) self.assertEqual(outSize.height, 45)
def test_partial_method_two_args(self): Example = ObjCClass("Example") self.assertEqual(Example.overloaded(12, extraArg=34), 12+34)
def test_objcclass_requires_class(self): """ObjCClass only accepts class pointers.""" random_obj = NSObject.alloc().init() with self.assertRaises(ValueError): ObjCClass(random_obj.ptr)
def _Class(name): try: return ObjCClass(name) except NameError: return None
import music music.set_queue_with_items(music.pick_music()) music.play() """ from pyto_ui import __pil_image_from_ui_image__ from typing import List from pyto import PyMusicHelper from ctypes import cdll import PIL import threading try: from rubicon.objc import ObjCClass MPMusicPlayerController = ObjCClass("MPMusicPlayerController") """ The 'MPMusicPlayerController' class from the 'MediaPlayer' framework. """ MPMediaItem = ObjCClass("MPMediaItem") """ The 'MPMediaItem' class from the 'MediaPlayer' framework. """ MPMediaItemCollection = ObjCClass("MPMediaItemCollection") """ The 'MPMediaItemCollection' class from the 'MediaPlayer' framework. """ MPMediaQuery = ObjCClass("MPMediaQuery") """ The 'MPMusicMPMediaQueryPlayerController' class from the 'MediaPlayer' framework. """ MediaPlayer = cdll.LoadLibrary( "/System/Library/Frameworks/MediaPlayer.framework/MediaPlayer") except (NameError, ValueError): MPMusicPlayerController = "MPMusicPlayerController"