diff --git a/.github/workflows/deploy-wheels.yaml b/.github/workflows/pypi.yml similarity index 88% rename from .github/workflows/deploy-wheels.yaml rename to .github/workflows/pypi.yml index 7c86d18..17b6f34 100644 --- a/.github/workflows/deploy-wheels.yaml +++ b/.github/workflows/pypi.yml @@ -2,11 +2,6 @@ name: Build on: push: - branches: - - deploy-pypi-test - - deploy-pypi - # Release branches - #- "[0-9]+.[0-9]+.X" # Manual run workflow_dispatch: @@ -83,8 +78,7 @@ jobs: url: https://test.pypi.org/project/delphivcl permissions: id-token: write - # upload to PyPI test only for pushes to 'deploy-pypi-test' - if: github.event_name == 'push' && github.ref == 'refs/heads/deploy-pypi-test' + if: github.ref == 'refs/heads/main' steps: - uses: actions/download-artifact@v2 with: @@ -105,8 +99,7 @@ jobs: url: https://pypi.org/project/delphivcl/ permissions: id-token: write - # upload to PyPI only for pushes to 'deploy-pypi' - if: github.event_name == 'push' && github.ref == 'refs/heads/deploy-pypi' + if: startsWith(github.ref, 'refs/tags/v') steps: - uses: actions/download-artifact@v2 with: diff --git a/.github/workflows/sphinx-build.yaml b/.github/workflows/sphinx-build.yml similarity index 100% rename from .github/workflows/sphinx-build.yaml rename to .github/workflows/sphinx-build.yml diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yml similarity index 89% rename from .github/workflows/tests.yaml rename to .github/workflows/tests.yml index b44ae20..f42b658 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yml @@ -3,10 +3,7 @@ name: Tests on: push: branches: - - main - - test - # Release branches - #- "[0-9]+.[0-9]+.X" + - main # Manual run workflow_dispatch: diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..87cfd2a --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +recursive-include delphivcl *.pyd +recursive-include delphivcl docs.xml \ No newline at end of file diff --git a/build.py b/build.py new file mode 100644 index 0000000..3d3f1e2 --- /dev/null +++ b/build.py @@ -0,0 +1,133 @@ +import sys +import os +import sys +import shutil +import time +import platform +import distutils.dir_util +from wheel.bdist_wheel import bdist_wheel + + +''' +BDistWheel forces python and abi wheel tags for binary distributions +''' + + +class BDistWheel(bdist_wheel): + + def finalize_options(self): + bdist_wheel.finalize_options(self) + self.root_is_pure = ("--universal" in sys.argv) + + +''' +Sort out the platform library for binary distribution and add to the package directory. +Place all libraries onto the package directory for source distribution. +Place the XML doc file onto the package directory. +''' + + +class PackageDataBuilder(): + + def __init__(self): + self.pkg_dir = os.path.join(os.curdir, "delphivcl") + self.plat_name = None + for arg in sys.argv: + if arg.startswith("--plat-name=") and (len(arg.split("=")) == 2): + self.plat_name = arg.split("=")[1] + + ''' + Must run "python setup.py clean --all" between builds. + ''' + + def clean_up(self): + lib_dirs = [os.path.join(self.pkg_dir, "Win32"), + os.path.join(self.pkg_dir, "Win64")] + + for lib_dir in lib_dirs: + if os.path.isdir(lib_dir): + shutil.rmtree(lib_dir) + + # Wait until the OS remove all dirs + for lib_dir in lib_dirs: + for attempts in range(3): + if not os.path.isdir(lib_dir): + break + else: + time.sleep(1) + + ''' + Cross-compiling wheel. + This generates a wheel following the cross platform set on --plat-name. + See: https://docs.python.org/3/distutils/builtdist.html#cross-compiling-on-windows + ''' + + def __check_cross_compiling(self): + is_cross_compiling = False + lib_dir = None + + if self.plat_name: + is_cross_compiling = True + if self.plat_name == "win32": + lib_dir = "Win32" + elif self.plat_name == "win_amd64": + lib_dir = "Win64" + else: + is_cross_compiling = False + + return (is_cross_compiling, lib_dir) + + ''' + Copy the VCL extension module(s) to the package data folder. + Source distributions and Universal binary distributions will deliver + all library versions. The right one will be loaded by __init__.py. + Platform distributions will deliver only the library that matches the runner. + ''' + + def __pick_and_copy_libraries(self): + if ("sdist" in sys.argv) or (("bdist_wheel" in sys.argv) and ("--universal" in sys.argv)): + # sdist/bdist[--universal] deploy all extension modules + distutils.dir_util.copy_tree("lib", self.pkg_dir) + else: + # Deploys the current platform extension module only + is_cross_compiling, lib_dir = self.__check_cross_compiling() + if not is_cross_compiling: + plat_sys = platform.system() + if plat_sys == "Windows": + if (sys.maxsize > 2**32): + # Win x64 + lib_dir = "Win64" + else: + # Win x86 + lib_dir = "Win32" + + if lib_dir: + distutils.dir_util.copy_tree(os.path.join( + "lib", lib_dir), os.path.join(self.pkg_dir, lib_dir)) + else: + raise ValueError("Unsupported platform.") + + ''' + Copy the XML doc file to the package data folder. + The docs.xml file is the result of the compilation of all xml doc files. + ''' + + def __pick_and_copy_docs(self): + # Copy the doc files to the package folder into the doc subfolder + docs_file = os.path.join("docs", "xml", "docs.xml") + if os.path.exists(docs_file): + pkg_doc_dir = os.path.join(self.pkg_dir, "doc") + if not os.path.exists(pkg_doc_dir): + os.mkdir(pkg_doc_dir) + distutils.file_util.copy_file( + docs_file, os.path.join(pkg_doc_dir, "docs.xml")) + + def build_package_data(self): + self.__pick_and_copy_libraries() + self.__pick_and_copy_docs() + + +def setup(): + builder = PackageDataBuilder() + builder.clean_up() + builder.build_package_data() diff --git a/delphivcl/__init__.py b/delphivcl/__init__.py index 7be473c..6bd558a 100644 --- a/delphivcl/__init__.py +++ b/delphivcl/__init__.py @@ -1,47 +1,58 @@ -import sys, os, sys, platform -from os import environ -import importlib, importlib.machinery, importlib.util +import sys +import os +import sys +import platform +import importlib +import importlib.machinery +import importlib.util -class PyVerNotSupported(Exception): - pass -def findmodule(): - pyver = f"{sys.version_info.major}.{sys.version_info.minor}" - ossys = platform.system() - libdir = None +def find_extension_module(): + py_ver = f"{sys.version_info.major}.{sys.version_info.minor}" + plat_sys = platform.system() + lib_dir = None - if not (pyver in ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]): - raise PyVerNotSupported(f"DelphiVCL doesn't support Python{pyver}.") + if not (py_ver in ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]): + raise ValueError(f"DelphiVCL doesn't support Python{py_ver}.") - if ossys == "Windows": - if (sys.maxsize > 2**32): - #Win x64 - libdir = "Win64" + if plat_sys == "Windows": + if (sys.maxsize > 2**32): + # Win x64 + lib_dir = "Win64" + else: + # Win x86 + lib_dir = "Win32" + + if lib_dir: + lib_dir = os.path.join(os.path.dirname( + os.path.abspath(__file__)), lib_dir) + if not os.path.exists(lib_dir): + raise ValueError( + "DelphiVCL module not found. \ + Try to reinstall the delphivcl package or check for support compatibility.") + + for file_name in os.listdir(lib_dir): + if 'DelphiVCL' in file_name: + return os.path.join(lib_dir, os.path.basename(file_name)) + raise ValueError( + "DelphiVCL module not found. Try to reinstall the delphivcl package.") else: - #Win x86 - libdir = "Win32" - - if libdir: - sdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), libdir) - if not os.path.exists(sdir): - raise ValueError("DelphiVCL module not found. Try to reinstall the delphivcl package or check for support compatibility.") - for fname in os.listdir(sdir): - if 'DelphiVCL' in fname: - return os.path.join(sdir, os.path.basename(fname)) - raise ValueError("DelphiVCL module not found. Try to reinstall the delphivcl package.") - else: - raise ValueError("Unsupported platform.") + raise ValueError("Unsupported platform.") + def new_import(): - modulefullpath = findmodule() - loader = importlib.machinery.ExtensionFileLoader("DelphiVCL", modulefullpath) - spec = importlib.util.spec_from_file_location("DelphiVCL", modulefullpath, - loader=loader, submodule_search_locations=None) - ld = loader.create_module(spec) + lib_path = find_extension_module() + loader = importlib.machinery.ExtensionFileLoader("DelphiVCL", lib_path) + spec = importlib.util.spec_from_file_location("DelphiVCL", + lib_path, + loader=loader, + submodule_search_locations=None) + loader.create_module(spec) package = importlib.util.module_from_spec(spec) sys.modules["delphivcl"] = package spec.loader.exec_module(package) return package -#Import the shared lib -package = new_import() \ No newline at end of file + +# Import the extension module +package = new_import() diff --git a/delphivcl/__version__.py b/delphivcl/__version__.py deleted file mode 100644 index 87a7cf5..0000000 --- a/delphivcl/__version__.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "1.0.4" \ No newline at end of file diff --git a/experts/README.md b/experts/README.md deleted file mode 100644 index 912f79a..0000000 --- a/experts/README.md +++ /dev/null @@ -1,3 +0,0 @@ -We have ported the experts to a new repository. Please, have a visit to the link below: - -https://github.com/Embarcadero/Delphi4PythonExporter \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 00e3138..d1cf2ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,27 +1,14 @@ [build-system] -requires = ["setuptools>=40.9.0", "wheel"] - -[tool.cibuildwheel] -build = ["cp36-win*", "cp37-win*", "cp38-win*", "cp39-win*", "cp310-win*"] -skip = "pp*" -#archs = ["auto"] -#repair-wheel-command = "" - -[tool.cibuildwheel.windows] -archs = ["x86", "AMD64"] - -[tool.isort] -profile = "black" -multi_line_output = 3 - -[tool.poetry] -name = "delphivcl" -version = "0.1.18" -description = "" -authors = ["Jim McKeth", "Lucas Belo", "Lucio Montero"] - -[tool.poetry.dependencies] -python = ">=3.6<=3.10" - -[tool.poetry.dev-dependencies] -pytest = "^6.2.5" +requires = [ + "setuptools >= 54", + "setuptools_scm[toml] >= 4, <6", + "setuptools_scm_git_archive", + "wheel >= 0.29.0", +] +build-backend = 'setuptools.build_meta' + +[tool.setuptools_scm] +version_scheme = "post-release" +local_scheme = "no-local-version" +write_to = "delphivcl/__version__.py" +git_describe_command = "git describe --dirty --tags --long --match v* --first-parent" \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..baf740e --- /dev/null +++ b/setup.cfg @@ -0,0 +1,54 @@ +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + +[bdist_wheel] +universal = 0 + +[build_sphinx] +source-dir = docs/source +build-dir = _build +all-files = True + +[metadata] +name = delphivcl +version = 1.0.5 +description = Delphi VCL for Python +long_description = file: README.md +long_description_content_type = text/markdown; charset=UTF-8 +url = https://github.com/Embarcadero/DelphiVCL4Python +author = Lucas Belo, Jim McKeeth +author_email = lucas.belo@live.com +license = BSD +license_files = ['LICENSE.md'] +classifiers = + Intended Audience :: Developers + Topic :: Software Development + License :: Other/Proprietary License + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3 :: Only + Operating System :: Microsoft :: Windows +project_urls = + Documentation = https://embarcadero.github.io/DelphiVCL4Python + Source = https://github.com/Embarcadero/DelphiVCL4Python + Tracker = https://github.com/Embarcadero/DelphiVCL4Python/issues + +[options] +zip_safe = False +packages = find: +platforms = any +include_package_data = True +install_requires = +python_requires = >=3 +setup_requires = + setuptools_scm +cmdclass = + bdist_wheel = build.BDistWheel \ No newline at end of file diff --git a/setup.py b/setup.py index 1bd5d78..578f955 100644 --- a/setup.py +++ b/setup.py @@ -1,105 +1,10 @@ -import setuptools, os, sys, platform, distutils.dir_util -from pathlib import Path +import setuptools +import build -pkgname = "delphivcl" -#Force platform wheel -try: - from wheel.bdist_wheel import bdist_wheel as _bdist_wheel - class bdist_wheel(_bdist_wheel): - def finalize_options(self): - _bdist_wheel.finalize_options(self) - self.root_is_pure = ("--universal" in sys.argv) -except ImportError: - bdist_wheel = None +def main(): + build.setup() + setuptools.setup() -def get_release_version(): - lcals = locals() - gbals = globals() - with open(os.path.join(os.getcwd(), pkgname, "__version__.py"), "rt") as opf: - opffilecontents = opf.read() - retvalue = exec(opffilecontents, gbals, lcals) - versorigstr = lcals["__version__"] - return versorigstr - -pkg_dir = os.path.join(os.curdir, pkgname) -if ("sdist" in sys.argv) or (("bdist_wheel" in sys.argv) and ("--universal" in sys.argv)): - #sdist deploys all shared libraries - distutils.dir_util.copy_tree("lib", pkg_dir) -else: - #Deploy the current platform shared library only - ossys = platform.system() - platmac = platform.machine() - libdir = None - if ossys == "Windows": - if (sys.maxsize > 2**32): - #Win x64 - libdir = "Win64" - else: - #Win x86 - libdir = "Win32" - - if libdir: - distutils.dir_util.copy_tree(os.path.join("lib", libdir), os.path.join(pkg_dir, libdir)) - else: - raise ValueError("Unsupported platform.") - -#Copy the doc files to the package folder into the doc subfolder -if os.path.exists(os.path.join("docs", "xml", "docs.xml")): - pkg_doc_dir = os.path.join(pkg_dir, "doc") - if not os.path.exists(pkg_doc_dir): - os.mkdir(pkg_doc_dir) - distutils.file_util.copy_file(os.path.join("docs", "xml", "docs.xml"), os.path.join(pkg_doc_dir, "docs.xml")) - -#Create the package data. -pkgdata = [] -for dir_, _, files in os.walk(pkg_dir): - for file_name in files: - rel_dir = os.path.relpath(dir_, pkg_dir) - rel_file = os.path.join(rel_dir, file_name) - #Add the shared library. - if ''.join(Path(rel_file).suffixes) in ['.pyd', '.tds']: - pkgdata.append(rel_file) - #Add the doc xml file - elif (rel_file.endswith('.xml')): - pkgdata.append(rel_file) - -#Read the current version from __version.py__ -versnewstr = get_release_version() - -with open("README.md", "r") as fh: - long_description = fh.read() - -setuptools.setup( - name=pkgname, - version=versnewstr, - description="Delphi VCL for Python", - author="Lucas Belo, Jim McKeeth", - author_email="lucas.belo@live.com", - long_description=long_description, - long_description_content_type="text/markdown", - license="Other/Proprietary License", - license_files=["LICENSE.md"], - url="https://github.com/Embarcadero/DelphiVCL4Python", - python_requires=">=3.6", - packages=[pkgname], - package_data={pkgname: pkgdata}, - classifiers=[ - 'Intended Audience :: Developers', - 'Topic :: Software Development', - 'License :: Other/Proprietary License', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3 :: Only', - 'Operating System :: Microsoft :: Windows', - ], - cmdclass={ - 'bdist_wheel': bdist_wheel - } -) +if __name__ == "__main__": + main() diff --git a/tests/___init__.py b/tests/___init__.py deleted file mode 100644 index 521ad4f..0000000 --- a/tests/___init__.py +++ /dev/null @@ -1,6 +0,0 @@ -import importlib.machinery, importlib.util -def new_import(ext_file): - loader = importlib.machinery.ExtensionFileLoader("DelphiVCL", ext_file) - spec = importlib.util.spec_from_file_location("DelphiVCL", ext_file, - loader=loader, submodule_search_locations=None) - #print("spec", spec, spec.loader, modulefullpath, __file__) diff --git a/tests/__main__.py b/tests/__main__.py deleted file mode 100644 index 4077dbf..0000000 --- a/tests/__main__.py +++ /dev/null @@ -1 +0,0 @@ -from delphivcl import * \ No newline at end of file diff --git a/tests/test_import.py b/tests/test_import.py deleted file mode 100644 index 57ba20d..0000000 --- a/tests/test_import.py +++ /dev/null @@ -1,24 +0,0 @@ -import importlib.machinery, importlib.util -import sys - -#from ..delphivcl import * -#from . import new_import -def new_import(ext_file=None): - if ext_file is None: - ext_file = r"C:\Users\lucio\anaconda3\envs\DelphiVCL_assessment\lib\site-packages\delphivcl\DelphiVCL.pyd" - loader = importlib.machinery.ExtensionFileLoader("DelphiVCL", ext_file) - spec = importlib.util.spec_from_file_location("DelphiVCL", ext_file, - loader=loader, submodule_search_locations=None) - #ld = loader.create_module(spec) - package = importlib.util.module_from_spec(spec) - assert "delphivcl" in sys.modules, sys.modules.keys() - return - return package - return ld - -def test_import(): - ld = new_import(r"C:\Users\lucio\PycharmProjects\DelphiVCL_assessment\DelphiVCL4Python\lib\DelphiVCL_Win64_38\DelphiVCL.pyd") - assert 0, ld - -if __name__ == "__main__": - test_import() \ No newline at end of file