diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index abb24631..1a65d35c 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -88,9 +88,11 @@ jobs: - name: Compile C-Extensions run: | sudo chmod a+rw /etc/udev/rules.d - python3 setup.py install - cp ./build/lib.linux-x86_64-${{ env.add_dir_str }}/DisplayCAL/lib64/python${{ env.py_version }}/RealDisplaySizeMM.cpython-${{ env.py_version }}-x86_64-linux-gnu.so ./DisplayCAL/lib64/python${{ env.py_version }}/ - + python3 -m build + pip install dist/DisplayCAL-*.whl + export PYPATH=`which python` + export PYDIR=`dirname $PYPATH` + cp $PYDIR/../lib/python${{ matrix.python-version }}/site-packages/DisplayCAL/lib64/python${{ env.py_version }}/RealDisplaySizeMM.*.so ./DisplayCAL/lib64/python${{ env.py_version }}/ - name: Test with pytest run: | python -m pytest --verbose --cov=. --cov-report html diff --git a/.gitignore b/.gitignore index 96d153b1..2abbce4b 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ __pycache__/ /DisplayCAL/lib64/python39/*.so /DisplayCAL/lib64/python310/*.so /DisplayCAL/lib64/RealDisplaySizeMM.cpython-310-darwin.so +/DisplayCAL/lib64/RealDisplaySizeMM.cpython-311-darwin.so +/DisplayCAL/lib64/RealDisplaySizeMM.cpython-312-darwin.so diff --git a/DisplayCAL/setup.py b/DisplayCAL/setup.py index 5fbe5c26..27425a18 100644 --- a/DisplayCAL/setup.py +++ b/DisplayCAL/setup.py @@ -64,6 +64,7 @@ def findall(dir=os.curdir): import distutils.filelist + distutils.filelist.findall = findall # Fix findall bug in distutils @@ -74,6 +75,7 @@ def findall(dir=os.curdir): description, longdesc, DOMAIN, + development_home_page, name, py_maxversion, py_minversion, @@ -199,7 +201,8 @@ def add_lib_excludes(key, excludebits): for exclude in ("32", "64"): for pycompat in ("38", "39", "310", "311"): if key == "win32" and ( - pycompat == str(sys.version_info[0]) + str(sys.version_info[1]) or exclude == excludebits[0] + pycompat == str(sys.version_info[0]) + str(sys.version_info[1]) + or exclude == excludebits[0] ): continue config["excludes"][key].extend( @@ -367,7 +370,7 @@ def create_app_symlinks(dist_dir, scripts): def get_data(tgt_dir, key, pkgname=None, subkey=None, excludes=None): - """Return configured data files""" + """Return configured data files.""" files = config[key] src_dir = source_dir if pkgname: @@ -381,12 +384,9 @@ def get_data(tgt_dir, key, pkgname=None, subkey=None, excludes=None): data = [] for pth in files: if not [exclude for exclude in excludes or [] if fnmatch(pth, exclude)]: - data.append( - ( - os.path.normpath(os.path.join(tgt_dir, os.path.dirname(pth))), - safe_glob(os.path.join(src_dir, pth)), - ) - ) + normalized_path = os.path.normpath(os.path.join(tgt_dir, os.path.dirname(pth))) + safe_path = [relpath(p, src_dir) for p in safe_glob(os.path.join(src_dir, pth))] + data.append((normalized_path, safe_path)) return data @@ -470,12 +470,12 @@ def setup(): if use_setuptools: if "--use-setuptools" in sys.argv[1:] and not os.path.exists("use-setuptools"): open("use-setuptools", "w").close() - try: - from ez_setup import use_setuptools as ez_use_setuptools - - ez_use_setuptools() - except ImportError: - pass + # try: + # from ez_setup import use_setuptools as ez_use_setuptools + # + # ez_use_setuptools() + # except ImportError: + # pass try: import setuptools from setuptools import setup, Extension, find_packages @@ -522,7 +522,10 @@ def findall( sys.argv = sys.argv[:i] + ["install"] + sys.argv[i + 1:] install.create_home_path = lambda self: None - if skip_instrument_conf_files := "--skip-instrument-configuration-files" in sys.argv[1:]: + if ( + skip_instrument_conf_files := "--skip-instrument-configuration-files" + in sys.argv[1:] + ): i = sys.argv.index("--skip-instrument-configuration-files") sys.argv = sys.argv[:i] + sys.argv[i + 1:] @@ -613,9 +616,11 @@ def findall( # on Mac OS X and Windows, we want data files in the package dir # (package_data will be ignored when using py2exe) package_data = { - name: config["package_data"][name] - if sys.platform in ("darwin", "win32") and not do_py2app and not do_py2exe - else [] + name: ( + config["package_data"][name] + if sys.platform in ("darwin", "win32") and not do_py2app and not do_py2exe + else [] + ) } if sdist and sys.platform in ("darwin", "win32"): package_data[name].extend( @@ -642,7 +647,33 @@ def findall( ) ) else: - data_files.append((doc, [os.path.join(pydir, "..", "LICENSE.txt")])) + data_files.append( + ( + doc, + [ + relpath( + os.path.join(pydir, "..", "LICENSE.txt"), + source_dir + ) + ] + ) + ) + + # metainfo / appdata.xml + data_files.append( + ( + os.path.join(os.path.dirname(data), "metainfo"), + [ + relpath( + os.path.normpath( + os.path.join(pydir, "..", "dist", f"{appstream_id}.appdata.xml") + ), + source_dir, + ) + ], + ) + ) + if sys.platform not in ("darwin", "win32") or do_py2app or do_py2exe: # Linux/Unix or py2app/py2exe data_files += get_data(data, "package_data", name, excludes=["theme/icons/*"]) @@ -692,12 +723,6 @@ def findall( print("WARNING: OpenAL32.dll not found!") elif sys.platform != "darwin": # Linux - data_files.append( - ( - os.path.join(os.path.dirname(data), "metainfo"), - [os.path.join(pydir, "..", "dist", appstream_id + ".appdata.xml")], - ) - ) data_files.append( ( os.path.join(os.path.dirname(data), "applications"), @@ -709,9 +734,11 @@ def findall( ) data_files.append( ( - autostart - if os.geteuid() == 0 or prefix.startswith("/") - else autostart_home, + ( + autostart + if os.geteuid() == 0 or prefix.startswith("/") + else autostart_home + ), [ os.path.join( pydir, @@ -911,7 +938,8 @@ def findall( from distutils.core import setup, Extension setup(ext_modules=[Extension("{name}.lib{bits}.RealDisplaySizeMM", sources={sources}, define_macros={macros}, extra_link_args={link_args})])""", - ] + sys.argv[1:], + ] + + sys.argv[1:], stdout=sp.PIPE, stderr=sp.STDOUT, ) @@ -956,12 +984,7 @@ def findall( if sdist: # For source distributions we want all libraries for pycompat in ("38", "39", "310", "311"): - packages.extend( - [ - f"{name}.lib{bits}", - f"{name}.lib{bits}.python{pycompat}" - ] - ) + packages.extend([f"{name}.lib{bits}", f"{name}.lib{bits}.python{pycompat}"]) elif sys.platform == "darwin": # On Mac OS X we only want the universal binaries packages.append(f"{name}.lib{bits}") @@ -995,7 +1018,7 @@ def findall( ], "data_files": data_files, "description": description, - "download_url": f"https://{DOMAIN}/download/{name}-{version}.tar.gz", + "download_url": f"{development_home_page}/releases/download/{version}/{name}-{version}.tar.gz", "ext_modules": ext_modules, "license": "GPL v3", "long_description": longdesc, @@ -1005,8 +1028,7 @@ def findall( "package_data": package_data, "package_dir": {name: name}, "platforms": [ - "Python >= %s <= %s" - % ( + "Python >= {} <= {}".format( ".".join(str(n) for n in py_minversion), ".".join(str(n) for n in py_maxversion), ), @@ -1024,13 +1046,14 @@ def findall( if setuptools: attrs["entry_points"] = { "gui_scripts": [ - "%s = %s.main:main%s" - % ( + "{} = {}.main:main{}".format( script, name, - "" - if script == name.lower() - else script[len(name):].lower().replace("-", "_"), + ( + "" + if script == name.lower() + else script[len(name):].lower().replace("-", "_") + ), ) for script, desc in scripts ] @@ -1271,7 +1294,7 @@ def copy_package_data(self, package, target_dir): "excludes": config["excludes"]["all"] + config["excludes"]["win32"], "bundle_files": 3 if wx.VERSION >= (2, 8, 10, 1) else 1, "compressed": 1, - "optimize": 0 # 0 = don’t optimize (generate .pyc) + "optimize": 0, # 0 = don’t optimize (generate .pyc) # 1 = normal optimization (like python -O) # 2 = extra optimization (like python -OO) } @@ -1545,8 +1568,7 @@ def copy_package_data(self, package, target_dir): for _datadir, datafiles in attrs.get("data_files", []): for datafile in datafiles: manifest_in.append( - "include " - + ( + "include {}".format( relpath(os.path.sep.join(datafile.split("/")), source_dir) or datafile ) @@ -1568,13 +1590,16 @@ def copy_package_data(self, package, target_dir): "include " + os.path.sep.join([pkgdir] + obj.split("/")) ) for pymod in attrs.get("py_modules", []): - manifest_in.append("include " + os.path.join(*pymod.split("."))) - manifest_in.append("include " + os.path.join(name, "theme", "theme-info.txt")) + manifest_in.append("include {}".format(os.path.join(*pymod.split(".")))) manifest_in.append( - "recursive-include %s %s %s" - % (os.path.join(name, "theme", "icons"), "*.icns", "*.ico") + "include {}".format(os.path.join(name, "theme", "theme-info.txt")) ) - manifest_in.append("include " + os.path.join("man", "*.1")) + manifest_in.append( + "recursive-include {} {} {}".format( + os.path.join(name, "theme", "icons"), "*.icns", "*.ico" + ) + ) + manifest_in.append("include {}".format(os.path.join("man", "*.1"))) manifest_in.append("recursive-include misc *") if skip_instrument_conf_files: manifest_in.extend( @@ -1584,9 +1609,9 @@ def copy_package_data(self, package, target_dir): "exclude misc/*.usermap", ] ) - manifest_in.append("include " + os.path.join("screenshots", "*.png")) - manifest_in.append("include " + os.path.join("scripts", "*")) - manifest_in.append("include " + os.path.join("tests", "*")) + manifest_in.append("include {}".format(os.path.join("screenshots", "*.png"))) + manifest_in.append("include {}".format(os.path.join("scripts", "*"))) + manifest_in.append("include {}".format(os.path.join("tests", "*"))) manifest_in.append("recursive-include theme *") manifest_in.append("recursive-include util *.cmd *.py *.sh") if sys.platform == "win32" and not setuptools: @@ -1609,7 +1634,7 @@ def copy_package_data(self, package, target_dir): pydir, "..", "dist", - "bbfreeze.%s-py%s" % (get_platform(), sys.version[:3]), + "bbfreeze.{}-py{}".format(get_platform(), sys.version[:3]), ) sys.argv.insert(i + 1, f"--dist-dir={dist_dir}") if "egg_info" not in sys.argv[1:i]: @@ -1686,6 +1711,7 @@ def copy_package_data(self, package, target_dir): def setup_do_py2exe(): import py2exe + # ModuleFinder can't handle runtime changes to __path__, but win32com # uses them try: diff --git a/setup.cfg b/setup.cfg index e062b14a..f9929b39 100644 --- a/setup.cfg +++ b/setup.cfg @@ -35,3 +35,6 @@ install_script = util/DisplayCAL_postinstall.py [install] record = INSTALLED_FILES + +[black] +line-length = 88 \ No newline at end of file diff --git a/setup.py b/setup.py index 0e3b7ab3..ca67f5e6 100755 --- a/setup.py +++ b/setup.py @@ -630,7 +630,7 @@ def setup(): replace_placeholders( Path(pydir, "misc", f"{tmpl_name}.template.html"), - Path(pydir, tmpl_name + ".html"), + Path(pydir, f"{tmpl_name}.html"), lastmod_time, {"STABILITY": "Beta" if stability != "stable" else ""}, ) @@ -688,9 +688,11 @@ def setup(): languages = "\n\t\t".join(languages) tmpl_name = appstream_id + ".appdata.xml" + misc_tmpl_name = Path(pydir, "misc", tmpl_name) + dist_tmpl_name = Path(pydir, "dist", tmpl_name) replace_placeholders( - Path(pydir, "misc", tmpl_name), - Path(pydir, "dist", tmpl_name), + misc_tmpl_name, + dist_tmpl_name, lastmod_time, { "APPDATAPROVIDES": provides, @@ -698,6 +700,7 @@ def setup(): "CHANGELOG": format_changelog(changelog, "appstream"), }, ) + if appdata: sys.argv.remove("appdata") diff --git a/tests/test_setup.py b/tests/test_setup.py new file mode 100644 index 00000000..3311ef66 --- /dev/null +++ b/tests/test_setup.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -+- +import os +import pytest + +from DisplayCAL.setup import get_data + + +@pytest.mark.parametrize( + "tgt_dir, key, pkgname, subkey, excludes", [ + ["DisplayCAL", "doc", None, None, ["LICENSE.txt"]] + ] +) +def test_get_data_returns_relative_paths( + tgt_dir, key, pkgname, subkey, excludes +): + """DisplayCAL.setup.get_data() returns relative paths.""" + result = get_data(tgt_dir, key, pkgname, subkey, excludes) + all_paths = [] + for r in result: + all_paths += r[1] + assert all([not os.path.isabs(path) for path in all_paths])