242 lines
8.5 KiB
Python
242 lines
8.5 KiB
Python
# Copyright 2015 Google Inc. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
|
|
from setuptools import setup, find_packages, Extension
|
|
from setuptools.command.build_ext import build_ext as _build_ext
|
|
from setuptools.command.sdist import sdist as _sdist
|
|
import pkg_resources
|
|
from distutils import log
|
|
import sys
|
|
import os
|
|
import re
|
|
from io import open
|
|
|
|
|
|
needs_pytest = {'pytest', 'test'}.intersection(sys.argv)
|
|
pytest_runner = ['pytest_runner'] if needs_pytest else []
|
|
needs_wheel = {'bdist_wheel'}.intersection(sys.argv)
|
|
wheel = ['wheel'] if needs_wheel else []
|
|
|
|
# Check if minimum required Cython is available.
|
|
# For consistency, we require the same as our vendored Cython.Shadow module
|
|
cymod = "Lib/cu2qu/cython.py"
|
|
cython_version_re = re.compile('__version__ = ["\']([0-9][0-9\w\.]+)["\']')
|
|
with open(cymod, "r", encoding="utf-8") as fp:
|
|
for line in fp:
|
|
m = cython_version_re.match(line)
|
|
if m:
|
|
cython_min_version = m.group(1)
|
|
break
|
|
else:
|
|
sys.exit("error: failed to parse cython version in '%s'" % cymod)
|
|
|
|
required_cython = "cython >= %s" % cython_min_version
|
|
try:
|
|
pkg_resources.require(required_cython)
|
|
except pkg_resources.ResolutionError:
|
|
has_cython = False
|
|
else:
|
|
has_cython = True
|
|
|
|
# First, check if the CU2QU_WITH_CYTHON environment variable is set.
|
|
# Values "1", "true" or "yes" mean that Cython is required and will be used
|
|
# to regenerate the *.c sources from which the native extension is built;
|
|
# "0", "false" or "no" mean that Cython is not required and no extension
|
|
# module will be compiled (i.e. the wheel is pure-python and universal).
|
|
# If the variable is not set, then the pre-generated *.c sources that
|
|
# are included in the sdist package will be used to try build the extension.
|
|
# However, if any error occurs during compilation (e.g. the host
|
|
# machine doesn't have the required compiler toolchain installed), the
|
|
# installation proceeds without the compiled extensions, but will only have
|
|
# the pure-python module.
|
|
env_with_cython = os.environ.get("CU2QU_WITH_CYTHON")
|
|
with_cython = (
|
|
True if env_with_cython in {"1", "true", "yes"}
|
|
else False if env_with_cython in {"0", "false", "no"}
|
|
else None
|
|
)
|
|
|
|
# command line options --with-cython and --without-cython are also supported.
|
|
# They override the environment variable
|
|
opt_with_cython = {'--with-cython'}.intersection(sys.argv)
|
|
opt_without_cython = {'--without-cython'}.intersection(sys.argv)
|
|
if opt_with_cython and opt_without_cython:
|
|
sys.exit(
|
|
"error: the options '--with-cython' and '--without-cython' are "
|
|
"mutually exclusive"
|
|
)
|
|
elif opt_with_cython:
|
|
sys.argv.remove("--with-cython")
|
|
with_cython = True
|
|
elif opt_without_cython:
|
|
sys.argv.remove("--without-cython")
|
|
with_cython = False
|
|
|
|
|
|
class cython_build_ext(_build_ext):
|
|
"""Compile *.pyx source files to *.c using cythonize if Cython is
|
|
installed, else use the pre-generated *.c sources.
|
|
"""
|
|
|
|
def finalize_options(self):
|
|
if with_cython:
|
|
if not has_cython:
|
|
from distutils.errors import DistutilsSetupError
|
|
|
|
raise DistutilsSetupError(
|
|
"%s is required when using --with-cython" % required_cython
|
|
)
|
|
|
|
from Cython.Build import cythonize
|
|
|
|
# optionally enable line tracing for test coverage support
|
|
linetrace = os.environ.get("CYTHON_TRACE") == "1"
|
|
|
|
self.distribution.ext_modules[:] = cythonize(
|
|
self.distribution.ext_modules,
|
|
force=linetrace or self.force,
|
|
annotate=os.environ.get("CYTHON_ANNOTATE") == "1",
|
|
quiet=not self.verbose,
|
|
compiler_directives={
|
|
"linetrace": linetrace,
|
|
"language_level": 3,
|
|
"embedsignature": True,
|
|
},
|
|
)
|
|
else:
|
|
# replace *.py/.pyx sources with their pre-generated *.c versions
|
|
for ext in self.distribution.ext_modules:
|
|
ext.sources = [re.sub("\.pyx?$", ".c", n) for n in ext.sources]
|
|
|
|
_build_ext.finalize_options(self)
|
|
|
|
def build_extensions(self):
|
|
if not has_cython:
|
|
log.info(
|
|
"%s is not installed. Pre-generated *.c sources will be "
|
|
"will be used to build the extensions." % required_cython
|
|
)
|
|
|
|
try:
|
|
_build_ext.build_extensions(self)
|
|
except Exception as e:
|
|
if with_cython:
|
|
raise
|
|
from distutils.errors import DistutilsModuleError
|
|
|
|
# optional compilation failed: we delete 'ext_modules' and make sure
|
|
# the generated wheel is 'pure'
|
|
del self.distribution.ext_modules[:]
|
|
try:
|
|
bdist_wheel = self.get_finalized_command("bdist_wheel")
|
|
except DistutilsModuleError:
|
|
# 'bdist_wheel' command not available as wheel is not installed
|
|
pass
|
|
else:
|
|
bdist_wheel.root_is_pure = True
|
|
log.error('error: building extensions failed: %s' % e)
|
|
|
|
def get_source_files(self):
|
|
filenames = _build_ext.get_source_files(self)
|
|
|
|
# include pre-generated *.c sources inside sdist, but only if cython is
|
|
# installed (and hence they will be updated upon making the sdist)
|
|
if has_cython:
|
|
for ext in self.extensions:
|
|
filenames.extend(
|
|
[re.sub("\.pyx?$", ".c", n) for n in ext.sources]
|
|
)
|
|
return filenames
|
|
|
|
|
|
class cython_sdist(_sdist):
|
|
""" Run 'cythonize' on *.pyx sources to ensure the *.c files included
|
|
in the source distribution are up-to-date.
|
|
"""
|
|
|
|
def run(self):
|
|
if with_cython and not has_cython:
|
|
from distutils.errors import DistutilsSetupError
|
|
|
|
raise DistutilsSetupError(
|
|
"%s is required when creating sdist --with-cython"
|
|
% required_cython
|
|
)
|
|
|
|
if has_cython:
|
|
from Cython.Build import cythonize
|
|
|
|
cythonize(
|
|
self.distribution.ext_modules,
|
|
force=True, # always regenerate *.c sources
|
|
quiet=not self.verbose,
|
|
compiler_directives={
|
|
"language_level": 3,
|
|
"embedsignature": True
|
|
},
|
|
)
|
|
|
|
_sdist.run(self)
|
|
|
|
|
|
# don't build extensions if user explicitly requested --without-cython
|
|
if with_cython is False:
|
|
extensions = []
|
|
else:
|
|
extensions = [
|
|
Extension("cu2qu.cu2qu", ["Lib/cu2qu/cu2qu.py"]),
|
|
]
|
|
|
|
with open('README.rst', 'r') as f:
|
|
long_description = f.read()
|
|
|
|
setup(
|
|
name='cu2qu',
|
|
use_scm_version={"write_to": "Lib/cu2qu/_version.py"},
|
|
description='Cubic-to-quadratic bezier curve conversion',
|
|
author="James Godfrey-Kittle, Behdad Esfahbod",
|
|
author_email="jamesgk@google.com",
|
|
url="https://github.com/googlefonts",
|
|
license="Apache License, Version 2.0",
|
|
long_description=long_description,
|
|
packages=find_packages('Lib'),
|
|
package_dir={'': 'Lib'},
|
|
ext_modules=extensions,
|
|
include_package_data=True,
|
|
setup_requires=pytest_runner + wheel + ["setuptools_scm"],
|
|
tests_require=[
|
|
'pytest>=2.8',
|
|
],
|
|
install_requires=[
|
|
"fonttools[ufo] >= 3.32.0",
|
|
],
|
|
extras_require={"cli": ["defcon >= 0.6.0"]},
|
|
entry_points={"console_scripts": ["cu2qu = cu2qu.cli:main [cli]"]},
|
|
classifiers=[
|
|
'Development Status :: 4 - Beta',
|
|
'Intended Audience :: Developers',
|
|
'License :: OSI Approved :: Apache Software License',
|
|
'Operating System :: OS Independent',
|
|
'Programming Language :: Python',
|
|
'Programming Language :: Python :: 2',
|
|
'Programming Language :: Python :: 3',
|
|
'Topic :: Scientific/Engineering :: Mathematics',
|
|
'Topic :: Multimedia :: Graphics :: Graphics Conversion',
|
|
'Topic :: Multimedia :: Graphics :: Editors :: Vector-Based',
|
|
'Topic :: Software Development :: Libraries :: Python Modules',
|
|
],
|
|
cmdclass={"build_ext": cython_build_ext, "sdist": cython_sdist},
|
|
)
|