Haibo Huang | 5406a6a | 2020-02-26 16:36:20 -0800 | [diff] [blame] | 1 | #! /usr/bin/env python3 |
jvr | 3285b4b | 2001-08-09 18:47:22 +0000 | [diff] [blame] | 2 | |
Denis Jacquerye | db08ee2 | 2013-11-29 14:11:19 +0100 | [diff] [blame] | 3 | from __future__ import print_function |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 4 | import io |
| 5 | import sys |
| 6 | import os |
| 7 | from os.path import isfile, join as pjoin |
| 8 | from glob import glob |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 9 | from setuptools import setup, find_packages, Command, Extension |
| 10 | from setuptools.command.build_ext import build_ext as _build_ext |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 11 | from distutils import log |
| 12 | from distutils.util import convert_path |
| 13 | import subprocess as sp |
| 14 | import contextlib |
| 15 | import re |
jvr | 3285b4b | 2001-08-09 18:47:22 +0000 | [diff] [blame] | 16 | |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 17 | # Force distutils to use py_compile.compile() function with 'doraise' argument |
| 18 | # set to True, in order to raise an exception on compilation errors |
| 19 | import py_compile |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 20 | |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 21 | orig_py_compile = py_compile.compile |
jvr | 3285b4b | 2001-08-09 18:47:22 +0000 | [diff] [blame] | 22 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 23 | |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 24 | def doraise_py_compile(file, cfile=None, dfile=None, doraise=False): |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 25 | orig_py_compile(file, cfile=cfile, dfile=dfile, doraise=True) |
| 26 | |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 27 | |
| 28 | py_compile.compile = doraise_py_compile |
| 29 | |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 30 | setup_requires = [] |
| 31 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 32 | if {"bdist_wheel"}.intersection(sys.argv): |
| 33 | setup_requires.append("wheel") |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 34 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 35 | if {"release"}.intersection(sys.argv): |
| 36 | setup_requires.append("bump2version") |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 37 | |
| 38 | try: |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 39 | __import__("cython") |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 40 | except ImportError: |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 41 | has_cython = False |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 42 | else: |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 43 | has_cython = True |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 44 | |
| 45 | env_with_cython = os.environ.get("FONTTOOLS_WITH_CYTHON") |
| 46 | with_cython = ( |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 47 | True |
| 48 | if env_with_cython in {"1", "true", "yes"} |
Elliott Hughes | 8e084f2 | 2024-04-01 15:28:06 +0000 | [diff] [blame] | 49 | else False if env_with_cython in {"0", "false", "no"} else None |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 50 | ) |
| 51 | # --with-cython/--without-cython options override environment variables |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 52 | opt_with_cython = {"--with-cython"}.intersection(sys.argv) |
| 53 | opt_without_cython = {"--without-cython"}.intersection(sys.argv) |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 54 | if opt_with_cython and opt_without_cython: |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 55 | sys.exit( |
| 56 | "error: the options '--with-cython' and '--without-cython' are " |
| 57 | "mutually exclusive" |
| 58 | ) |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 59 | elif opt_with_cython: |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 60 | sys.argv.remove("--with-cython") |
| 61 | with_cython = True |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 62 | elif opt_without_cython: |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 63 | sys.argv.remove("--without-cython") |
| 64 | with_cython = False |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 65 | |
| 66 | if with_cython and not has_cython: |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 67 | setup_requires.append("cython") |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 68 | |
| 69 | ext_modules = [] |
| 70 | if with_cython is True or (with_cython is None and has_cython): |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 71 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 89 | |
Elliott Hughes | 69c9aca | 2018-10-30 14:11:58 -0700 | [diff] [blame] | 90 | extras_require = { |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 91 | # 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 Hughes | 8e084f2 | 2024-04-01 15:28:06 +0000 | [diff] [blame] | 98 | "lxml >= 4.0", |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 99 | ], |
| 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 Hughes | 8e084f2 | 2024-04-01 15:28:06 +0000 | [diff] [blame] | 121 | # 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 Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 124 | ], |
| 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 Hughes | 69c9aca | 2018-10-30 14:11:58 -0700 | [diff] [blame] | 147 | } |
| 148 | # use a special 'all' key as shorthand to includes all the extra dependencies |
| 149 | extras_require["all"] = sum(extras_require.values(), []) |
| 150 | |
| 151 | |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 152 | # Trove classifiers for PyPI |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 153 | classifiers = { |
| 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 | } |
jvr | 5808f3f | 2001-08-09 23:03:47 +0000 | [diff] [blame] | 175 | |
| 176 | |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 177 | # concatenate README.rst and NEWS.rest into long_description so they are |
| 178 | # displayed on the FontTols project page on PyPI |
| 179 | with io.open("README.rst", "r", encoding="utf-8") as readme: |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 180 | long_description = readme.read() |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 181 | long_description += "\nChangelog\n~~~~~~~~~\n\n" |
| 182 | with io.open("NEWS.rst", "r", encoding="utf-8") as changelog: |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 183 | long_description += changelog.read() |
jvr | 059cbe3 | 2002-07-01 09:11:01 +0000 | [diff] [blame] | 184 | |
| 185 | |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 186 | @contextlib.contextmanager |
| 187 | def capture_logger(name): |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 188 | """Context manager to capture a logger output with a StringIO stream.""" |
| 189 | import logging |
jvr | 91bde17 | 2003-01-03 21:01:07 +0000 | [diff] [blame] | 190 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 191 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 204 | |
| 205 | |
| 206 | class release(Command): |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 207 | """ |
| 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 211 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 212 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 218 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 219 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 221 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 222 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 224 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 225 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 228 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 229 | Links: |
| 230 | - http://semver.org/ |
| 231 | - https://www.python.org/dev/peps/pep-0440/ |
| 232 | - https://github.com/c4urself/bump2version |
| 233 | """ |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 234 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 235 | description = "update version strings for release" |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 236 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 237 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 243 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 244 | changelog_name = "NEWS.rst" |
Elliott Hughes | 8e084f2 | 2024-04-01 15:28:06 +0000 | [diff] [blame] | 245 | version_RE = re.compile(r"^[0-9]+\.[0-9]+") |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 246 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 255 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 256 | def initialize_options(self): |
| 257 | self.minor = False |
| 258 | self.major = False |
| 259 | self.sign = False |
| 260 | self.allow_dirty = False |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 261 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 262 | def finalize_options(self): |
| 263 | if all([self.major, self.minor]): |
| 264 | from distutils.errors import DistutilsOptionError |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 265 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 266 | raise DistutilsOptionError("--major/--minor are mutually exclusive") |
| 267 | self.part = "major" if self.major else "minor" if self.minor else None |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 268 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 269 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 280 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 281 | changes = self.format_changelog(release_version) |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 282 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 283 | self.git_commit(release_version) |
| 284 | self.git_tag(release_version, changes, self.sign) |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 285 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 286 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 289 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 290 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 295 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 296 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 304 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 305 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 323 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 324 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 329 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 330 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 339 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 340 | with capture_logger("bumpversion.list") as out: |
| 341 | bumpversion.cli.main(args) |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 342 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 343 | last_line = out.getvalue().splitlines()[-1] |
| 344 | new_version = last_line.replace("new_version=", "") |
| 345 | return new_version |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 346 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 347 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 353 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 354 | log.info("formatting changelog") |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 355 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 356 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 372 | |
| 373 | |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 374 | def find_data_files(manpath="share/man"): |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 375 | """Find FontTools's data_files (just man pages at this point). |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 376 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 377 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 380 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 381 | E.g., if the data files installation directory is "/usr", the default man |
| 382 | page installation directory will be "/usr/share/man". |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 383 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 384 | You can override this via the $FONTTOOLS_MANPATH environment variable. |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 385 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 386 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 389 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 390 | $ FONTTOOLS_MANPATH="man" pip install -v . |
| 391 | [...] |
| 392 | running install_data |
| 393 | copying Doc/man/ttx.1 -> /usr/man/man1 |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 394 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 395 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 398 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 399 | $ FONTTOOLS_MANPATH="man" pip install --no-binary=fonttools fonttools |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 400 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 401 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 405 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 406 | # 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 410 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 411 | manpages = [f for f in glob(pjoin("Doc", "man", "man1", "*.1")) if isfile(f)] |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 412 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 413 | data_files = [(manpagedir, manpages)] |
| 414 | return data_files |
Haibo Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 415 | |
jvr | 91bde17 | 2003-01-03 21:01:07 +0000 | [diff] [blame] | 416 | |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 417 | class cython_build_ext(_build_ext): |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 418 | """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 Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 421 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 422 | def finalize_options(self): |
| 423 | from Cython.Build import cythonize |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 424 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 425 | # optionally enable line tracing for test coverage support |
| 426 | linetrace = os.environ.get("CYTHON_TRACE") == "1" |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 427 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 428 | 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 Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 439 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 440 | _build_ext.finalize_options(self) |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 441 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 442 | 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 Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 449 | |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 450 | # 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 Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 462 | |
| 463 | cmdclass = {"release": release} |
| 464 | |
| 465 | if ext_modules: |
| 466 | cmdclass["build_ext"] = cython_build_ext |
| 467 | |
| 468 | |
| 469 | setup_params = dict( |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 470 | name="fonttools", |
Elliott Hughes | 8e084f2 | 2024-04-01 15:28:06 +0000 | [diff] [blame] | 471 | version="4.49.0", |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 472 | 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 Huang | 8b3c57b | 2018-07-03 17:43:11 -0700 | [diff] [blame] | 499 | ) |
Haibo Huang | d123eeb | 2020-04-03 12:18:18 -0700 | [diff] [blame] | 500 | |
| 501 | |
| 502 | if __name__ == "__main__": |
Elliott Hughes | 02cec46 | 2023-11-10 19:23:18 +0000 | [diff] [blame] | 503 | setup(**setup_params) |