Hello community, here is the log from the commit of package python-cairocffi for openSUSE:Factory checked in at 2017-04-20 20:53:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-cairocffi (Old) and /work/SRC/openSUSE:Factory/.python-cairocffi.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-cairocffi" Thu Apr 20 20:53:04 2017 rev:8 rq:487695 version:0.8.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-cairocffi/python-cairocffi.changes 2016-02-03 10:19:37.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python-cairocffi.new/python-cairocffi.changes 2017-04-20 20:53:06.297681348 +0200 @@ -1,0 +2,22 @@ +Wed Apr 12 19:01:15 UTC 2017 - toddrme2...@gmail.com + +- Fix download URL. + +------------------------------------------------------------------- +Wed Apr 12 17:44:02 UTC 2017 - toddrme2...@gmail.com + +- Update to version 0.8.0 + * Follow semver + * Avoid implicit relative import + * Use utf-8 instead of utf8 in headers + * Keep cairo library loaded until all relevant objects are freed + * Add cairo_quartz_* functions for MacOS + * Use the default ReadTheDocs theme + * Fix implicit casts + +------------------------------------------------------------------- +Fri Oct 14 14:12:05 UTC 2016 - jmate...@suse.com + +- update for multipython build + +------------------------------------------------------------------- Old: ---- cairocffi-0.7.2.tar.gz New: ---- cairocffi-0.8.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-cairocffi.spec ++++++ --- /var/tmp/diff_new_pack.qIx8HT/_old 2017-04-20 20:53:07.469515642 +0200 +++ /var/tmp/diff_new_pack.qIx8HT/_new 2017-04-20 20:53:07.469515642 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-cairocffi # -# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,27 +16,26 @@ # +%{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-cairocffi -Version: 0.7.2 +Version: 0.8.0 Release: 0 Summary: Python cairo bindings based on cffi License: BSD-3-Clause Group: Development/Languages/Python Url: https://github.com/SimonSapin/cairocffi -Source: https://pypi.python.org/packages/source/c/cairocffi/cairocffi-%{version}.tar.gz +Source: https://files.pythonhosted.org/packages/source/c/cairocffi/cairocffi-%{version}.tar.gz +BuildRequires: %{python_module cffi >= 0.6} +BuildRequires: %{python_module devel} +BuildRequires: %{python_module setuptools} BuildRequires: cairo BuildRequires: gdk-pixbuf -BuildRequires: python-cffi >= 0.6 -BuildRequires: python-devel -BuildRequires: python-setuptools +BuildRequires: python-rpm-macros Requires: cairo Requires: python-cffi >= 0.6 BuildRoot: %{_tmppath}/%{name}-%{version}-build -%if 0%{?suse_version} && 0%{?suse_version} <= 1110 -%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} -%else BuildArch: noarch -%endif +%python_subpackages %description cairocffi is a CFFI-based drop-in replacement for Pycairo, @@ -62,22 +61,30 @@ %setup -q -n cairocffi-%{version} %build -python setup.py build +%python_build %install -python setup.py install --prefix=%{_prefix} --root=%{buildroot} +%python_install -%files +%files %python_files %defattr(-,root,root,-) %doc LICENSE CHANGES README.rst %{python_sitelib}/cairocffi-%{version}-py*.egg-info %{python_sitelib}/cairocffi/ %exclude %{python_sitelib}/cairocffi/test_pixbuf.py* %exclude %{python_sitelib}/cairocffi/pixbuf.py* +%ifpycache +%exclude %{python_sitelib}/cairocffi/__pycache__/test_pixbuf.* +%exclude %{python_sitelib}/cairocffi/__pycache__/pixbuf.* +%endif -%files pixbuf +%files %{python_files pixbuf} %defattr(-,root,root,-) %{python_sitelib}/cairocffi/pixbuf.py* %{python_sitelib}/cairocffi/test_pixbuf.py* +%ifpycache +%{python_sitelib}/cairocffi/__pycache__/test_pixbuf.* +%{python_sitelib}/cairocffi/__pycache__/pixbuf.* +%endif %changelog ++++++ cairocffi-0.7.2.tar.gz -> cairocffi-0.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/.gitignore new/cairocffi-0.8.0/.gitignore --- old/cairocffi-0.7.2/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/cairocffi-0.8.0/.gitignore 2016-08-26 18:06:11.000000000 +0200 @@ -0,0 +1,11 @@ +*.pyc +__pycache__ +cairocffi/_ffi*.py +*.egg +*.egg-info +/.eggs +/dist +/.tox +/.coverage +/htmlcov +/docs/_build diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/.travis.yml new/cairocffi-0.8.0/.travis.yml --- old/cairocffi-0.7.2/.travis.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/cairocffi-0.8.0/.travis.yml 2016-08-26 18:06:11.000000000 +0200 @@ -0,0 +1,17 @@ +language: python +python: + - "2.6" + - "2.7" + - "3.2" + - "3.3" + - "3.4" + - "3.5" +before_install: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" +install: + - "pip install xcffib" + - "pip install ." + - "python cairocffi/ffi_build.py" +script: "py.test" +sudo: false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/CHANGES new/cairocffi-0.8.0/CHANGES --- old/cairocffi-0.7.2/CHANGES 2014-09-23 19:09:55.000000000 +0200 +++ new/cairocffi-0.8.0/CHANGES 2017-02-03 14:00:51.000000000 +0100 @@ -1,6 +1,53 @@ cairocffi changelog ------------------- +Version 0.8.0 +............. + +Released on 2017-02-03 + +* Follow semver +* `#76 <https://github.com/Kozea/cairocffi/issues/76>`_: + Avoid implicit relative import +* `#74 <https://github.com/Kozea/cairocffi/pull/74>`_: + Use utf-8 instead of utf8 in headers +* `#73 <https://github.com/Kozea/cairocffi/issues/73>`_: + Keep cairo library loaded until all relevant objects are freed +* `#86 <https://github.com/Kozea/cairocffi/pull/86>`_: + Add cairo_quartz_* functions for MacOS +* Use the default ReadTheDocs theme +* Fix implicit casts + + +Version 0.7.2 +............. + +Released on 2015-08-04 + +* Use ctypes.util.find_library with dlopen. + + +Version 0.7.1 +............. + +Released on 2015-06-22 + +* Allow installing cairocffi when cffi<1.0 is installed. + + +Version 0.7 +........... + +Released on 2015-06-05 + +* `#47 <https://github.com/SimonSapin/cairocffi/pull/47>`_: + Fix PyPy support. +* `#60 <https://github.com/SimonSapin/cairocffi/pull/60>`_: + Use CFFI-1.0 methods. +* `#61 <https://github.com/SimonSapin/cairocffi/pull/61>`_: + Allow ffi import when package is pip installed. + + Version 0.6 ........... diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/PKG-INFO new/cairocffi-0.8.0/PKG-INFO --- old/cairocffi-0.7.2/PKG-INFO 2015-08-04 16:26:46.000000000 +0200 +++ new/cairocffi-0.8.0/PKG-INFO 2017-02-03 14:05:56.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cairocffi -Version: 0.7.2 +Version: 0.8.0 Summary: cffi-based cairo bindings for Python Home-page: https://github.com/SimonSapin/cairocffi Author: Simon Sapin diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/__init__.py new/cairocffi-0.8.0/cairocffi/__init__.py --- old/cairocffi-0.7.2/cairocffi/__init__.py 2015-08-04 16:26:29.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/__init__.py 2017-02-03 12:41:24.000000000 +0100 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi ~~~~~~~~~ @@ -15,14 +15,9 @@ from . import constants from .compat import FileNotFoundError +from ._ffi import ffi -try: - from ._ffi import ffi -except ImportError: - # PyPy < 2.6 compatibility - from .ffi_build import ffi - -VERSION = '0.7.2' +VERSION = '0.8.0' # pycairo compat: version = '1.10.0' version_info = (1, 10, 0) @@ -46,6 +41,16 @@ cairo = dlopen(ffi, 'cairo', 'cairo-2') +class _keepref(object): + """Function wrapper that keeps a reference to another object.""" + def __init__(self, ref, func): + self.ref = ref + self.func = func + + def __call__(self, *args, **kwargs): + self.func(*args, **kwargs) + + class CairoError(Exception): """Raised when cairo returns an error status.""" def __init__(self, message, status): @@ -105,7 +110,8 @@ # Implementation is in submodules, but public API is all here. from .surfaces import (Surface, ImageSurface, PDFSurface, PSSurface, - SVGSurface, RecordingSurface, Win32PrintingSurface) + SVGSurface, RecordingSurface, Win32Surface, + Win32PrintingSurface) try: from .xcb import XCBSurface except ImportError: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/compat.py new/cairocffi-0.8.0/cairocffi/compat.py --- old/cairocffi-0.7.2/cairocffi/compat.py 2013-05-24 04:33:32.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/compat.py 2016-08-26 18:06:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.compat ~~~~~~~~~~~~~~~~ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/constants.py new/cairocffi-0.8.0/cairocffi/constants.py --- old/cairocffi-0.7.2/cairocffi/constants.py 2014-09-23 18:18:14.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/constants.py 2016-08-26 18:06:11.000000000 +0200 @@ -2023,6 +2023,31 @@ cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font, cairo_matrix_t *device_to_logical); + + typedef void* CGContextRef; + typedef void* CGFontRef; + typedef void* ATSUFontID; + + +cairo_surface_t * +cairo_quartz_surface_create (cairo_format_t format, + unsigned int width, + unsigned int height); + +cairo_surface_t * +cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, + unsigned int width, + unsigned int height); + +CGContextRef +cairo_quartz_surface_get_cg_context (cairo_surface_t *surface); + +cairo_font_face_t * +cairo_quartz_font_face_create_for_cgfont (CGFontRef font); + +cairo_font_face_t * +cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id); + """ _CAIRO_XCB_HEADERS = r""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/context.py new/cairocffi-0.8.0/cairocffi/context.py --- old/cairocffi-0.7.2/cairocffi/context.py 2014-12-17 00:16:20.000000000 +0100 +++ new/cairocffi-0.8.0/cairocffi/context.py 2016-08-26 18:12:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.context ~~~~~~~~~~~~~~~~~ @@ -10,7 +10,7 @@ """ -from . import ffi, cairo, _check_status, constants +from . import ffi, cairo, _check_status, constants, _keepref from .matrix import Matrix from .patterns import Pattern from .surfaces import Surface @@ -101,7 +101,7 @@ self._init_pointer(cairo.cairo_create(target._pointer)) def _init_pointer(self, pointer): - self._pointer = ffi.gc(pointer, cairo.cairo_destroy) + self._pointer = ffi.gc(pointer, _keepref(cairo, cairo.cairo_destroy)) self._check_status() def _check_status(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/ffi_build.py new/cairocffi-0.8.0/cairocffi/ffi_build.py --- old/cairocffi-0.7.2/cairocffi/ffi_build.py 2015-06-03 13:44:03.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/ffi_build.py 2016-08-26 18:06:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.ffi_build ~~~~~~~~~~~~~~~~~~~ @@ -16,7 +16,7 @@ # Path hack to import constants when this file is exec'd by setuptools this_file = os.path.abspath(__file__) -this_dir = os.path.split(this_file)[0] +this_dir = os.path.dirname(this_file) sys.path.append(this_dir) import constants @@ -24,9 +24,7 @@ # Primary cffi definitions ffi = FFI() -if hasattr(ffi, 'set_source'): - # PyPy < 2.6 compatibility - ffi.set_source('cairocffi._ffi', None) +ffi.set_source('cairocffi._ffi', None) ffi.cdef(constants._CAIRO_HEADERS) # include xcffib cffi definitions for cairo xcb support @@ -39,9 +37,7 @@ # gdk pixbuf cffi definitions ffi_pixbuf = FFI() -if hasattr(ffi_pixbuf, 'set_source'): - # PyPy < 2.6 compatibility - ffi_pixbuf.set_source('cairocffi._ffi_pixbuf', None) +ffi_pixbuf.set_source('cairocffi._ffi_pixbuf', None) ffi_pixbuf.include(ffi) ffi_pixbuf.cdef(''' typedef unsigned long gsize; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/fonts.py new/cairocffi-0.8.0/cairocffi/fonts.py --- old/cairocffi-0.7.2/cairocffi/fonts.py 2013-05-24 04:33:32.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/fonts.py 2016-08-26 18:12:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.fonts ~~~~~~~~~~~~~~~ @@ -10,7 +10,7 @@ """ -from . import ffi, cairo, _check_status, constants +from . import ffi, cairo, _check_status, constants, _keepref from .matrix import Matrix from .compat import xrange @@ -31,7 +31,8 @@ """ def __init__(self, pointer): - self._pointer = ffi.gc(pointer, cairo.cairo_font_face_destroy) + self._pointer = ffi.gc( + pointer, _keepref(cairo, cairo.cairo_font_face_destroy)) self._check_status() def _check_status(self): @@ -137,7 +138,8 @@ ctm._pointer, options._pointer)) def _init_pointer(self, pointer): - self._pointer = ffi.gc(pointer, cairo.cairo_scaled_font_destroy) + self._pointer = ffi.gc( + pointer, _keepref(cairo, cairo.cairo_scaled_font_destroy)) self._check_status() def _check_status(self): @@ -347,9 +349,10 @@ status = cairo.cairo_scaled_font_text_to_glyphs( self._pointer, x, y, _encode_string(text), -1, glyphs, num_glyphs, clusters, num_clusters, cluster_flags) - glyphs = ffi.gc(glyphs[0], cairo.cairo_glyph_free) + glyphs = ffi.gc(glyphs[0], _keepref(cairo, cairo.cairo_glyph_free)) if with_clusters: - clusters = ffi.gc(clusters[0], cairo.cairo_text_cluster_free) + clusters = ffi.gc( + clusters[0], _keepref(cairo, cairo.cairo_text_cluster_free)) _check_status(status) glyphs = [ (glyph.index, glyph.x, glyph.y) @@ -393,7 +396,8 @@ getattr(self, 'set_' + name)(value) def _init_pointer(self, pointer): - self._pointer = ffi.gc(pointer, cairo.cairo_font_options_destroy) + self._pointer = ffi.gc( + pointer, _keepref(cairo, cairo.cairo_font_options_destroy)) self._check_status() def _check_status(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/matrix.py new/cairocffi-0.8.0/cairocffi/matrix.py --- old/cairocffi-0.7.2/cairocffi/matrix.py 2013-05-24 04:33:32.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/matrix.py 2016-08-26 18:06:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.matrix ~~~~~~~~~~~~~~~~ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/patterns.py new/cairocffi-0.8.0/cairocffi/patterns.py --- old/cairocffi-0.7.2/cairocffi/patterns.py 2013-05-24 04:33:32.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/patterns.py 2016-08-26 18:12:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.patterns ~~~~~~~~~~~~~~~~~~ @@ -10,7 +10,7 @@ """ -from . import ffi, cairo, _check_status, constants +from . import ffi, cairo, _check_status, constants, _keepref from .matrix import Matrix from .surfaces import Surface from .compat import xrange @@ -34,7 +34,8 @@ """ def __init__(self, pointer): - self._pointer = ffi.gc(pointer, cairo.cairo_pattern_destroy) + self._pointer = ffi.gc( + pointer, _keepref(cairo, cairo.cairo_pattern_destroy)) self._check_status() def _check_status(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/pixbuf.py new/cairocffi-0.8.0/cairocffi/pixbuf.py --- old/cairocffi-0.7.2/cairocffi/pixbuf.py 2015-08-04 16:26:08.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/pixbuf.py 2016-08-26 18:06:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.pixbuf ~~~~~~~~~~~~~~~~ @@ -16,13 +16,9 @@ from array import array from . import dlopen, ImageSurface, Context, constants +from ._ffi_pixbuf import ffi from .compat import xrange -try: - from ._ffi_pixbuf import ffi -except ImportError: - # PyPy < 2.6 compatibility - from .ffi_build import ffi_pixbuf as ffi __all__ = ['decode_to_image_surface'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/surfaces.py new/cairocffi-0.8.0/cairocffi/surfaces.py --- old/cairocffi-0.7.2/cairocffi/surfaces.py 2015-06-03 13:44:03.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/surfaces.py 2017-01-26 12:46:32.000000000 +0100 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.surface ~~~~~~~~~~~~~~~~~ @@ -15,7 +15,7 @@ import ctypes import weakref -from . import ffi, cairo, _check_status, constants +from . import ffi, cairo, _check_status, constants, _keepref from .fonts import FontOptions, _encode_string @@ -128,7 +128,8 @@ """ def __init__(self, pointer, target_keep_alive=None): - self._pointer = ffi.gc(pointer, cairo.cairo_surface_destroy) + self._pointer = ffi.gc( + pointer, _keepref(cairo, cairo.cairo_surface_destroy)) self._check_status() if target_keep_alive not in (None, ffi.NULL): keep_alive = KeepAlive(target_keep_alive) @@ -440,7 +441,7 @@ else: # TODO: avoid making a copy here if possible. length = len(data) - data = ffi.new('char[]', data) + data = ffi.new('unsigned char[]', data) keep_alive = KeepAlive(data, mime_type) _check_status(cairo.cairo_surface_set_mime_data( self._pointer, mime_type, data, length, @@ -648,7 +649,7 @@ raise ValueError('Got a %d bytes buffer, needs at least %d.' % (length, stride * height)) pointer = cairo.cairo_image_surface_create_for_data( - ffi.cast('char*', address), format, width, height, stride) + ffi.cast('unsigned char*', address), format, width, height, stride) Surface.__init__(self, pointer, target_keep_alive=data) @classmethod @@ -1274,6 +1275,31 @@ return tuple(extents) +class Win32Surface(Surface): + """ Creates a cairo surface that targets the given DC. + + The DC will be queried for its initial clip extents, and this + will be used as the size of the cairo surface. The resulting + surface will always be of format CAIRO_FORMAT_RGB24; should + you need another surface format, you will need to create one + through cairo_win32_surface_create_with_dib(). + + :param hdc : + The DC to create a surface for, + as obtained from :func:`win32gui.CreateDC`. + **Note**: this unsafely inteprets an integer as a pointer. + Make sure it actually points to a valid DC! + :type hdc: int + + *New in cairocffi 0.8* + + """ + def __init__(self, hdc): + pointer = cairo.cairo_win32_surface_create( + ffi.cast('void*', hdc)) + Surface.__init__(self, pointer) + + class Win32PrintingSurface(Surface): """ Creates a cairo surface that targets the given DC. @@ -1308,5 +1334,6 @@ constants.SURFACE_TYPE_PDF: PDFSurface, constants.SURFACE_TYPE_SVG: SVGSurface, constants.SURFACE_TYPE_RECORDING: RecordingSurface, + constants.SURFACE_TYPE_WIN32: Win32Surface, constants.SURFACE_TYPE_WIN32_PRINTING: Win32PrintingSurface } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/test_cairo.py new/cairocffi-0.8.0/cairocffi/test_cairo.py --- old/cairocffi-0.7.2/cairocffi/test_cairo.py 2014-09-23 19:04:30.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/test_cairo.py 2016-08-26 18:06:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.tests ~~~~~~~~~~~~~~~ @@ -1064,8 +1064,8 @@ assert 5 == x1 < x2 < x3 assert clusters == [(2, 1), (1, 1), (1, 1)] assert is_backwards == 0 - assert font.glyph_extents(glyphs) == font.text_extents(text) - assert font.glyph_extents(glyphs) == context.glyph_extents(glyphs) + assert round_tuple(font.glyph_extents(glyphs)) == round_tuple(font.text_extents(text)) + assert round_tuple(font.glyph_extents(glyphs)) == round_tuple(context.glyph_extents(glyphs)) assert context.copy_path() == [] context.glyph_path(glyphs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/test_pixbuf.py new/cairocffi-0.8.0/cairocffi/test_pixbuf.py --- old/cairocffi-0.7.2/cairocffi/test_pixbuf.py 2013-06-20 12:31:55.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/test_pixbuf.py 2016-08-26 18:06:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.test_pixbuf ~~~~~~~~~~~~~~~~~~~~~ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/test_xcb.py new/cairocffi-0.8.0/cairocffi/test_xcb.py --- old/cairocffi-0.7.2/cairocffi/test_xcb.py 2015-06-05 13:24:27.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/test_xcb.py 2016-08-26 18:06:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.test_xcb diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi/xcb.py new/cairocffi-0.8.0/cairocffi/xcb.py --- old/cairocffi-0.7.2/cairocffi/xcb.py 2015-06-03 13:44:03.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi/xcb.py 2016-08-26 18:06:11.000000000 +0200 @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ cairocffi.xcb ~~~~~~~~~~~~~ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi.egg-info/PKG-INFO new/cairocffi-0.8.0/cairocffi.egg-info/PKG-INFO --- old/cairocffi-0.7.2/cairocffi.egg-info/PKG-INFO 2015-08-04 16:26:46.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi.egg-info/PKG-INFO 2017-02-03 14:05:56.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cairocffi -Version: 0.7.2 +Version: 0.8.0 Summary: cffi-based cairo bindings for Python Home-page: https://github.com/SimonSapin/cairocffi Author: Simon Sapin diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/cairocffi.egg-info/SOURCES.txt new/cairocffi-0.8.0/cairocffi.egg-info/SOURCES.txt --- old/cairocffi-0.7.2/cairocffi.egg-info/SOURCES.txt 2015-08-04 16:26:46.000000000 +0200 +++ new/cairocffi-0.8.0/cairocffi.egg-info/SOURCES.txt 2017-02-03 14:05:56.000000000 +0100 @@ -1,4 +1,6 @@ .coveragerc +.gitignore +.travis.yml CHANGES LICENSE MANIFEST.in @@ -32,4 +34,11 @@ docs/index.rst docs/overview.rst docs/pixbuf.rst -docs/xcb.rst \ No newline at end of file +docs/xcb.rst +utils/cairo_coverage.py +utils/cairocffi_to_pycairo.py +utils/compare_pycairo.py +utils/mkconstants.py +utils/pango_example.py +utils/pycairo_to_cairocffi.py +utils/tests.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/docs/overview.rst new/cairocffi-0.8.0/docs/overview.rst --- old/cairocffi-0.7.2/docs/overview.rst 2014-09-30 12:02:48.000000000 +0200 +++ new/cairocffi-0.8.0/docs/overview.rst 2016-10-15 14:49:52.000000000 +0200 @@ -81,7 +81,8 @@ cairo versions -------------- -The same cairocffi version can be used with a variety of cairo version. +Cairo, pycairo, and cairocffi each have version numbers. The same cairocffi version can +be used with a variety of cairo versions. For example, the :meth:`Surface.set_mime_data` method is based on the :c:func:`cairo_surface_set_mime_data` C function, which is only available since cairo 1.10. @@ -89,11 +90,22 @@ You can however still use the rest of the API. There is no need for cairocffi’s versions to be tied to cairo’s versions. -Use :func:`cairo_version` to test the version number:: +Use :func:`cairo_version` to test the version number for cairo:: - if cairo.cairo_version() > 11000: + if cairocffi.cairo_version() > 11000: surface.set_mime_data('image/jpeg', jpeg_bytes) +Here are all the version numbers:: + + >>> print("The cairo version is %s, meaning %s." + ... % (cairocffi.cairo_version(), cairocffi.cairo_version_string()) + The cairo version is 11402, meaning 1.14.02. + >>> print("The latest pycairo version this cairocffi version is compatible with is %s." + ... % cairo.version) + The latest pycairo version this cairocffi version is compatible with is 1.10.0. + >>> print("The cairocffi version is %s." % cairo.VERSION) + The cairocffi version is 0.7.2 + cairocffi is tested with both cairo 1.8.2 and the latest (1.12.8 as of this writing.) @@ -130,7 +142,9 @@ For doing something useful with cairo, you need at least a surface and a context:: - surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 300, 200) + import cairocffi as cairo + + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 300, 200) context = cairo.Context(surface) with context: context.set_source_rgb(1, 1, 1) # White diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/setup.cfg new/cairocffi-0.8.0/setup.cfg --- old/cairocffi-0.7.2/setup.cfg 2015-08-04 16:26:46.000000000 +0200 +++ new/cairocffi-0.8.0/setup.cfg 2017-02-03 14:05:56.000000000 +0100 @@ -6,7 +6,6 @@ upload-dir = docs/_build/html [egg_info] -tag_svn_revision = 0 -tag_date = 0 tag_build = +tag_date = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/setup.py new/cairocffi-0.8.0/setup.py --- old/cairocffi-0.7.2/setup.py 2015-06-22 16:29:17.000000000 +0200 +++ new/cairocffi-0.8.0/setup.py 2016-08-26 18:06:11.000000000 +0200 @@ -2,7 +2,6 @@ from os import path import re import io -import sys VERSION = re.search( @@ -18,29 +17,6 @@ encoding='utf-8', ).read() -if '_cffi_backend' in sys.builtin_module_names: - import _cffi_backend - requires_cffi = "cffi==" + _cffi_backend.__version__ -else: - requires_cffi = "cffi>=1.1.0" - -# PyPy < 2.6 compatibility -if requires_cffi.startswith("cffi==0."): - cffi_args = dict() -else: - cffi_args = dict(cffi_modules=[ - 'cairocffi/ffi_build.py:ffi', - 'cairocffi/ffi_build.py:ffi_pixbuf' - ]) - -try: - import cffi - if cffi.__version__.startswith('0.'): - # https://github.com/SimonSapin/cairocffi/issues/64 - cffi_args = dict() -except ImportError: - pass - setup( name='cairocffi', version=VERSION, @@ -59,8 +35,11 @@ 'Topic :: Multimedia :: Graphics', ], packages=find_packages(), - install_requires=[requires_cffi], - setup_requires=[requires_cffi], + install_requires=['cffi>=1.1.0'], + setup_requires=['cffi>=1.1.0'], + cffi_modules=[ + 'cairocffi/ffi_build.py:ffi', + 'cairocffi/ffi_build.py:ffi_pixbuf' + ], extras_require={'xcb': ['xcffib>=0.3.2']}, - **cffi_args ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/utils/cairo_coverage.py new/cairocffi-0.8.0/utils/cairo_coverage.py --- old/cairocffi-0.7.2/utils/cairo_coverage.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cairocffi-0.8.0/utils/cairo_coverage.py 2016-08-26 18:06:11.000000000 +0200 @@ -0,0 +1,25 @@ +# coding: utf-8 + +import inspect +import pycparser +import cairocffi + +ALL_THE_CODE = ''.join( + line + for module in [ + cairocffi, cairocffi.surfaces, cairocffi.patterns, + cairocffi.fonts, cairocffi.context, cairocffi.matrix] + for line in inspect.getsourcelines(module)[0]) + + +class Visitor(pycparser.c_ast.NodeVisitor): + def visit_Decl(self, node): + for _, child in node.children(): + if isinstance(child, pycparser.c_ast.FuncDecl): + if ('cairo.' + node.name) not in ALL_THE_CODE and not ( + node.name.endswith('user_data')): + print(node.name) + break + +print('cairo functions never used in cairocffi:\n') +Visitor().visit(pycparser.CParser().parse(cairocffi.constants._CAIRO_HEADERS)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/utils/cairocffi_to_pycairo.py new/cairocffi-0.8.0/utils/cairocffi_to_pycairo.py --- old/cairocffi-0.7.2/utils/cairocffi_to_pycairo.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cairocffi-0.8.0/utils/cairocffi_to_pycairo.py 2016-08-26 18:06:11.000000000 +0200 @@ -0,0 +1,34 @@ +# coding: utf-8 + +import ctypes +import cairo # pycairo +import cairocffi + +pycairo = ctypes.PyDLL(cairo._cairo.__file__) +pycairo.PycairoContext_FromContext.restype = ctypes.c_void_p +pycairo.PycairoContext_FromContext.argtypes = 3 * [ctypes.c_void_p] +ctypes.pythonapi.PyList_Append.argtypes = 2 * [ctypes.c_void_p] + + +def _UNSAFE_cairocffi_context_to_pycairo(cairocffi_context): + # Sanity check. Continuing with another type would probably segfault. + if not isinstance(cairocffi_context, cairocffi.Context): + raise TypeError('Expected a cairocffi.Context, got %r' + % cairocffi_context) + + # Create a reference for PycairoContext_FromContext to take ownership of. + cairocffi.cairo.cairo_reference(cairocffi_context._pointer) + # Casting the pointer to uintptr_t (the integer type as wide as a pointer) + # gets the context’s integer address. + # On CPython id(cairo.Context) gives the address to the Context type, + # as expected by PycairoContext_FromContext. + address = pycairo.PycairoContext_FromContext( + int(cairocffi.ffi.cast('uintptr_t', cairocffi_context._pointer)), + id(cairo.Context), + None) + assert address + # This trick uses Python’s C API + # to get a reference to a Python object from its address. + temp_list = [] + assert ctypes.pythonapi.PyList_Append(id(temp_list), address) == 0 + return temp_list[0] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/utils/compare_pycairo.py new/cairocffi-0.8.0/utils/compare_pycairo.py --- old/cairocffi-0.7.2/utils/compare_pycairo.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cairocffi-0.8.0/utils/compare_pycairo.py 2016-08-26 18:06:11.000000000 +0200 @@ -0,0 +1,26 @@ +# coding: utf-8 + +import cairo as pycairo +import cairocffi + +# We want the real pycairo +assert pycairo is not cairocffi + + +print('Missing pycairo API:\n') + +for name in dir(pycairo): + pycairo_obj = getattr(pycairo, name) + cairocffi_obj = getattr(cairocffi, name, None) + if name.startswith(('_', 'version', 'CAPI')): + continue + if cairocffi_obj is None: + print(name) + elif isinstance(pycairo_obj, type): + for method_name in dir(pycairo_obj): + if method_name.startswith('__'): + continue + pycairo_method = getattr(pycairo_obj, method_name) + cairocffi_method = getattr(cairocffi_obj, method_name, None) + if cairocffi_method is None: + print('%s.%s' % (name, method_name)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/utils/mkconstants.py new/cairocffi-0.8.0/utils/mkconstants.py --- old/cairocffi-0.7.2/utils/mkconstants.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cairocffi-0.8.0/utils/mkconstants.py 2016-08-26 18:06:11.000000000 +0200 @@ -0,0 +1,83 @@ +# coding: utf-8 +import os +import sys +import re +import pycparser.c_generator + + +def parse_constant(node): + if isinstance(node, pycparser.c_ast.Constant): + return node.value + elif isinstance(node, pycparser.c_ast.UnaryOp) and node.op == '-': + return '-' + parse_constant(node.expr) + else: + raise TypeError(node) + + +class PrintEnumsVisitor(pycparser.c_ast.NodeVisitor): + def visit_Enum(self, node): + value = 0 + for enumerator in node.values.enumerators: + if enumerator.value is not None: + value_string = parse_constant(enumerator.value) + value = int(value_string, 0) + else: + value_string = str(value) + assert enumerator.name.startswith('CAIRO_') # len('CAIRO_') == 6 + print('%s = %s' % (enumerator.name[6:], value_string)) + value += 1 + print('') + + +def read_cairo_header(cairo_git_dir, suffix): + filename = os.path.join(cairo_git_dir, 'src', 'cairo%s.h' % suffix) + source = open(filename).read() + source = re.sub( + '/\*.*?\*/' + '|CAIRO_(BEGIN|END)_DECLS' + '|cairo_public ' + r'|^\s*#.*?[^\\]\n', + '', + source, + flags=re.DOTALL | re.MULTILINE) + source = re.sub('\n{3,}', '\n\n', source) + return source + + +def generate(cairo_git_dir): + # Remove comments, preprocessor instructions and macros. + source = read_cairo_header(cairo_git_dir, '') + source += read_cairo_header(cairo_git_dir, '-pdf') + source += read_cairo_header(cairo_git_dir, '-ps') + source += read_cairo_header(cairo_git_dir, '-svg') + + source += ''' + typedef void* HDC; + typedef void* HFONT; + typedef void LOGFONTW; + ''' + source += read_cairo_header(cairo_git_dir, '-win32') + + source += ''' + typedef void* CGContextRef; + typedef void* CGFontRef; + typedef void* ATSUFontID; + ''' + source += read_cairo_header(cairo_git_dir, '-quartz') + + ast = pycparser.CParser().parse(source) + + print('# *** Do not edit this file ***') + print('# Generated by utils/mkconstants.py\n') + PrintEnumsVisitor().visit(ast) + print('_CAIRO_HEADERS = r"""%s"""' % source) + + source = read_cairo_header(cairo_git_dir, '-xcb') + print('_CAIRO_XCB_HEADERS = r"""%s"""\n' % source) + + +if __name__ == '__main__': + if len(sys.argv) >= 2: + generate(sys.argv[1]) + else: + print('Usage: %s path/to/cairo_source.git' % sys.argv[0]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/utils/pango_example.py new/cairocffi-0.8.0/utils/pango_example.py --- old/cairocffi-0.7.2/utils/pango_example.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cairocffi-0.8.0/utils/pango_example.py 2016-08-26 18:06:11.000000000 +0200 @@ -0,0 +1,56 @@ +# coding: utf-8 +import cairocffi +import cffi + + +ffi = cffi.FFI() +ffi.include(cairocffi.ffi) +ffi.cdef(''' + /* GLib */ + typedef void* gpointer; + void g_object_unref (gpointer object); + + /* Pango and PangoCairo */ + typedef ... PangoLayout; + typedef enum { + PANGO_ALIGN_LEFT, + PANGO_ALIGN_CENTER, + PANGO_ALIGN_RIGHT + } PangoAlignment; + int pango_units_from_double (double d); + PangoLayout * pango_cairo_create_layout (cairo_t *cr); + void pango_cairo_show_layout (cairo_t *cr, PangoLayout *layout); + void pango_layout_set_width (PangoLayout *layout, int width); + void pango_layout_set_alignment ( + PangoLayout *layout, PangoAlignment alignment); + void pango_layout_set_markup ( + PangoLayout *layout, const char *text, int length); +''') +gobject = ffi.dlopen('gobject-2.0') +pango = ffi.dlopen('pango-1.0') +pangocairo = ffi.dlopen('pangocairo-1.0') + +gobject_ref = lambda pointer: ffi.gc(pointer, gobject.g_object_unref) +units_from_double = pango.pango_units_from_double + + +def write_example_pdf(target): + pt_per_mm = 72 / 25.4 + width, height = 210 * pt_per_mm, 297 * pt_per_mm # A4 portrait + surface = cairocffi.PDFSurface(target, width, height) + context = cairocffi.Context(surface) + context.translate(0, 300) + context.rotate(-0.2) + + layout = gobject_ref( + pangocairo.pango_cairo_create_layout(context._pointer)) + pango.pango_layout_set_width(layout, units_from_double(width)) + pango.pango_layout_set_alignment(layout, pango.PANGO_ALIGN_CENTER) + markup = u'<span font="italic 30">Hi from Παν語!</span>' + markup = ffi.new('char[]', markup.encode('utf8')) + pango.pango_layout_set_markup(layout, markup, -1) + pangocairo.pango_cairo_show_layout(context._pointer, layout) + + +if __name__ == '__main__': + write_example_pdf(target='pango_example.pdf') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/utils/pycairo_to_cairocffi.py new/cairocffi-0.8.0/utils/pycairo_to_cairocffi.py --- old/cairocffi-0.7.2/utils/pycairo_to_cairocffi.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cairocffi-0.8.0/utils/pycairo_to_cairocffi.py 2016-08-26 18:06:11.000000000 +0200 @@ -0,0 +1,27 @@ +# coding: utf-8 + +import cairo # pycairo +import cairocffi + + +def _UNSAFE_pycairo_context_to_cairocffi(pycairo_context): + # Sanity check. Continuing with another type would probably segfault. + if not isinstance(pycairo_context, cairo.Context): + raise TypeError('Expected a cairo.Context, got %r' % pycairo_context) + + # On CPython, id() gives the memory address of a Python object. + # pycairo implements Context as a C struct: + # typedef struct { + # PyObject_HEAD + # cairo_t *ctx; + # PyObject *base; + # } PycairoContext; + # Still on CPython, object.__basicsize__ is the size of PyObject_HEAD, + # ie. the offset to the ctx field. + # ffi.cast() converts the integer address to a cairo_t** pointer. + # [0] dereferences that pointer, ie. read the ctx field. + # The result is a cairo_t* pointer that cairocffi can use. + return cairocffi.Context._from_pointer( + cairocffi.ffi.cast('cairo_t **', + id(pycairo_context) + object.__basicsize__)[0], + incref=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cairocffi-0.7.2/utils/tests.py new/cairocffi-0.8.0/utils/tests.py --- old/cairocffi-0.7.2/utils/tests.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cairocffi-0.8.0/utils/tests.py 2016-08-26 18:06:11.000000000 +0200 @@ -0,0 +1,29 @@ +# coding: utf-8 + +import io +import cairo # pycairo +import cairocffi + +from pycairo_to_cairocffi import _UNSAFE_pycairo_context_to_cairocffi +from cairocffi_to_pycairo import _UNSAFE_cairocffi_context_to_pycairo +import pango_example + + +def test(): + cairocffi_context = cairocffi.Context(cairocffi.PDFSurface(None, 10, 20)) + cairocffi_context.scale(2, 3) + pycairo_context = _UNSAFE_cairocffi_context_to_pycairo(cairocffi_context) + cairocffi_context2 = _UNSAFE_pycairo_context_to_cairocffi(pycairo_context) + assert tuple(cairocffi_context.get_matrix()) == (2, 0, 0, 3, 0, 0) + assert tuple(cairocffi_context2.get_matrix()) == (2, 0, 0, 3, 0, 0) + assert tuple(pycairo_context.get_matrix()) == (2, 0, 0, 3, 0, 0) + assert cairocffi_context2._pointer == cairocffi_context._pointer + + file_obj = io.BytesIO() + # Mostly test that this runs without raising. + pango_example.write_example_pdf(file_obj) + assert file_obj.getvalue().startswith(b'%PDF') + + +if __name__ == '__main__': + test()