blob: 2d2410562411d689de460914ac74b3b2c1e642d8 [file] [log] [blame]
Haibo Huang5406a6a2020-02-26 16:36:20 -08001#! /usr/bin/env python3
jvr3285b4b2001-08-09 18:47:22 +00002
Denis Jacqueryedb08ee22013-11-29 14:11:19 +01003from __future__ import print_function
Haibo Huang8b3c57b2018-07-03 17:43:11 -07004import io
5import sys
6import os
7from os.path import isfile, join as pjoin
8from glob import glob
Haibo Huangd123eeb2020-04-03 12:18:18 -07009from setuptools import setup, find_packages, Command, Extension
10from setuptools.command.build_ext import build_ext as _build_ext
Haibo Huang8b3c57b2018-07-03 17:43:11 -070011from distutils import log
12from distutils.util import convert_path
13import subprocess as sp
14import contextlib
15import re
jvr3285b4b2001-08-09 18:47:22 +000016
Haibo Huang8b3c57b2018-07-03 17:43:11 -070017# Force distutils to use py_compile.compile() function with 'doraise' argument
18# set to True, in order to raise an exception on compilation errors
19import py_compile
Elliott Hughes02cec462023-11-10 19:23:18 +000020
Haibo Huang8b3c57b2018-07-03 17:43:11 -070021orig_py_compile = py_compile.compile
jvr3285b4b2001-08-09 18:47:22 +000022
Elliott Hughes02cec462023-11-10 19:23:18 +000023
Haibo Huang8b3c57b2018-07-03 17:43:11 -070024def doraise_py_compile(file, cfile=None, dfile=None, doraise=False):
Elliott Hughes02cec462023-11-10 19:23:18 +000025 orig_py_compile(file, cfile=cfile, dfile=dfile, doraise=True)
26
Haibo Huang8b3c57b2018-07-03 17:43:11 -070027
28py_compile.compile = doraise_py_compile
29
Haibo Huangd123eeb2020-04-03 12:18:18 -070030setup_requires = []
31
Elliott Hughes02cec462023-11-10 19:23:18 +000032if {"bdist_wheel"}.intersection(sys.argv):
33 setup_requires.append("wheel")
Haibo Huangd123eeb2020-04-03 12:18:18 -070034
Elliott Hughes02cec462023-11-10 19:23:18 +000035if {"release"}.intersection(sys.argv):
36 setup_requires.append("bump2version")
Haibo Huangd123eeb2020-04-03 12:18:18 -070037
38try:
Elliott Hughes02cec462023-11-10 19:23:18 +000039 __import__("cython")
Haibo Huangd123eeb2020-04-03 12:18:18 -070040except ImportError:
Elliott Hughes02cec462023-11-10 19:23:18 +000041 has_cython = False
Haibo Huangd123eeb2020-04-03 12:18:18 -070042else:
Elliott Hughes02cec462023-11-10 19:23:18 +000043 has_cython = True
Haibo Huangd123eeb2020-04-03 12:18:18 -070044
45env_with_cython = os.environ.get("FONTTOOLS_WITH_CYTHON")
46with_cython = (
Elliott Hughes02cec462023-11-10 19:23:18 +000047 True
48 if env_with_cython in {"1", "true", "yes"}
Elliott Hughes8e084f22024-04-01 15:28:06 +000049 else False if env_with_cython in {"0", "false", "no"} else None
Haibo Huangd123eeb2020-04-03 12:18:18 -070050)
51# --with-cython/--without-cython options override environment variables
Elliott Hughes02cec462023-11-10 19:23:18 +000052opt_with_cython = {"--with-cython"}.intersection(sys.argv)
53opt_without_cython = {"--without-cython"}.intersection(sys.argv)
Haibo Huangd123eeb2020-04-03 12:18:18 -070054if opt_with_cython and opt_without_cython:
Elliott Hughes02cec462023-11-10 19:23:18 +000055 sys.exit(
56 "error: the options '--with-cython' and '--without-cython' are "
57 "mutually exclusive"
58 )
Haibo Huangd123eeb2020-04-03 12:18:18 -070059elif opt_with_cython:
Elliott Hughes02cec462023-11-10 19:23:18 +000060 sys.argv.remove("--with-cython")
61 with_cython = True
Haibo Huangd123eeb2020-04-03 12:18:18 -070062elif opt_without_cython:
Elliott Hughes02cec462023-11-10 19:23:18 +000063 sys.argv.remove("--without-cython")
64 with_cython = False
Haibo Huangd123eeb2020-04-03 12:18:18 -070065
66if with_cython and not has_cython:
Elliott Hughes02cec462023-11-10 19:23:18 +000067 setup_requires.append("cython")
Haibo Huangd123eeb2020-04-03 12:18:18 -070068
69ext_modules = []
70if with_cython is True or (with_cython is None and has_cython):
Elliott Hughes02cec462023-11-10 19:23:18 +000071 ext_modules.append(
72 Extension("fontTools.cu2qu.cu2qu", ["Lib/fontTools/cu2qu/cu2qu.py"]),
73 )
74 ext_modules.append(
75 Extension("fontTools.qu2cu.qu2cu", ["Lib/fontTools/qu2cu/qu2cu.py"]),
76 )
77 ext_modules.append(
78 Extension("fontTools.misc.bezierTools", ["Lib/fontTools/misc/bezierTools.py"]),
79 )
80 ext_modules.append(
81 Extension("fontTools.pens.momentsPen", ["Lib/fontTools/pens/momentsPen.py"]),
82 )
83 ext_modules.append(
84 Extension("fontTools.varLib.iup", ["Lib/fontTools/varLib/iup.py"]),
85 )
86 ext_modules.append(
87 Extension("fontTools.feaLib.lexer", ["Lib/fontTools/feaLib/lexer.py"]),
88 )
Haibo Huang8b3c57b2018-07-03 17:43:11 -070089
Elliott Hughes69c9aca2018-10-30 14:11:58 -070090extras_require = {
Elliott Hughes02cec462023-11-10 19:23:18 +000091 # for fontTools.ufoLib: to read/write UFO fonts
92 "ufo": [
93 "fs >= 2.2.0, < 3",
94 ],
95 # for fontTools.misc.etree and fontTools.misc.plistlib: use lxml to
96 # read/write XML files (faster/safer than built-in ElementTree)
97 "lxml": [
Elliott Hughes8e084f22024-04-01 15:28:06 +000098 "lxml >= 4.0",
Elliott Hughes02cec462023-11-10 19:23:18 +000099 ],
100 # for fontTools.sfnt and fontTools.woff2: to compress/uncompress
101 # WOFF 1.0 and WOFF 2.0 webfonts.
102 "woff": [
103 "brotli >= 1.0.1; platform_python_implementation == 'CPython'",
104 "brotlicffi >= 0.8.0; platform_python_implementation != 'CPython'",
105 "zopfli >= 0.1.4",
106 ],
107 # for fontTools.unicode and fontTools.unicodedata: to use the latest version
108 # of the Unicode Character Database instead of the built-in unicodedata
109 # which varies between python versions and may be outdated.
110 "unicode": [
111 ("unicodedata2 >= 15.1.0; python_version <= '3.12'"),
112 ],
113 # for graphite type tables in ttLib/tables (Silf, Glat, Gloc)
114 "graphite": ["lz4 >= 1.7.4.2"],
115 # for fontTools.interpolatable: to solve the "minimum weight perfect
116 # matching problem in bipartite graphs" (aka Assignment problem)
117 "interpolatable": [
118 # use pure-python alternative on pypy
119 "scipy; platform_python_implementation != 'PyPy'",
120 "munkres; platform_python_implementation == 'PyPy'",
Elliott Hughes8e084f22024-04-01 15:28:06 +0000121 # to output PDF or HTML reports. NOTE: wheels are only available for
122 # windows currently, other platforms will need to build from source.
123 "pycairo",
Elliott Hughes02cec462023-11-10 19:23:18 +0000124 ],
125 # for fontTools.varLib.plot, to visualize DesignSpaceDocument and resulting
126 # VariationModel
127 "plot": [
128 # TODO: figure out the minimum version of matplotlib that we need
129 "matplotlib",
130 ],
131 # for fontTools.misc.symfont, module for symbolic font statistics analysis
132 "symfont": [
133 "sympy",
134 ],
135 # To get file creator and type of Macintosh PostScript Type 1 fonts (macOS only)
136 "type1": [
137 "xattr; sys_platform == 'darwin'",
138 ],
139 # for fontTools.ttLib.removeOverlaps, to remove overlaps in TTF fonts
140 "pathops": [
141 "skia-pathops >= 0.5.0",
142 ],
143 # for packing GSUB/GPOS tables with Harfbuzz repacker
144 "repacker": [
145 "uharfbuzz >= 0.23.0",
146 ],
Elliott Hughes69c9aca2018-10-30 14:11:58 -0700147}
148# use a special 'all' key as shorthand to includes all the extra dependencies
149extras_require["all"] = sum(extras_require.values(), [])
150
151
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700152# Trove classifiers for PyPI
Elliott Hughes02cec462023-11-10 19:23:18 +0000153classifiers = {
154 "classifiers": [
155 "Development Status :: 5 - Production/Stable",
156 "Environment :: Console",
157 "Environment :: Other Environment",
158 "Intended Audience :: Developers",
159 "Intended Audience :: End Users/Desktop",
160 "License :: OSI Approved :: MIT License",
161 "Natural Language :: English",
162 "Operating System :: OS Independent",
163 "Programming Language :: Python",
164 "Programming Language :: Python :: 3.8",
165 "Programming Language :: Python :: 3.9",
166 "Programming Language :: Python :: 3.10",
167 "Programming Language :: Python :: 3.11",
168 "Programming Language :: Python :: 3.12",
169 "Programming Language :: Python :: 3",
170 "Topic :: Text Processing :: Fonts",
171 "Topic :: Multimedia :: Graphics",
172 "Topic :: Multimedia :: Graphics :: Graphics Conversion",
173 ]
174}
jvr5808f3f2001-08-09 23:03:47 +0000175
176
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700177# concatenate README.rst and NEWS.rest into long_description so they are
178# displayed on the FontTols project page on PyPI
179with io.open("README.rst", "r", encoding="utf-8") as readme:
Elliott Hughes02cec462023-11-10 19:23:18 +0000180 long_description = readme.read()
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700181long_description += "\nChangelog\n~~~~~~~~~\n\n"
182with io.open("NEWS.rst", "r", encoding="utf-8") as changelog:
Elliott Hughes02cec462023-11-10 19:23:18 +0000183 long_description += changelog.read()
jvr059cbe32002-07-01 09:11:01 +0000184
185
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700186@contextlib.contextmanager
187def capture_logger(name):
Elliott Hughes02cec462023-11-10 19:23:18 +0000188 """Context manager to capture a logger output with a StringIO stream."""
189 import logging
jvr91bde172003-01-03 21:01:07 +0000190
Elliott Hughes02cec462023-11-10 19:23:18 +0000191 logger = logging.getLogger(name)
192 try:
193 import StringIO
194
195 stream = StringIO.StringIO()
196 except ImportError:
197 stream = io.StringIO()
198 handler = logging.StreamHandler(stream)
199 logger.addHandler(handler)
200 try:
201 yield stream
202 finally:
203 logger.removeHandler(handler)
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700204
205
206class release(Command):
Elliott Hughes02cec462023-11-10 19:23:18 +0000207 """
208 Tag a new release with a single command, using the 'bumpversion' tool
209 to update all the version strings in the source code.
210 The version scheme conforms to 'SemVer' and PEP 440 specifications.
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700211
Elliott Hughes02cec462023-11-10 19:23:18 +0000212 Firstly, the pre-release '.devN' suffix is dropped to signal that this is
213 a stable release. If '--major' or '--minor' options are passed, the
214 the first or second 'semver' digit is also incremented. Major is usually
215 for backward-incompatible API changes, while minor is used when adding
216 new backward-compatible functionalities. No options imply 'patch' or bug-fix
217 release.
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700218
Elliott Hughes02cec462023-11-10 19:23:18 +0000219 A new header is also added to the changelog file ("NEWS.rst"), containing
220 the new version string and the current 'YYYY-MM-DD' date.
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700221
Elliott Hughes02cec462023-11-10 19:23:18 +0000222 All changes are committed, and an annotated git tag is generated. With the
223 --sign option, the tag is GPG-signed with the user's default key.
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700224
Elliott Hughes02cec462023-11-10 19:23:18 +0000225 Finally, the 'patch' part of the version string is bumped again, and a
226 pre-release suffix '.dev0' is appended to mark the opening of a new
227 development cycle.
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700228
Elliott Hughes02cec462023-11-10 19:23:18 +0000229 Links:
230 - http://semver.org/
231 - https://www.python.org/dev/peps/pep-0440/
232 - https://github.com/c4urself/bump2version
233 """
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700234
Elliott Hughes02cec462023-11-10 19:23:18 +0000235 description = "update version strings for release"
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700236
Elliott Hughes02cec462023-11-10 19:23:18 +0000237 user_options = [
238 ("major", None, "bump the first digit (incompatible API changes)"),
239 ("minor", None, "bump the second digit (new backward-compatible features)"),
240 ("sign", "s", "make a GPG-signed tag, using the default key"),
241 ("allow-dirty", None, "don't abort if working directory is dirty"),
242 ]
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700243
Elliott Hughes02cec462023-11-10 19:23:18 +0000244 changelog_name = "NEWS.rst"
Elliott Hughes8e084f22024-04-01 15:28:06 +0000245 version_RE = re.compile(r"^[0-9]+\.[0-9]+")
Elliott Hughes02cec462023-11-10 19:23:18 +0000246 date_fmt = "%Y-%m-%d"
247 header_fmt = "%s (released %s)"
248 commit_message = "Release {new_version}"
249 tag_name = "{new_version}"
250 version_files = [
251 "setup.cfg",
252 "setup.py",
253 "Lib/fontTools/__init__.py",
254 ]
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700255
Elliott Hughes02cec462023-11-10 19:23:18 +0000256 def initialize_options(self):
257 self.minor = False
258 self.major = False
259 self.sign = False
260 self.allow_dirty = False
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700261
Elliott Hughes02cec462023-11-10 19:23:18 +0000262 def finalize_options(self):
263 if all([self.major, self.minor]):
264 from distutils.errors import DistutilsOptionError
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700265
Elliott Hughes02cec462023-11-10 19:23:18 +0000266 raise DistutilsOptionError("--major/--minor are mutually exclusive")
267 self.part = "major" if self.major else "minor" if self.minor else None
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700268
Elliott Hughes02cec462023-11-10 19:23:18 +0000269 def run(self):
270 if self.part is not None:
271 log.info("bumping '%s' version" % self.part)
272 self.bumpversion(self.part, commit=False)
273 release_version = self.bumpversion(
274 "release", commit=False, allow_dirty=True
275 )
276 else:
277 log.info("stripping pre-release suffix")
278 release_version = self.bumpversion("release")
279 log.info(" version = %s" % release_version)
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700280
Elliott Hughes02cec462023-11-10 19:23:18 +0000281 changes = self.format_changelog(release_version)
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700282
Elliott Hughes02cec462023-11-10 19:23:18 +0000283 self.git_commit(release_version)
284 self.git_tag(release_version, changes, self.sign)
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700285
Elliott Hughes02cec462023-11-10 19:23:18 +0000286 log.info("bumping 'patch' version and pre-release suffix")
287 next_dev_version = self.bumpversion("patch", commit=True)
288 log.info(" version = %s" % next_dev_version)
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700289
Elliott Hughes02cec462023-11-10 19:23:18 +0000290 def git_commit(self, version):
291 """Stage and commit all relevant version files, and format the commit
292 message with specified 'version' string.
293 """
294 files = self.version_files + [self.changelog_name]
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700295
Elliott Hughes02cec462023-11-10 19:23:18 +0000296 log.info("committing changes")
297 for f in files:
298 log.info(" %s" % f)
299 if self.dry_run:
300 return
301 sp.check_call(["git", "add"] + files)
302 msg = self.commit_message.format(new_version=version)
303 sp.check_call(["git", "commit", "-m", msg], stdout=sp.PIPE)
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700304
Elliott Hughes02cec462023-11-10 19:23:18 +0000305 def git_tag(self, version, message, sign=False):
306 """Create annotated git tag with given 'version' and 'message'.
307 Optionally 'sign' the tag with the user's GPG key.
308 """
309 log.info(
310 "creating %s git tag '%s'" % ("signed" if sign else "annotated", version)
311 )
312 if self.dry_run:
313 return
314 # create an annotated (or signed) tag from the new version
315 tag_opt = "-s" if sign else "-a"
316 tag_name = self.tag_name.format(new_version=version)
317 proc = sp.Popen(["git", "tag", tag_opt, "-F", "-", tag_name], stdin=sp.PIPE)
318 # use the latest changes from the changelog file as the tag message
319 tag_message = "%s\n\n%s" % (tag_name, message)
320 proc.communicate(tag_message.encode("utf-8"))
321 if proc.returncode != 0:
322 sys.exit(proc.returncode)
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700323
Elliott Hughes02cec462023-11-10 19:23:18 +0000324 def bumpversion(self, part, commit=False, message=None, allow_dirty=None):
325 """Run bumpversion.main() with the specified arguments, and return the
326 new computed version string (cf. 'bumpversion --help' for more info)
327 """
328 import bumpversion.cli
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700329
Elliott Hughes02cec462023-11-10 19:23:18 +0000330 args = (
331 (["--verbose"] if self.verbose > 1 else [])
332 + (["--dry-run"] if self.dry_run else [])
333 + (["--allow-dirty"] if (allow_dirty or self.allow_dirty) else [])
334 + (["--commit"] if commit else ["--no-commit"])
335 + (["--message", message] if message is not None else [])
336 + ["--list", part]
337 )
338 log.debug("$ bumpversion %s" % " ".join(a.replace(" ", "\\ ") for a in args))
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700339
Elliott Hughes02cec462023-11-10 19:23:18 +0000340 with capture_logger("bumpversion.list") as out:
341 bumpversion.cli.main(args)
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700342
Elliott Hughes02cec462023-11-10 19:23:18 +0000343 last_line = out.getvalue().splitlines()[-1]
344 new_version = last_line.replace("new_version=", "")
345 return new_version
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700346
Elliott Hughes02cec462023-11-10 19:23:18 +0000347 def format_changelog(self, version):
348 """Write new header at beginning of changelog file with the specified
349 'version' and the current date.
350 Return the changelog content for the current release.
351 """
352 from datetime import datetime
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700353
Elliott Hughes02cec462023-11-10 19:23:18 +0000354 log.info("formatting changelog")
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700355
Elliott Hughes02cec462023-11-10 19:23:18 +0000356 changes = []
357 with io.open(self.changelog_name, "r+", encoding="utf-8") as f:
358 for ln in f:
359 if self.version_RE.match(ln):
360 break
361 else:
362 changes.append(ln)
363 if not self.dry_run:
364 f.seek(0)
365 content = f.read()
366 date = datetime.today().strftime(self.date_fmt)
367 f.seek(0)
368 header = self.header_fmt % (version, date)
369 f.write(header + "\n" + "-" * len(header) + "\n\n" + content)
370
371 return "".join(changes)
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700372
373
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700374def find_data_files(manpath="share/man"):
Elliott Hughes02cec462023-11-10 19:23:18 +0000375 """Find FontTools's data_files (just man pages at this point).
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700376
Elliott Hughes02cec462023-11-10 19:23:18 +0000377 By default, we install man pages to "share/man" directory relative to the
378 base installation directory for data_files. The latter can be changed with
379 the --install-data option of 'setup.py install' sub-command.
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700380
Elliott Hughes02cec462023-11-10 19:23:18 +0000381 E.g., if the data files installation directory is "/usr", the default man
382 page installation directory will be "/usr/share/man".
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700383
Elliott Hughes02cec462023-11-10 19:23:18 +0000384 You can override this via the $FONTTOOLS_MANPATH environment variable.
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700385
Elliott Hughes02cec462023-11-10 19:23:18 +0000386 E.g., on some BSD systems man pages are installed to 'man' instead of
387 'share/man'; you can export $FONTTOOLS_MANPATH variable just before
388 installing:
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700389
Elliott Hughes02cec462023-11-10 19:23:18 +0000390 $ FONTTOOLS_MANPATH="man" pip install -v .
391 [...]
392 running install_data
393 copying Doc/man/ttx.1 -> /usr/man/man1
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700394
Elliott Hughes02cec462023-11-10 19:23:18 +0000395 When installing from PyPI, for this variable to have effect you need to
396 force pip to install from the source distribution instead of the wheel
397 package (otherwise setup.py is not run), by using the --no-binary option:
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700398
Elliott Hughes02cec462023-11-10 19:23:18 +0000399 $ FONTTOOLS_MANPATH="man" pip install --no-binary=fonttools fonttools
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700400
Elliott Hughes02cec462023-11-10 19:23:18 +0000401 Note that you can only override the base man path, i.e. without the
402 section number (man1, man3, etc.). The latter is always implied to be 1,
403 for "general commands".
404 """
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700405
Elliott Hughes02cec462023-11-10 19:23:18 +0000406 # get base installation directory for man pages
407 manpagebase = os.environ.get("FONTTOOLS_MANPATH", convert_path(manpath))
408 # all our man pages go to section 1
409 manpagedir = pjoin(manpagebase, "man1")
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700410
Elliott Hughes02cec462023-11-10 19:23:18 +0000411 manpages = [f for f in glob(pjoin("Doc", "man", "man1", "*.1")) if isfile(f)]
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700412
Elliott Hughes02cec462023-11-10 19:23:18 +0000413 data_files = [(manpagedir, manpages)]
414 return data_files
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700415
jvr91bde172003-01-03 21:01:07 +0000416
Haibo Huangd123eeb2020-04-03 12:18:18 -0700417class cython_build_ext(_build_ext):
Elliott Hughes02cec462023-11-10 19:23:18 +0000418 """Compile *.pyx source files to *.c using cythonize if Cython is
419 installed and there is a working C compiler, else fall back to pure python dist.
420 """
Haibo Huangd123eeb2020-04-03 12:18:18 -0700421
Elliott Hughes02cec462023-11-10 19:23:18 +0000422 def finalize_options(self):
423 from Cython.Build import cythonize
Haibo Huangd123eeb2020-04-03 12:18:18 -0700424
Elliott Hughes02cec462023-11-10 19:23:18 +0000425 # optionally enable line tracing for test coverage support
426 linetrace = os.environ.get("CYTHON_TRACE") == "1"
Haibo Huangd123eeb2020-04-03 12:18:18 -0700427
Elliott Hughes02cec462023-11-10 19:23:18 +0000428 self.distribution.ext_modules[:] = cythonize(
429 self.distribution.ext_modules,
430 force=linetrace or self.force,
431 annotate=os.environ.get("CYTHON_ANNOTATE") == "1",
432 quiet=not self.verbose,
433 compiler_directives={
434 "linetrace": linetrace,
435 "language_level": 3,
436 "embedsignature": True,
437 },
438 )
Haibo Huangd123eeb2020-04-03 12:18:18 -0700439
Elliott Hughes02cec462023-11-10 19:23:18 +0000440 _build_ext.finalize_options(self)
Haibo Huangd123eeb2020-04-03 12:18:18 -0700441
Elliott Hughes02cec462023-11-10 19:23:18 +0000442 def build_extensions(self):
443 try:
444 _build_ext.build_extensions(self)
445 except Exception as e:
446 if with_cython:
447 raise
448 from distutils.errors import DistutilsModuleError
Haibo Huangd123eeb2020-04-03 12:18:18 -0700449
Elliott Hughes02cec462023-11-10 19:23:18 +0000450 # optional compilation failed: we delete 'ext_modules' and make sure
451 # the generated wheel is 'pure'
452 del self.distribution.ext_modules[:]
453 try:
454 bdist_wheel = self.get_finalized_command("bdist_wheel")
455 except DistutilsModuleError:
456 # 'bdist_wheel' command not available as wheel is not installed
457 pass
458 else:
459 bdist_wheel.root_is_pure = True
460 log.error("error: building extensions failed: %s" % e)
461
Haibo Huangd123eeb2020-04-03 12:18:18 -0700462
463cmdclass = {"release": release}
464
465if ext_modules:
466 cmdclass["build_ext"] = cython_build_ext
467
468
469setup_params = dict(
Elliott Hughes02cec462023-11-10 19:23:18 +0000470 name="fonttools",
Elliott Hughes8e084f22024-04-01 15:28:06 +0000471 version="4.49.0",
Elliott Hughes02cec462023-11-10 19:23:18 +0000472 description="Tools to manipulate font files",
473 author="Just van Rossum",
474 author_email="just@letterror.com",
475 maintainer="Behdad Esfahbod",
476 maintainer_email="behdad@behdad.org",
477 url="http://github.com/fonttools/fonttools",
478 license="MIT",
479 platforms=["Any"],
480 python_requires=">=3.8",
481 long_description=long_description,
482 package_dir={"": "Lib"},
483 packages=find_packages("Lib"),
484 include_package_data=True,
485 data_files=find_data_files(),
486 ext_modules=ext_modules,
487 setup_requires=setup_requires,
488 extras_require=extras_require,
489 entry_points={
490 "console_scripts": [
491 "fonttools = fontTools.__main__:main",
492 "ttx = fontTools.ttx:main",
493 "pyftsubset = fontTools.subset:main",
494 "pyftmerge = fontTools.merge:main",
495 ]
496 },
497 cmdclass=cmdclass,
498 **classifiers,
Haibo Huang8b3c57b2018-07-03 17:43:11 -0700499)
Haibo Huangd123eeb2020-04-03 12:18:18 -0700500
501
502if __name__ == "__main__":
Elliott Hughes02cec462023-11-10 19:23:18 +0000503 setup(**setup_params)