Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 88a664e

Browse filesBrowse files
committed
Use a specific version of Freetype for testing
This should theoretically allow us to turn down the tolerance on image comparison tests.
1 parent 240850a commit 88a664e
Copy full SHA for 88a664e

File tree

Expand file treeCollapse file tree

8 files changed

+140
-37
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+140
-37
lines changed

‎.gitignore

Copy file name to clipboardExpand all lines: .gitignore
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ dist
3939
.eggs
4040
# tox testing tool
4141
.tox
42+
setup.cfg
4243

4344
# OS generated files #
4445
######################

‎.travis.yml

Copy file name to clipboardExpand all lines: .travis.yml
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ install:
7575
# version since is it basically just a .ttf file
7676
# The current Travis Ubuntu image is to old to search .local/share/fonts so we store fonts in .fonts
7777

78-
# We install ipython to use the console highlighting. From IPython 3 this depends on jsonschema and misture.
78+
# We install ipython to use the console highlighting. From IPython 3 this depends on jsonschema and mistune.
7979
# Neihter is installed as a dependency of IPython since they are not used by the IPython console.
8080
- |
8181
if [[ $BUILD_DOCS == true ]]; then
@@ -90,6 +90,10 @@ install:
9090
cp Felipa-Regular.ttf ~/.fonts
9191
fc-cache -f -v
9292
fi;
93+
94+
# Use the special local version of freetype for testing
95+
- echo '[test]\ntesting_freetype = True' > setup.cfg
96+
9397
- python setup.py install
9498

9599
script:

‎doc/devel/testing.rst

Copy file name to clipboardExpand all lines: doc/devel/testing.rst
+16-11Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ Optionally you can install:
3333

3434
- `pep8 <http://pep8.readthedocs.org/en/latest>`_ to test coding standards
3535

36+
Build matplotlib for image comparison tests
37+
-------------------------------------------
38+
39+
matplotlib's test suite makes heavy use of image comparison tests,
40+
meaning the result of a plot is compared against a known good result.
41+
Unfortunately, different versions of freetype produce differently
42+
formed characters, causing these image comparisons to fail. To make
43+
them reproducible, matplotlib can be built with a special local copy
44+
of freetype. This is recommended for all matplotlib developers.
45+
46+
Add the following content to a ``setup.cfg`` file at the root of the
47+
matplotlib source directory::
48+
49+
[test]
50+
testing_freetype = True
51+
3652
Running the tests
3753
-----------------
3854

@@ -185,17 +201,6 @@ decorator:
185201
If some variation is expected in the image between runs, this
186202
value may be adjusted.
187203

188-
Freetype version
189-
----------------
190-
191-
Due to subtle differences in the font rendering under different
192-
version of freetype some care must be taken when generating the
193-
baseline images. Currently (early 2015), almost all of the images
194-
were generated using ``freetype 2.5.3-21`` on Fedora 21 and only the
195-
fonts that ship with ``matplotlib`` (regenerated in PR #4031 / commit
196-
005cfde02751d274f2ab8016eddd61c3b3828446) and travis is using
197-
``freetype 2.4.8`` on ubuntu.
198-
199204
Known failing tests
200205
-------------------
201206

‎lib/matplotlib/__init__.py

Copy file name to clipboardExpand all lines: lib/matplotlib/__init__.py
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,17 @@ def _init_tests():
14991499
if not os.path.isdir(os.path.join(os.path.dirname(__file__), 'tests')):
15001500
raise ImportError("matplotlib test data is not installed")
15011501

1502+
# The version of freetype to install locally for running the
1503+
# tests. This must match the value in `setupext.py`
1504+
LOCAL_FREETYPE_VERSION = '2.5.2'
1505+
1506+
from matplotlib import ft2font
1507+
if (ft2font.__freetype_version__ != LOCAL_FREETYPE_VERSION or
1508+
ft2font.__freetype_build_type__ != 'local'):
1509+
raise ImportError(
1510+
"matplotlib is not built with the correct freetype version to run "
1511+
"tests. Set local_freetype=True in setup.cfg and rebuild.")
1512+
15021513
try:
15031514
import nose
15041515
try:

‎setup.cfg.template

Copy file name to clipboardExpand all lines: setup.cfg.template
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
# This can be a single directory or a comma-delimited list of directories.
99
#basedirlist = /usr
1010

11+
[test]
12+
# If you plan to develop matplotlib and run or add to the test suite,
13+
# set this to True. It will download and build a specific version of
14+
# freetype, and then use that to build the ft2font extension. This
15+
# ensures that test images are exactly reproducible.
16+
#local_freetype = False
17+
1118
[status]
1219
# To suppress display of the dependencies and their versions
1320
# at the top of the build log, uncomment the following line:

‎setup.py

Copy file name to clipboardExpand all lines: setup.py
+12-2Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from distribute_setup import use_setuptools
1010
use_setuptools()
1111
from setuptools.command.test import test as TestCommand
12+
from setuptools.command.build_ext import build_ext as BuildExtCommand
1213

1314
import sys
1415

@@ -239,8 +240,19 @@ def run_tests(self):
239240
argv=['nosetests'] + self.test_args,
240241
exit=True)
241242

243+
244+
class BuildExtraLibraries(BuildExtCommand):
245+
def run(self):
246+
for package in good_packages:
247+
package.do_custom_build()
248+
249+
return super(BuildExtraLibraries, self).run()
250+
251+
242252
cmdclass = versioneer.get_cmdclass()
243253
cmdclass['test'] = NoseTestCommand
254+
cmdclass['build_ext'] = BuildExtraLibraries
255+
244256

245257
# One doesn't normally see `if __name__ == '__main__'` blocks in a setup.py,
246258
# however, this is needed on Windows to avoid creating infinite subprocesses
@@ -303,8 +315,6 @@ def run_tests(self):
303315
# Now collect all of the information we need to build all of the
304316
# packages.
305317
for package in good_packages:
306-
if isinstance(package, str):
307-
continue
308318
packages.extend(package.get_packages())
309319
namespace_packages.extend(package.get_namespace_packages())
310320
py_modules.extend(package.get_py_modules())

‎setupext.py

Copy file name to clipboardExpand all lines: setupext.py
+80-22Lines changed: 80 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
PY3 = (sys.version_info[0] >= 3)
2121

2222

23+
# This is the version of freetype to use when building a local version
24+
# of freetype. It must match the value in
25+
# lib/matplotlib.__init__.py:validate_test_dependencies
26+
LOCAL_FREETYPE_VERSION = '2.5.2'
27+
28+
2329
if sys.platform != 'win32':
2430
if sys.version_info[0] < 3:
2531
from commands import getstatusoutput
@@ -47,22 +53,19 @@
4753
config = configparser.SafeConfigParser()
4854
config.read(setup_cfg)
4955

50-
try:
56+
if config.has_option('status', 'suppress'):
5157
options['display_status'] = not config.getboolean("status", "suppress")
52-
except:
53-
pass
5458

55-
try:
59+
if config.has_option('rc_options', 'backend'):
5660
options['backend'] = config.get("rc_options", "backend")
57-
except:
58-
pass
5961

60-
try:
62+
if config.has_option('directories', 'basedirlist'):
6163
options['basedirlist'] = [
6264
x.strip() for x in
6365
config.get("directories", "basedirlist").split(',')]
64-
except:
65-
pass
66+
67+
if config.has_option('test', 'local_freetype'):
68+
options['local_freetype'] = config.get("test", "local_freetype")
6669
else:
6770
config = None
6871

@@ -448,6 +451,14 @@ def _check_for_pkg_config(self, package, include_file, min_version=None,
448451

449452
return 'version %s' % version
450453

454+
def do_custom_build(self):
455+
"""
456+
If a package needs to do extra custom things, such as building a
457+
third-party library, before building an extension, it should
458+
override this method.
459+
"""
460+
pass
461+
451462

452463
class OptionalPackage(SetupPackage):
453464
optional = True
@@ -461,10 +472,9 @@ def get_config(cls):
461472
if the package is at default state ("auto"), forced by the user (True)
462473
or opted-out (False).
463474
"""
464-
try:
465-
return config.getboolean(cls.config_category, cls.name)
466-
except:
467-
return "auto"
475+
if config is not None and config.has_option(cls.config_category, cls.name):
476+
return config.get(cls.config_category, cls.name)
477+
return "auto"
468478

469479
def check(self):
470480
"""
@@ -872,6 +882,9 @@ class FreeType(SetupPackage):
872882
name = "freetype"
873883

874884
def check(self):
885+
if options.get('local_freetype'):
886+
return "Using local version for testing"
887+
875888
if sys.platform == 'win32':
876889
check_include_file(get_include_dirs(), 'ft2build.h', 'freetype')
877890
return 'Using unknown version found on system.'
@@ -917,15 +930,60 @@ def version_from_header(self):
917930
return '.'.join([major, minor, patch])
918931

919932
def add_flags(self, ext):
920-
pkg_config.setup_extension(
921-
ext, 'freetype2',
922-
default_include_dirs=[
923-
'include/freetype2', 'freetype2',
924-
'lib/freetype2/include',
925-
'lib/freetype2/include/freetype2'],
926-
default_library_dirs=[
927-
'freetype2/lib'],
928-
default_libraries=['freetype', 'z'])
933+
if options.get('local_freetype'):
934+
src_path = os.path.join(
935+
'build', 'freetype-{0}'.format(LOCAL_FREETYPE_VERSION))
936+
# Statically link to the locally-built freetype.
937+
# This is certainly broken on Windows.
938+
ext.include_dirs.insert(0, os.path.join(src_path, 'include'))
939+
ext.extra_objects.insert(
940+
0, os.path.join(src_path, 'objs', '.libs', 'libfreetype.a'))
941+
ext.define_macros.append(('FREETYPE_BUILD_TYPE', 'local'))
942+
else:
943+
pkg_config.setup_extension(
944+
ext, 'freetype2',
945+
default_include_dirs=[
946+
'include/freetype2', 'freetype2',
947+
'lib/freetype2/include',
948+
'lib/freetype2/include/freetype2'],
949+
default_library_dirs=[
950+
'freetype2/lib'],
951+
default_libraries=['freetype', 'z'])
952+
ext.define_macros.append(('FREETYPE_BUILD_TYPE', 'system'))
953+
954+
def do_custom_build(self):
955+
# We're using a system freetype
956+
if not options.get('local_freetype'):
957+
return
958+
959+
src_path = os.path.join(
960+
'build', 'freetype-{0}'.format(LOCAL_FREETYPE_VERSION))
961+
962+
# We've already built freetype
963+
if os.path.isfile(os.path.join(src_path, 'objs', '.libs', 'libfreetype.a')):
964+
return
965+
966+
tarball = 'freetype-{0}.tar.gz'.format(LOCAL_FREETYPE_VERSION)
967+
tarball_path = os.path.join('build', tarball)
968+
if not os.path.isfile(tarball_path):
969+
print("Downloading {0}".format(tarball))
970+
if sys.version_info[0] == 2:
971+
from urllib import urlretrieve
972+
else:
973+
from urllib.request import urlretrieve
974+
975+
urlretrieve(
976+
'http://download.savannah.gnu.org/releases/freetype/{0}'.format(tarball),
977+
tarball_path)
978+
979+
print("Building {0}".format(tarball))
980+
subprocess.check_call(
981+
['tar zxf {0}'.format(tarball)], shell=True, cwd='build')
982+
subprocess.check_call(
983+
['./configure --without-zlib --without-bzip2 --without-png'],
984+
shell=True, cwd=src_path)
985+
subprocess.check_call(
986+
['make'], shell=True, cwd=src_path)
929987

930988

931989
class FT2Font(SetupPackage):

‎src/ft2font_wrapper.cpp

Copy file name to clipboardExpand all lines: src/ft2font_wrapper.cpp
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
// From Python
88
#include <structmember.h>
99

10+
#define STRINGIFY(s) XSTRINGIFY(s)
11+
#define XSTRINGIFY(s) #s
12+
1013
static PyObject *convert_xys_to_array(std::vector<double> &xys)
1114
{
1215
npy_intp dims[] = {(npy_intp)xys.size() / 2, 2 };
@@ -1759,7 +1762,7 @@ PyMODINIT_FUNC initft2font(void)
17591762
int error = FT_Init_FreeType(&_ft2Library);
17601763

17611764
if (error) {
1762-
PyErr_SetString(PyExc_RuntimeError, "Could not find initialize the freetype2 library");
1765+
PyErr_SetString(PyExc_RuntimeError, "Could not initialize the freetype2 library");
17631766
INITERROR;
17641767
}
17651768

@@ -1774,6 +1777,10 @@ PyMODINIT_FUNC initft2font(void)
17741777
}
17751778
}
17761779

1780+
if (PyModule_AddStringConstant(m, "__freetype_build_type__", STRINGIFY(FREETYPE_BUILD_TYPE))) {
1781+
INITERROR;
1782+
}
1783+
17771784
import_array();
17781785

17791786
#if PY3K

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.