Ejemplo n.º 1
0
def _cleanup():
    """Free all tracked instances.

       Closes and destroys all currently allocated resources. This gets called
       from atexit handler just before :term:`ImageMagick` gets uninitialized.
    """
    msg = formattable('Tracked weakrefs: {0}')
    logger.debug(msg.format(len(_registry)))
    alive = 0
    unclosed = 0

    with __lock:
        for obj in _registry.values():
            alive += 1
            if not obj.closed:
                unclosed += 1
                obj.close(untrack=False)

    msg = formattable('Alive weakrefs: {0}')
    logger.debug(msg.format(alive))

    msg = formattable('Unclosed resources: {0}')
    logger.debug(msg.format(unclosed))

    logger.debug('Finished cleanup')
Ejemplo n.º 2
0
def memoized(f, *args, **kw):
    """Decorator that caches a function's return value each time it is called.

    If called later with the same arguments, the cached value is returned, and
    not re-evaluated. This decorator performs proper synchronization to make it
    thread-safe.
    """
    key = f, args, frozenset(kw.items())
    if key not in __cache:
        with __lock:
            if key not in __cache:
                __cache[key] = {'lock': RLock()}

    key_cache = __cache[key]
    if 'value' not in key_cache:
        with key_cache['lock']:
            if 'value' not in key_cache:
                info = key[0].__name__, key[1]
                msg = formattable('Memoizing {0} args={1}').format(*info)
                logger.debug(msg)

                result = f(*args, **kw)

                key_cache['value'] = result
                msg = formattable('Memoized {0} args={1}').format(*info)
                logger.debug(msg)

    return key_cache['value']
Ejemplo n.º 3
0
def _cleanup():
    """Free all tracked instances.

       Closes and destroys all currently allocated resources. This gets called
       from atexit handler just before :term:`ImageMagick` gets uninitialized.
    """
    msg = formattable('Tracked weakrefs: {0}')
    logger.debug(msg.format(len(_registry)))
    alive = 0
    unclosed = 0

    with __lock:
        for obj in _registry.values():
            alive += 1
            if not obj.closed:
                unclosed += 1
                obj.close(untrack=False)

    msg = formattable('Alive weakrefs: {0}')
    logger.debug(msg.format(alive))

    msg = formattable('Unclosed resources: {0}')
    logger.debug(msg.format(unclosed))

    logger.debug('Finished cleanup')
Ejemplo n.º 4
0
def memoized(f, *args, **kw):
    """Decorator that caches a function's return value each time it is called.

    If called later with the same arguments, the cached value is returned, and
    not re-evaluated. This decorator performs proper synchronization to make it
    thread-safe.
    """
    key = f, args, frozenset(kw.items())
    if key not in __cache:
        with __lock:
            if key not in __cache:
                __cache[key] = {'lock': RLock()}

    key_cache = __cache[key]
    if 'value' not in key_cache:
        with key_cache['lock']:
            if 'value' not in key_cache:
                info = key[0].__name__, key[1]
                msg = formattable('Memoizing {0} args={1}').format(*info)
                logger.debug(msg)

                result = f(*args, **kw)

                key_cache['value'] = result
                msg = formattable('Memoized {0} args={1}').format(*info)
                logger.debug(msg)

    return key_cache['value']
Ejemplo n.º 5
0
    def _lock(self, key):
        with self.__lock:
            if key in self.__locked:
                msg = formattable("Key '{0}' has been already locked")
                raise PystaciaException(msg.format(key))

            self.__locked.append(key)
Ejemplo n.º 6
0
    def __delattr__(self, key):
        with self.__lock:
            if key in self.__locked:
                msg = formattable("Key '{0}' has been locked")
                raise PystaciaException(msg.format(key))

            del self.__dict__[key]
Ejemplo n.º 7
0
    def __delattr__(self, key):
        with self.__lock:
            if key in self.__locked:
                msg = formattable("Key '{0}' has been locked")
                raise PystaciaException(msg.format(key))

            del self.__dict__[key]
Ejemplo n.º 8
0
def init_dll(dll):
    def shutdown():
        logger.debug('Cleaning up traced instances')
        _cleanup()

        c_call(None, 'terminus')

        if jython:
            from java.lang import System  # @UnresolvedImport
            System.exit(0)

    logger.debug('Critical section - init MagickWand')
    with __lock:
        if not dll.__inited:
            c_call(None, 'genesis', __init=False)

            logger.debug('Registering atexit handler')
            atexit.register(shutdown)

            dll.__inited = True

    version = magick.get_version()
    if version < min_version:
        msg = formattable('Unsupported version of MagickWand {0}')
        warn(msg.format(version))
Ejemplo n.º 9
0
    def _lock(self, key):
        with self.__lock:
            if key in self.__locked:
                msg = formattable("Key '{0}' has been already locked")
                raise PystaciaException(msg.format(key))

            self.__locked.append(key)
Ejemplo n.º 10
0
def get_dll(init=True, environ=None, isolated=False):
    """Find ImageMagick DLL and initialize it.

       Searches available paths with :func:`find_library`
       and then fallbacks to standard :func:`ctypes.util.find_liblrary`.
       Loads the DLL into memory, initializes it and warns if it has
       unsupported API and ABI versions.
    """
    if not hasattr(get_dll, '__dll') or isolated:
        logger.debug('Critical section - load MagickWand')
        with __lock:
            if not hasattr(get_dll, '__dll') or isolated:
                if not environ:
                    environ = os.environ

                path = find_library(name, abis, environ=environ)
                if not path:
                    msg = 'Could not find or load MagickWand'
                    raise PystaciaException(msg)

                msg = formattable('Loading MagickWand from {0}')
                logger.debug(msg.format(path))
                dll = CDLL(path)
                if not isolated:
                    get_dll.__dll = dll
                    get_dll.__dll.__inited = False
                else:
                    return dll

    dll = get_dll.__dll

    if init and not dll.__inited:
        init_dll(dll)

    return dll
Ejemplo n.º 11
0
    def get_string(self):
        """Return string representation of color.

           :rtype: ``str``

           Returns standard CSS string representation of color either
           ``rgb(r, g, b)`` or ``rgba(r, g, b, a)`` when color is not
           fully opaque.
        """
        if self.alpha == 1:
            template = formattable('rgb({0}, {1}, {2})')
        else:
            template = formattable('rgba({0}, {1}, {2}, {3})')

        rgb = tuple(int(x * 255) for x in self.get_rgb())

        return template.format(*(rgb + (self.alpha, )))
Ejemplo n.º 12
0
    def get_string(self):
        """Return string representation of color.

           :rtype: ``str``

           Returns standard CSS string representation of color either
           ``rgb(r, g, b)`` or ``rgba(r, g, b, a)`` when color is not
           fully opaque.
        """
        if self.alpha == 1:
            template = formattable('rgb({0}, {1}, {2})')
        else:
            template = formattable('rgba({0}, {1}, {2}, {3})')

        rgb = tuple(int(x * 255) for x in self.get_rgb())

        return template.format(*(rgb + (self.alpha,)))
Ejemplo n.º 13
0
    def __getattr__(self, key):
        if key in self.__defaults:
            with self.__lock:
                if key in self.__defaults:
                    return self.__defaults[key]

        msg = '{0} object has no attribute {1}, neither found in defaults'
        raise AttributeError(formattable(msg).format(self.__class__, key))
Ejemplo n.º 14
0
    def __getattr__(self, key):
        if key in self.__defaults:
            with self.__lock:
                if key in self.__defaults:
                    return self.__defaults[key]

        msg = '{0} object has no attribute {1}, neither found in defaults'
        raise AttributeError(formattable(msg).format(self.__class__, key))
Ejemplo n.º 15
0
    def copy(self):
        """Get independent copy of this resource."""
        resource = self._clone()

        if resource is None:
            tmpl = formattable('{0} _clone method returned None')
            raise PystaciaException(tmpl.format(self.__class__.__name__))

        return self.__class__(resource)
Ejemplo n.º 16
0
    def __init__(self, resource=None):
        """Construct new instance of resource."""
        self.__resource = resource if resource is not None else self._alloc()

        if self.__resource is None:
            tmpl = formattable('{0} _alloc method returned None')
            raise PystaciaException(tmpl.format(self.__class__.__name__))

        _track(self)
Ejemplo n.º 17
0
    def __init__(self, resource=None):
        """Construct new instance of resource."""
        self.__resource = resource if resource is not None else self._alloc()

        if self.__resource is None:
            tmpl = formattable('{0} _alloc method returned None')
            raise PystaciaException(tmpl.format(self.__class__.__name__))

        _track(self)
Ejemplo n.º 18
0
    def copy(self):
        """Get independent copy of this resource."""
        resource = self._clone()

        if resource is None:
            tmpl = formattable('{0} _clone method returned None')
            raise PystaciaException(tmpl.format(self.__class__.__name__))

        return self.__class__(resource)
Ejemplo n.º 19
0
    def __repr__(self):
        template = "<{class_}(w={w},h={h},{depth}bit" ",{colorspace},{type}) object at {addr}>"
        w, h = self.size
        depth, type = self.depth, self.type.name  # @ReservedAssignment
        colorspace, addr = self.colorspace.name, id(self)
        class_ = self.__class__.__name__

        return formattable(template).format(
            class_=class_, w=w, h=h, depth=depth, colorspace=colorspace, addr=hex(addr), type=type
        )
Ejemplo n.º 20
0
def c_call(obj, method, *args, **kw):
    if hasattr(obj.__class__, '_api_type'):
        api_type = obj.__class__._api_type
    else:
        api_type = obj

    msg = formattable('Translating method {0}.{1}')
    logger.debug(msg.format(api_type, method))

    method_name, c_method = get_c_method(api_type, method)

    try:
        init = kw.pop('__init')
    except KeyError:
        init = True

    if init:
        get_dll()

    # if objects are casted here and then
    # there is only their resource passed
    # there is a risk that GC will collect
    # them and __del__ will be called between
    # driving Imagick to SIGSEGV
    # lets keep references to them
    keep_, args_, should_lock = prepare_args(c_method, obj, args)

    msg = formattable('Calling {0}')
    logger.debug(msg.format(method_name))

    if pypy and should_lock:
        __lock.acquire()

    result = c_method(*args_)

    if pypy and should_lock:
        __lock.release()

    del keep_

    return handle_result(
        result, c_method.restype, args_, c_method.argtypes)
Ejemplo n.º 21
0
 def test_repr(self):
     for x in [color.from_string(x) for x in
               ['red', 'green', 'blue', 'gray']]:
         rgba = x.get_rgba()
         float_re = '(\d(\.\d+)?)'
         regexp = (formattable('<Color\(r={0},g={0},b={0},a={0}\)').
                   format(float_re))
         result = match(regexp, repr(x))
         groups = tuple(float(v) for i, v in
                        enumerate(result.groups()) if not i % 2)
         self.assertEqual(groups, rgba)
Ejemplo n.º 22
0
def cast(enum_, name):
    if isinstance(enum_, Enum):
        pass
    elif isinstance(enum_, string_types):
        enum_ = enum(enum_)
    else:
        msg = formattable('Cannot cast {0} to Enum')
        raise CastException(msg.format(enum_))

    if isinstance(name, EnumValue):
        if name.enum != enum_:
            msg = formattable('Attempted to cast {0} to unrelated Enum {1}')
            raise CastException(msg.format(str(name), str(enum_)))

        return name
    elif isinstance(name, string_types):
        return enum_value(enum_, name)
    else:
        msg = formattable('Cannot cast {0} to EnumValue with Enum {1}')
        raise CastException(msg.format(str(name), str(enum_)))
Ejemplo n.º 23
0
def cast(enum_, name):
    if isinstance(enum_, Enum):
        pass
    elif isinstance(enum_, string_types):
        enum_ = enum(enum_)
    else:
        msg = formattable('Cannot cast {0} to Enum')
        raise CastException(msg.format(enum_))

    if isinstance(name, EnumValue):
        if name.enum != enum_:
            msg = formattable('Attempted to cast {0} to unrelated Enum {1}')
            raise CastException(msg.format(str(name), str(enum_)))

        return name
    elif isinstance(name, string_types):
        return enum_value(enum_, name)
    else:
        msg = formattable('Cannot cast {0} to EnumValue with Enum {1}')
        raise CastException(msg.format(str(name), str(enum_)))
Ejemplo n.º 24
0
 def test_repr(self):
     for x in [
             color.from_string(x) for x in ['red', 'green', 'blue', 'gray']
     ]:
         rgba = x.get_rgba()
         float_re = '(\d(\.\d+)?)'
         regexp = (formattable('<Color\(r={0},g={0},b={0},a={0}\)').format(
             float_re))
         result = match(regexp, repr(x))
         groups = tuple(
             float(v) for i, v in enumerate(result.groups()) if not i % 2)
         self.assertEqual(groups, rgba)
Ejemplo n.º 25
0
    def resource(self):
        """Get underlying C resource.

           You can use this method to get access to raw C struct that you
           can use with :term:`ctypes` calls directly. It can be useful
           when you want to perform custom operations.
        """
        if self.__resource is None:
            tmpl = formattable('{0} already closed.')
            raise PystaciaException(tmpl.format(self.__class__.__name__))

        return self.__resource
Ejemplo n.º 26
0
    def resource(self):
        """Get underlying C resource.

           You can use this method to get access to raw C struct that you
           can use with :term:`ctypes` calls directly. It can be useful
           when you want to perform custom operations.
        """
        if self.__resource is None:
            tmpl = formattable('{0} already closed.')
            raise PystaciaException(tmpl.format(self.__class__.__name__))

        return self.__resource
Ejemplo n.º 27
0
def find_in_path(path, name, abis, osname, factory):
    depends_path = join(path, 'depends.txt')
    if exists(depends_path):
        process_depends(depends_path, path, osname, factory)

    for abi in abis:
        template = dll_template(osname, abi)
        if not template:
            continue

        template = formattable(template)

        dll_path = join(path, template.format(name=name, abi=abi))

        logger.debug('Trying: ' + dll_path)

        if exists(dll_path):
            logger.debug('Found: ' + dll_path)

            if osname == 'windows':
                old_path = getcwd()
                chdir(path)

            try:
                factory(dll_path)
            except:
                from sys import exc_info
                msg = formattable('Caught exception while loading '
                                  '{0}: {1}. Rolling back')
                logger.debug(msg.format(dll_path, exc_info()[1]))

                if osname == 'windows':
                    chdir(old_path)
            else:
                if osname == 'windows':
                    chdir(old_path)

                return dll_path
Ejemplo n.º 28
0
def process_depends(depends_path, path, osname, factory):
    depends = open(depends_path)

    for line in depends:
        depname, depabi = line.split()
        template = formattable(dll_template(osname, depabi))
        dll_path = join(path, template.format(name=depname,
                                              abi=depabi))
        try:
            factory(dll_path)
        except:
            pass

    depends.close()
Ejemplo n.º 29
0
def _make_component(name):
    doc = formattable("""Set or get {0} channel information.

       The value ought to be a float between 0 and 1.

       :rtype: ``float`` or ``int``
    """).format(name)

    def fget(self):
        return getattr(impl, 'get_' + name)(self)

    def fset(self, value):
        getattr(impl, 'set_' + name)(self, value)

    return property(fget, fset, doc=doc)
Ejemplo n.º 30
0
def _make_component(name):
    doc = formattable("""Set or get {0} channel information.

       The value ought to be a float between 0 and 1.

       :rtype: ``float`` or ``int``
    """).format(name)

    def fget(self):
        return getattr(impl, 'get_' + name)(self)

    def fset(self, value):
        getattr(impl, 'set_' + name)(self, value)

    return property(fget, fset, doc=doc)
Ejemplo n.º 31
0
    def __repr__(self):
        template = '<{class_}(w={w},h={h},{depth}bit'\
                   ',{colorspace},{type}) object at {addr}>'
        w, h = self.size
        depth, type = self.depth, self.type.name  # @ReservedAssignment
        colorspace, addr = self.colorspace.name, id(self)
        class_ = self.__class__.__name__

        return formattable(template).format(class_=class_,
                                            w=w,
                                            h=h,
                                            depth=depth,
                                            colorspace=colorspace,
                                            addr=hex(addr),
                                            type=type)
Ejemplo n.º 32
0
def cast(value):
    if isinstance(value, Color):
        return value
    elif isinstance(value, integer_types):
        return from_int24(value)
    elif isinstance(value, string_types):
        return from_string(value)
    elif value.__len__:
        if len(value) == 3:
            return from_rgb(*value)
        elif len(value) == 4:
            return from_rgba(*value)

    template = formattable('Cannot cast {0} to Color instance.')
    raise PystaciaException(template.format(value))
Ejemplo n.º 33
0
def cast(value):
    if isinstance(value, Color):
        return value
    elif isinstance(value, integer_types):
        return from_int24(value)
    elif isinstance(value, string_types):
        return from_string(value)
    elif value.__len__:
        if len(value) == 3:
            return from_rgb(*value)
        elif len(value) == 4:
            return from_rgba(*value)

    template = formattable('Cannot cast {0} to Color instance.')
    raise PystaciaException(template.format(value))
Ejemplo n.º 34
0
def read(filename, factory=None):
    """Read :class:`Image` from filename.

       :param filename: file name to read
       :type filename: ``str``
       :param factory: Image subclass to use when instantiating objects
       :rtype: :class:`Image`

       Reads file, determines its format and returns an :class:`Image`
       representing it. You can optionally pass factory parameter
       to use alternative :class:`Image` subclass.

       >>> read('example.jpg')
       <Image(w=512,h=512,8bit,rgb,truecolor) object at 0x10302ee00L>
    """
    if not exists(filename):
        template = formattable('No such file or directory: {0}')
        raise IOError((2, template.format(filename)))

    return io.read(filename, factory=factory)
Ejemplo n.º 35
0
def read(filename, factory=None):
    """Read :class:`Image` from filename.

       :param filename: file name to read
       :type filename: ``str``
       :param factory: Image subclass to use when instantiating objects
       :rtype: :class:`Image`

       Reads file, determines its format and returns an :class:`Image`
       representing it. You can optionally pass factory parameter
       to use alternative :class:`Image` subclass.

       >>> read('example.jpg')
       <Image(w=512,h=512,8bit,rgb,truecolor) object at 0x10302ee00L>
    """
    if not exists(filename):
        template = formattable("No such file or directory: {0}")
        raise IOError((2, template.format(filename)))

    return io.read(filename, factory=factory)
Ejemplo n.º 36
0
    def setUp(self):
        self.environ = {'PYSTACIA_SKIP_SYSTEM': '1',
                        'PYSTACIA_SKIP_PACKAGE': '1'}
        self.olddir = getcwd()

        tmproot = self.tmproot = mkdtemp()
        for subdir in '', 'cdll', 'lib', 'dll', 'depends':
            path = join(tmproot, subdir)
            if not exists(path):
                mkdir(path)

            for osname in 'macos', 'linux', 'windows':
                for abi in 2, 1, None:
                    template = formattable(dll_template(osname, abi))
                    libpath = join(path,
                                   template.format(name='Foo', abi=abi))
                    open(libpath, 'w').close()

        depends = open(join(tmproot, 'depends', 'depends.txt'), 'w')
        depends.write('Depends 18\n')
        depends.close()
Ejemplo n.º 37
0
    def setUp(self):
        self.environ = {
            'PYSTACIA_SKIP_SYSTEM': '1',
            'PYSTACIA_SKIP_PACKAGE': '1'
        }
        self.olddir = getcwd()

        tmproot = self.tmproot = mkdtemp()
        for subdir in '', 'cdll', 'lib', 'dll', 'depends':
            path = join(tmproot, subdir)
            if not exists(path):
                mkdir(path)

            for osname in 'macos', 'linux', 'windows':
                for abi in 2, 1, None:
                    template = formattable(dll_template(osname, abi))
                    libpath = join(path, template.format(name='Foo', abi=abi))
                    open(libpath, 'w').close()

        depends = open(join(tmproot, 'depends', 'depends.txt'), 'w')
        depends.write('Depends 18\n')
        depends.close()
Ejemplo n.º 38
0
def lookup(mnemonic, enum=None, version=None, throw=True):
    if enum:
        mnemonic = enum.cast(mnemonic)

    if not version:
        version = get_version()

    value = None

    for entry in data.get(mnemonic.enum.name, []):
        if entry['_version'] > version:
            break
        value = entry.get(mnemonic.name)

    if value is None and throw:
        template = "Enumeration '{enum}' cannot map mnemonic '{mnemonic}'"
        template = formattable(template)
        enum = mnemonic.enum.name
        mnemonic = mnemonic.name
        raise PystaciaException(template.format(enum=enum, mnemonic=mnemonic))

    return value
Ejemplo n.º 39
0
def lookup(mnemonic, enum=None, version=None, throw=True):
    if enum:
        mnemonic = enum.cast(mnemonic)

    if not version:
        version = get_version()

    value = None

    for entry in data.get(mnemonic.enum.name, []):
        if entry['_version'] > version:
            break
        value = entry.get(mnemonic.name)

    if value is None and throw:
        template = "Enumeration '{enum}' cannot map mnemonic '{mnemonic}'"
        template = formattable(template)
        enum = mnemonic.enum.name
        mnemonic = mnemonic.name
        raise PystaciaException(template.format(enum=enum, mnemonic=mnemonic))

    return value
Ejemplo n.º 40
0
def get_c_method(api_type, method, throw=True):
    type_data = metadata[api_type]
    method_name = type_data['format'](method)

    if not throw and not hasattr(get_dll(False), method_name):
        return False

    c_method = getattr(get_dll(False), method_name)

    msg = formattable('Annoting {0}')
    logger.debug(msg.format(method_name))
    method_data = type_data['symbols'][method]

    argtypes = method_data[0]
    if 'arg' in type_data:
        argtypes = (type_data['arg'],) + argtypes
    c_method.argtypes = argtypes

    restype = type_data.get('result', None)
    if len(method_data) == 2:
        restype = method_data[1]
    c_method.restype = restype

    return method_name, c_method
Ejemplo n.º 41
0
    def __repr__(self):
        template = formattable("pystacia.lazyenum.enum('{0}')")

        return template.format(self.name)
Ejemplo n.º 42
0
    rose = lazy_imported('rose')
    wizard = lazy_imported('wizard')
    granite = lazy_imported('granite')
    netscape = lazy_imported('netscape')
    Image = lazy_imported('Image')

    composites = really_lazy_enum('composites')
    types = really_lazy_enum('types')
    filters = really_lazy_enum('filters')
    colorspaces = really_lazy_enum('colorspaces')
    compressions = really_lazy_enum('compressions')
    axes = really_lazy_enum('axes')

    __all__ = [
        'read', 'read_blob', 'read_raw',
        'blank', 'checkerboard',
        'lena', 'magick_logo', 'rose', 'wizard', 'granite', 'netscape',
        'composites', 'types', 'filters',
        'colorspaces', 'compressions', 'axes',
        'color', 'colors',
        'Image',

        'registry']

    from zope.deprecation import deprecated  # @UnresolvedImport
    from pystacia.compat import formattable

    msg = formattable('Use pystacia.image.{0} instead')
    for symbol in set(__all__) - set(['color', 'colors', 'registry']):
        deprecated(symbol, msg.format(symbol))
Ejemplo n.º 43
0
    def __repr__(self):
        template = ('<{class_}(r={0},g={1},b={2},a={3})'
                    ' object at {id}>')
        kw = dict(id=hex(id(self)), class_=self.__class__.__name__)

        return formattable(template).format(*self.get_rgba(), **kw)
Ejemplo n.º 44
0
    def __repr__(self):
        template = ('<{class_}(r={0},g={1},b={2},a={3})' ' object at {id}>')
        kw = dict(id=hex(id(self)), class_=self.__class__.__name__)

        return formattable(template).format(*self.get_rgba(), **kw)
Ejemplo n.º 45
0
    def __repr__(self):
        template = formattable("pystacia.lazyenum.enum('{0}')")

        return template.format(self.name)