def notify(title, subtitle, text, bundleid=None, url=None):
    if bundleid:
        # fake our bundleid
        set_fake_bundleid(bundleid)

    # create a new user notification
    notification = NSUserNotification.alloc().init()
    notification.setTitle_(title)
    notification.setSubtitle_(subtitle)
    notification.setInformativeText_(text)
    if url:
        userInfo = NSDictionary.dictionaryWithDictionary_({
            'action': u'open_url',
            'value': unicode(url)
        })
        notification.setUserInfo_(userInfo)
    notification.setHasActionButton_(True)
    notification.setActionButtonTitle_('Details')

    # get the default User Notification Center
    nc = NSUserNotificationCenter.defaultUserNotificationCenter()

    # create a delegate object that implements our delegate methods
    my_delegate = NotificationCenterDelegate.alloc().init()
    nc.setDelegate_(my_delegate)

    nc.removeAllDeliveredNotifications()
    # deliver the notification
    nc.deliverNotification_(notification)

    # keep running until the notification is activated
    while (my_delegate.keepRunning):
        NSRunLoop.currentRunLoop().runUntilDate_(
            NSDate.dateWithTimeIntervalSinceNow_(0.1))
Example #2
0
    def __init__(self):
        """return existing singleton or create a new one"""

        if hasattr(self, "context"):
            return
        """ initialize CIContext """
        context_options = NSDictionary.dictionaryWithDictionary_({
            "workingColorSpace":
            Quartz.CoreGraphics.kCGColorSpaceExtendedSRGB,
            "workingFormat":
            Quartz.kCIFormatRGBAh,
        })
        self.context = Quartz.CIContext.contextWithOptions_(context_options)
Example #3
0
    def __init__(self):
        """ return existing singleton or create a new one """

        if hasattr(self, "context"):
            return
        """ initialize CIContext """
        context_options = NSDictionary.dictionaryWithDictionary_({
            "workingColorSpace":
            Quartz.CoreGraphics.kCGColorSpaceExtendedSRGB,
            "workingFormat":
            Quartz.kCIFormatRGBAh,
        })
        mtldevice = Metal.MTLCreateSystemDefaultDevice()
        self.context = Quartz.CIContext.contextWithMTLDevice_options_(
            mtldevice, context_options)
Example #4
0
def detect_text(img_path: str, orientation: Optional[int] = None) -> List:
    """process image at img_path with VNRecognizeTextRequest and return list of results

    Args:
        img_path: path to the image file
        orientation: optional EXIF orientation (if known, passing orientation may improve quality of results)
    """
    if not vision:
        logging.warning(
            f"detect_text not implemented for this version of macOS")
        return []

    with objc.autorelease_pool():
        input_url = NSURL.fileURLWithPath_(img_path)

        with pipes() as (out, err):
            # capture stdout and stderr from system calls
            # otherwise, Quartz.CIImage.imageWithContentsOfURL_
            # prints to stderr something like:
            # 2020-09-20 20:55:25.538 python[73042:5650492] Creating client/daemon connection: B8FE995E-3F27-47F4-9FA8-559C615FD774
            # 2020-09-20 20:55:25.652 python[73042:5650492] Got the query meta data reply for: com.apple.MobileAsset.RawCamera.Camera, response: 0
            input_image = Quartz.CIImage.imageWithContentsOfURL_(input_url)

        vision_options = NSDictionary.dictionaryWithDictionary_({})
        if orientation is not None:
            if not 1 <= orientation <= 8:
                raise ValueError("orientation must be between 1 and 8")
            vision_handler = Vision.VNImageRequestHandler.alloc(
            ).initWithCIImage_orientation_options_(input_image, orientation,
                                                   vision_options)
        else:
            vision_handler = (
                Vision.VNImageRequestHandler.alloc().initWithCIImage_options_(
                    input_image, vision_options))
        results = []
        handler = make_request_handler(results)
        vision_request = (Vision.VNRecognizeTextRequest.alloc().
                          initWithCompletionHandler_(handler))
        error = vision_handler.performRequests_error_([vision_request], None)
        vision_request.dealloc()
        vision_handler.dealloc()

        for result in results:
            result[0] = str(result[0])

        return results
Example #5
0
    def write_jpeg(self, input_path, output_path, compression_quality=1.0):
        """convert image to jpeg and write image to output_path

        Args:
            input_path: path to input image (e.g. '/path/to/import/file.CR2') as str or pathlib.Path
            output_path: path to exported jpeg (e.g. '/path/to/export/file.jpeg') as str or pathlib.Path
            compression_quality: JPEG compression quality, float in range 0.0 to 1.0; default is 1.0 (best quality)

        Return:
            True if conversion successful, else False

        Raises:
            ValueError if compression quality not in range 0.0 to 1.0
            FileNotFoundError if input_path doesn't exist
            ImageConversionError if error during conversion
        """

        # Set up a dedicated objc autorelease pool for this function call.
        # This is to ensure that all the NSObjects are cleaned up after each
        # call to prevent memory leaks.
        # https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
        # https://pyobjc.readthedocs.io/en/latest/api/module-objc.html#memory-management
        with objc.autorelease_pool():
            # accept input_path or output_path as pathlib.Path
            if not isinstance(input_path, str):
                input_path = str(input_path)

            if not isinstance(output_path, str):
                output_path = str(output_path)

            if not pathlib.Path(input_path).is_file():
                raise FileNotFoundError(f"could not find {input_path}")

            if not (0.0 <= compression_quality <= 1.0):
                raise ValueError(
                    "illegal value for compression_quality: {compression_quality}"
                )

            input_url = NSURL.fileURLWithPath_(input_path)
            output_url = NSURL.fileURLWithPath_(output_path)

            with pipes() as (out, err):
                # capture stdout and stderr from system calls
                # otherwise, Quartz.CIImage.imageWithContentsOfURL_
                # prints to stderr something like:
                # 2020-09-20 20:55:25.538 python[73042:5650492] Creating client/daemon connection: B8FE995E-3F27-47F4-9FA8-559C615FD774
                # 2020-09-20 20:55:25.652 python[73042:5650492] Got the query meta data reply for: com.apple.MobileAsset.RawCamera.Camera, response: 0
                input_image = Quartz.CIImage.imageWithContentsOfURL_(input_url)

            if input_image is None:
                raise ImageConversionError(
                    f"Could not create CIImage for {input_path}")

            output_colorspace = (input_image.colorSpace()
                                 or Quartz.CGColorSpaceCreateWithName(
                                     Quartz.CoreGraphics.kCGColorSpaceSRGB))

            output_options = NSDictionary.dictionaryWithDictionary_({
                "kCGImageDestinationLossyCompressionQuality":
                compression_quality
            })
            (
                _,
                error,
            ) = self.context.writeJPEGRepresentationOfImage_toURL_colorSpace_options_error_(
                input_image, output_url, output_colorspace, output_options,
                None)
            if not error:
                return True
            else:
                raise ImageConversionError(
                    f"Error converting file {input_path} to jpeg at {output_path}: {error}"
                )
Example #6
0
    def write_jpeg(self, input_path, output_path, compression_quality=1.0):
        """ convert image to jpeg and write image to output_path

        Args:
            input_path: path to input image (e.g. '/path/to/import/file.CR2') as str or pathlib.Path
            output_path: path to exported jpeg (e.g. '/path/to/export/file.jpeg') as str or pathlib.Path
            compression_quality: JPEG compression quality, float in range 0.0 to 1.0; default is 1.0 (best quality)

        Return:
            True if conversion successful, else False

        Raises:
            ValueError if compression quality not in range 0.0 to 1.0
            FileNotFoundError if input_path doesn't exist
        """

        # accept input_path or output_path as pathlib.Path
        if not isinstance(input_path, str):
            input_path = str(input_path)

        if not isinstance(output_path, str):
            output_path = str(output_path)

        if not pathlib.Path(input_path).is_file():
            raise FileNotFoundError(f"could not find {input_path}")

        if not (0.0 <= compression_quality <= 1.0):
            raise ValueError(
                "illegal value for compression_quality: {compression_quality}")

        input_url = NSURL.fileURLWithPath_(input_path)
        output_url = NSURL.fileURLWithPath_(output_path)

        with pipes() as (out, err):
            # capture stdout and stderr from system calls
            # otherwise, Quartz.CIImage.imageWithContentsOfURL_
            # prints to stderr something like:
            # 2020-09-20 20:55:25.538 python[73042:5650492] Creating client/daemon connection: B8FE995E-3F27-47F4-9FA8-559C615FD774
            # 2020-09-20 20:55:25.652 python[73042:5650492] Got the query meta data reply for: com.apple.MobileAsset.RawCamera.Camera, response: 0
            input_image = Quartz.CIImage.imageWithContentsOfURL_(input_url)

        if input_image is None:
            logging.debug(f"Could not create CIImage for {input_path}")
            return False

        output_colorspace = input_image.colorSpace(
        ) or Quartz.CGColorSpaceCreateWithName(
            Quartz.CoreGraphics.kCGColorSpaceSRGB)

        output_options = NSDictionary.dictionaryWithDictionary_({
            "kCGImageDestinationLossyCompressionQuality":
            compression_quality
        })
        _, error = self.context.writeJPEGRepresentationOfImage_toURL_colorSpace_options_error_(
            input_image, output_url, output_colorspace, output_options, None)
        if not error:
            return True
        else:
            logging.debug(
                "Error converting file {input_path} to jpeg at {output_path}: {error}"
            )
            return False
Example #7
0
import kcpassword
import plistutils
import userpkg
import userplist
import shadowhash

from Foundation import NSDictionary

# Danger: this demo generates a autologin local admin user with a weak password!

password = '******'

user_data = {
    'name': 'test',
    'uid': '505',
    'ShadowHashData': shadowhash.generate(password)
}
user_plist = userplist.generate(user_data)
# we do it this way because it most closely resembles dscl output
print NSDictionary.dictionaryWithDictionary_(user_plist)

pkg_data = {
    'version': '1.0',
    'pkgid': 'com.foo.test_user',
    'destination_path': '~/Desktop/test-1.0.pkg',
    'kcpassword': kcpassword.generate(password),
    'is_admin': True,
    'user_plist': user_plist
}
userpkg.generate(pkg_data)
Example #8
0
def writeDictionary(dict, filepath):
    """
    Write dictionary to disk using Foundation call.
    """
    dictObj = NSDictionary.dictionaryWithDictionary_(dict)
    dictObj.writeToFile_atomically_(filepath, 1)
Example #9
0
def writeDictionary(dict, filepath):
    """
    Write dictionary to disk using Foundation call.
    """
    dictObj = NSDictionary.dictionaryWithDictionary_(dict)
    dictObj.writeToFile_atomically_(filepath, 1)