davemds pushed a commit to branch python-efl-1.25. http://git.enlightenment.org/bindings/python/python-efl.git/commit/?id=a379365ae2b957a76b7acd8246b9843085fdc1fe
commit a379365ae2b957a76b7acd8246b9843085fdc1fe Author: Dave Andreoli <d...@gurumeditation.it> Date: Sun Dec 5 16:55:33 2021 +0100 Switch to setuptools usage, instead of distutil and many other setup improvments, this is a squashed commit from many better and smaller commits on master --- MANIFEST.in | 2 +- Makefile | 19 +- efl/__init__.py | 8 +- pyproject.toml | 3 + setup.py | 717 ++++++++++++++++++++++++++------------------------------ 5 files changed, 358 insertions(+), 391 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index cc5684a..a6c3879 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include README INSTALL COPYING COPYING.LESSER AUTHORS ChangeLog +include README.md INSTALL COPYING COPYING.LESSER AUTHORS ChangeLog recursive-include efl *.c *.h *.pyx *.pxi *.pxd graft include graft tests diff --git a/Makefile b/Makefile index e155895..9d0a7d9 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,11 @@ install: $(PY) setup.py install +.PHONY: uninstall +uninstall: + $(PY) setup.py uninstall + + .PHONY: doc doc: $(PY) setup.py build build_doc @@ -47,9 +52,17 @@ clean: .PHONY: maintainer-clean maintainer-clean: $(PY) setup.py clean --all clean_generated_files + rm -rf build/ + rm -rf dist/ + rm -rf python_efl.egg-info/ + rm -f installed_files-*.txt + .PHONY: dist dist: - $(PY) setup.py sdist --formats=gztar,bztar - - + $(PY) setup.py sdist --formats=gztar,xztar + $(PY) setup.py bdist_wheel + @cd dist/; for f in `ls *.tar.*` ; do \ + echo Generating sha256 for: $$f ; \ + sha256sum $$f > $$f.sha256; \ + done diff --git a/efl/__init__.py b/efl/__init__.py index d2a7a7d..f74e08a 100644 --- a/efl/__init__.py +++ b/efl/__init__.py @@ -16,11 +16,11 @@ # along with this Python-EFL. If not, see <http://www.gnu.org/licenses/>. # semver examples: -# development: "1.12.99" ( 1, 12, 99 ) -# pre-release: "1.13.0-beta1" ( 1, 13, 0 ) -# release: "1.13.0" ( 1, 13, 0 ) +# development: '1.12.99' ( 1, 12, 99 ) +# pre-release: '1.13.0-beta1' ( 1, 13, 0 ) +# release: '1.13.0' ( 1, 13, 0 ) -__version__ = "1.25.0" +__version__ = '1.25.0' __version_info__ = (1, 25, 0) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..7a8d063 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ['setuptools', 'wheel'] +build-backend = 'setuptools.build_meta' \ No newline at end of file diff --git a/setup.py b/setup.py index 56c08e8..a5f8a50 100755 --- a/setup.py +++ b/setup.py @@ -3,261 +3,156 @@ import os import sys +import time import platform import subprocess -from distutils.core import setup, Command -from distutils.extension import Extension -from distutils.command.build_ext import build_ext -from distutils.version import StrictVersion, LooseVersion -from efl import __version__, __version_info__ as vers +import unittest +from distutils.version import LooseVersion +from setuptools import setup, Extension, Command script_path = os.path.dirname(os.path.abspath(__file__)) -# python-efl version (change in efl/__init__.py) -RELEASE = __version__ -VERSION = "%d.%d" % (vers[0], vers[1] if vers[2] < 99 else vers[1] + 1) - # dependencies -CYTHON_MIN_VERSION = "0.23.5" +EFL_MIN_VER = '1.25.1' +CYTHON_MIN_VERSION = '0.23.5' CYTHON_BLACKLIST = () -EFL_MIN_VER = RELEASE -ELM_MIN_VER = RELEASE - -# Add git commit count for dev builds -if vers[2] == 99: - try: - call = subprocess.Popen(["git", "rev-list", "--count", "HEAD"], - stdout=subprocess.PIPE) - out, err = call.communicate() - count = out.decode("utf-8").strip() - RELEASE += "a" + count - except Exception: - RELEASE += "a0" -# XXX: Force default visibility. See phab T504 -if os.getenv("CFLAGS") is not None and "-fvisibility=" in os.environ["CFLAGS"]: - os.environ["CFLAGS"] += " -fvisibility=default" +# basic utils +def read_file(rel_path): + with open(os.path.join(script_path, rel_path)) as fp: + return fp.read() + +def cmd_output(cmd): + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p.wait() + if p.returncode != 0: + print('WARNING: An error occurred while running "%s" (code %s)' % (cmd, p.returncode)) + stderr_content = p.stderr.read().decode('utf-8').strip() + if stderr_content: + print(stderr_content) + return '' + return p.stdout.read().decode('utf-8').strip() + +def get_version(rel_path): + for line in read_file(rel_path).splitlines(): + if line.startswith('__version__'): + return line.split("'")[1] + raise SystemExit('Unable to find version string.') + + +# python-efl version from sources +RELEASE = get_version('efl/__init__.py') + +# add git commit count for dev builds +if RELEASE.split('.')[2] == '99': + count = cmd_output('git rev-list --count HEAD') or '0' + RELEASE += 'a' + count +sys.stdout.write('Python-EFL: %s\n' % RELEASE) + + +# === check python version === +sys.stdout.write('Checking for Python: ') +py_ver = sys.version_info +py_ver = '%s.%s.%s' % (py_ver[0], py_ver[1], py_ver[2]) +if sys.hexversion < 0x020700f0: + raise SystemExit('too old. Found: %s Need at least 2.7.0' % py_ver) +sys.stdout.write('OK, found %s\n' % py_ver) +if sys.version_info.major == 2: + print( + '\n' + 'WARNING: Python 2 support is deprecated and will be removed soon.\n' + ' You should really upgrade to python 3, NOW !\n' + ' ...you have been warned, continue at your own risk.\n' + ) + time.sleep(5) # you really need to read the above message :P -# === Sphinx === -try: - from sphinx.setup_command import BuildDoc -except ImportError: - class BuildDoc(Command): - description = "build docs using sphinx, that must be installed." - version = "" - release = "" - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - print("Error: sphinx not found") +# === use cython or pre-generated C files === +USE_CYTHON = False +if os.getenv('DISABLE_CYTHON') is not None: + if os.path.exists(os.path.join(script_path, 'efl/eo/efl.eo.c')): + USE_CYTHON = False + else: + sys.exit( + 'You have requested to use pregenerated files with DISABLE_CYTHON\n' + 'but the files are not available!\n' + 'Unset DISABLE_CYTHON from your build environment and try again.' + ) +elif os.getenv('ENABLE_CYTHON') is not None: + USE_CYTHON = True +elif not os.path.exists(os.path.join(script_path, 'efl/eo/efl.eo.c')): + USE_CYTHON = True +elif os.path.exists(os.path.join(script_path, 'Makefile')): + USE_CYTHON = True -# === pkg-config === +# === pkg-config helper === def pkg_config(name, require, min_vers=None): try: - sys.stdout.write("Checking for " + name + ": ") + sys.stdout.write('Checking for %s: ' % name) - call = subprocess.Popen(["pkg-config", "--modversion", require], - stdout=subprocess.PIPE) - out, err = call.communicate() - if call.returncode != 0: - raise SystemExit("Did not find " + name + " with 'pkg-config'.") + ver = cmd_output('pkg-config --modversion %s' % require) + if not ver: + raise SystemExit('Cannot find %s with pkg-config.' % name) - ver = out.decode("utf-8").strip() if min_vers is not None: - assert (LooseVersion(ver) >= LooseVersion(min_vers)) is True - - call = subprocess.Popen(["pkg-config", "--cflags", require], - stdout=subprocess.PIPE) - out, err = call.communicate() - cflags = out.decode("utf-8").split() - - call = subprocess.Popen(["pkg-config", "--libs", require], - stdout=subprocess.PIPE) - out, err = call.communicate() - libs = out.decode("utf-8").split() - - sys.stdout.write("OK, found " + ver + "\n") - - cflags = list(set(cflags)) + assert LooseVersion(ver) >= LooseVersion(min_vers) + sys.stdout.write('OK, found %s\n' % ver) + cflags = cmd_output('pkg-config --cflags %s' % require).split() + libs = cmd_output('pkg-config --libs %s' % require).split() return (cflags, libs) except (OSError, subprocess.CalledProcessError): - raise SystemExit("Did not find " + name + " with 'pkg-config'.") - except (AssertionError): - raise SystemExit("%s version mismatch. Found: %s Needed %s" % ( - name, ver, min_vers)) - - -# === setup.py clean_generated_files command === -class CleanGenerated(Command): - description = "Clean C and html files generated by Cython" - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - for lib in ("eo", "evas", "ecore", "ecore_x", "ecore_input", "ecore_con", - "edje", "emotion", "elementary", "ethumb", "dbus_mainloop", - "utils"): - lib_path = os.path.join(script_path, "efl", lib) - for root, dirs, files in os.walk(lib_path): - for f in files: - if f.endswith((".c", ".html")) and f != "e_dbus.c": - self.remove(os.path.join(root, f)) - - def remove(self, fullpath): - print("removing %s" % fullpath.replace(script_path, "").lstrip('/')) - os.remove(fullpath) - - -# === setup.py uninstall command === -RECORD_FILE = "installed_files-%d.%d.txt" % sys.version_info[:2] -class Uninstall(Command): - description = 'remove all the installed files recorded at installation time' - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def remove_entry(self, entry): - if os.path.isfile(entry): - try: - print("removing file %s" % entry) - os.unlink(entry) - except OSError as e: - print(e) - return - - directory = os.path.dirname(entry) - while os.listdir(directory) == []: - try: - print("removing empty directory %s" % directory) - os.rmdir(directory) - except OSError as e: - print(e) - break - directory = os.path.dirname(directory) - - def run(self): - if not os.path.exists(RECORD_FILE): - print('ERROR: No %s file found!' % RECORD_FILE) - else: - for entry in open(RECORD_FILE).read().split(): - self.remove_entry(entry) - - -# === setup.py test command === -class Test(Command): - description = 'Run all the available unit tests using efl in build/' - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - import unittest - - sys.path.insert(0, "build/lib.%s-%s-%d.%d" % ( - platform.system().lower(), platform.machine(), - sys.version_info[0], sys.version_info[1])) - if "efl" in sys.modules: - del sys.modules["efl"] - - loader = unittest.TestLoader() - suite = loader.discover('./tests') - runner = unittest.TextTestRunner(verbosity=1, buffer=True) - result = runner.run(suite) - - -# === use cython or pre-generated C files === -USE_CYTHON = False -if os.getenv("DISABLE_CYTHON") is not None: - if os.path.exists(os.path.join(script_path, "efl/eo/efl.eo.c")): - USE_CYTHON = False - else: - sys.exit( - "You have requested to use pregenerated files with DISABLE_CYTHON\n" - "but the files are not available!\n" - "Unset DISABLE_CYTHON from your build environment and try again.") -elif os.getenv("ENABLE_CYTHON") is not None: - USE_CYTHON = True -elif not os.path.exists(os.path.join(script_path, "efl/eo/efl.eo.c")): - USE_CYTHON = True -elif os.path.exists(os.path.join(script_path, "Makefile")): - USE_CYTHON = True + raise SystemExit('Did not find %s with pkg-config.' % name) + except AssertionError: + raise SystemExit('%s version mismatch. Found: %s Needed %s' % (name, ver, min_vers)) ext_modules = [] py_modules = [] -packages = ["efl"] +packages = ['efl'] common_cflags = [ - "-fno-var-tracking-assignments", # seems to lower the mem used during build - "-Wno-misleading-indentation", # not needed (we don't indent the C code) - "-Wno-deprecated-declarations", # we bind deprecated functions - "-Wno-unused-variable", # eo_instance_from_object() is unused - "-Wno-format-security", # some cc don't like the way cython use EINA_LOG macros - # "-Werror", "-Wfatal-errors" # use this to stop build on first warnings + '-fno-var-tracking-assignments', # seems to lower the mem used during build + '-Wno-misleading-indentation', # not needed (we don't indent the C code) + '-Wno-deprecated-declarations', # we bind deprecated functions + '-Wno-unused-variable', # eo_instance_from_object() is unused + '-Wno-format-security', # some cc don't like the way cython use EINA_LOG macros + # '-Werror', '-Wfatal-errors' # use this to stop build on first warnings ] # remove clang unknown flags -if os.getenv("CC") == "clang": +if os.getenv('CC') == 'clang': common_cflags.remove('-fno-var-tracking-assignments') +# force default visibility. See phab T504 +if os.getenv('CFLAGS') is not None and '-fvisibility=' in os.environ['CFLAGS']: + os.environ['CFLAGS'] += ' -fvisibility=default' -if set(("build", "build_ext", "install", "bdist", "sdist")) & set(sys.argv): - sys.stdout.write("Python-EFL: %s\n" % RELEASE) - - # === Python === - sys.stdout.write("Checking for Python: ") - py_ver = sys.version_info - py_ver = "%s.%s.%s" % (py_ver[0], py_ver[1], py_ver[2]) - if sys.hexversion < 0x020600f0: - raise SystemExit("too old. Found: %s Need at least 2.6.0" % py_ver) - else: - sys.stdout.write("OK, found %s\n" % py_ver) - # === Cython === - sys.stdout.write("Checking for Cython: ") +if set(('build', 'build_ext', 'install', 'bdist', 'bdist_wheel', 'sdist')) & set(sys.argv): + # === check cython version === + sys.stdout.write('Checking for Cython: ') if USE_CYTHON: # check if cython is installed try: - from Cython.Distutils import Extension, build_ext - from Cython.Build import cythonize + import Cython import Cython.Compiler.Options except ImportError: - raise SystemExit("not found! Needed >= %s" % (CYTHON_MIN_VERSION)) + raise SystemExit('not found! Needed >= %s' % (CYTHON_MIN_VERSION)) # check min version if LooseVersion(Cython.__version__) < LooseVersion(CYTHON_MIN_VERSION): - raise SystemExit("too old! Found %s Needed %s" % ( + raise SystemExit('too old! Found %s Needed %s' % ( Cython.__version__, CYTHON_MIN_VERSION)) # check black-listed releases if Cython.__version__.startswith(CYTHON_BLACKLIST): - raise SystemExit("found %s, it's broken! Need another release" % + raise SystemExit('found %s, its broken! Need another release' % Cython.__version__) - sys.stdout.write("OK, found %s\n" % Cython.__version__) - module_suffix = ".pyx" + sys.stdout.write('OK, found %s\n' % Cython.__version__) + MODULES_EXT = 'pyx' # Stop compilation on first error Cython.Compiler.Options.fast_fail = True # Generates HTML files with annotated source @@ -266,223 +161,279 @@ if set(("build", "build_ext", "install", "bdist", "sdist")) & set(sys.argv): Cython.Compiler.Options.docstrings = True else: - sys.stdout.write("not needed, using pre-generated C files\n") - module_suffix = ".c" + sys.stdout.write('not needed, using pre-generated C files\n') + MODULES_EXT = 'c' # === Eina === eina_cflags, eina_libs = pkg_config('Eina', 'eina', EFL_MIN_VER) # === Eo === eo_cflags, eo_libs = pkg_config('Eo', 'eo', EFL_MIN_VER) - eo_ext = Extension("efl.eo", - ["efl/eo/efl.eo" + module_suffix], - define_macros=[ - ('EFL_BETA_API_SUPPORT', 1), - ('EFL_EO_API_SUPPORT', 1) - ], - include_dirs=['include/'], - extra_compile_args=eo_cflags + common_cflags, - extra_link_args=eo_libs + eina_libs - ) - ext_modules.append(eo_ext) + ext_modules.append(Extension( + 'efl.eo', ['efl/eo/efl.eo.' + MODULES_EXT], + extra_compile_args=eo_cflags + common_cflags, + extra_link_args=eo_libs + )) # === Utilities === - utils_ext = [ - Extension("efl.utils.deprecated", - ["efl/utils/deprecated" + module_suffix], - include_dirs=['include/'], - extra_compile_args=eina_cflags + common_cflags, - extra_link_args=eina_libs), - Extension("efl.utils.conversions", - ["efl/utils/conversions" + module_suffix], - include_dirs=['include/'], - extra_compile_args=eo_cflags + common_cflags, - extra_link_args=eo_libs + eina_libs), - Extension("efl.utils.logger", - ["efl/utils/logger" + module_suffix], - include_dirs=['include/'], - extra_compile_args=eina_cflags + common_cflags, - extra_link_args=eina_libs), - ] - ext_modules.extend(utils_ext) - py_modules.append("efl.utils.setup") - packages.append("efl.utils") + ext_modules.append(Extension( + 'efl.utils.deprecated', ['efl/utils/deprecated.' + MODULES_EXT], + extra_compile_args=eina_cflags + common_cflags, + extra_link_args=eina_libs + )) + ext_modules.append(Extension( + 'efl.utils.conversions', ['efl/utils/conversions.' + MODULES_EXT], + extra_compile_args=eo_cflags + common_cflags, + extra_link_args=eo_libs + eina_libs + )) + ext_modules.append(Extension( + 'efl.utils.logger', ['efl/utils/logger.' + MODULES_EXT], + extra_compile_args=eina_cflags + common_cflags, + extra_link_args=eina_libs + )) + py_modules.append('efl.utils.setup') + packages.append('efl.utils') # === Evas === evas_cflags, evas_libs = pkg_config('Evas', 'evas', EFL_MIN_VER) - evas_ext = Extension("efl.evas", - ["efl/evas/efl.evas" + module_suffix], - define_macros=[ - ('EFL_BETA_API_SUPPORT', 1), - ('EFL_EO_API_SUPPORT', 1) - ], - include_dirs=['include/'], - extra_compile_args=evas_cflags + common_cflags, - extra_link_args=evas_libs + eina_libs + eo_libs) - ext_modules.append(evas_ext) - - # === Ecore === + ext_modules.append(Extension( + 'efl.evas', ['efl/evas/efl.evas.' + MODULES_EXT], + extra_compile_args=evas_cflags + common_cflags, + extra_link_args=evas_libs + )) + + # === Ecore + EcoreFile === ecore_cflags, ecore_libs = pkg_config('Ecore', 'ecore', EFL_MIN_VER) - ecore_file_cflags, ecore_file_libs = pkg_config('EcoreFile', 'ecore-file', - EFL_MIN_VER) - ecore_ext = Extension("efl.ecore", - ["efl/ecore/efl.ecore" + module_suffix], - include_dirs=['include/'], - extra_compile_args=list(set(ecore_cflags + - ecore_file_cflags + - common_cflags)), - extra_link_args=ecore_libs + ecore_file_libs + - eina_libs + evas_libs) - ext_modules.append(ecore_ext) + ecore_file_cflags, ecore_file_libs = pkg_config('EcoreFile', 'ecore-file', EFL_MIN_VER) + ext_modules.append(Extension( + 'efl.ecore', ['efl/ecore/efl.ecore.' + MODULES_EXT], + extra_compile_args=list(set(ecore_cflags + ecore_file_cflags + common_cflags)), + extra_link_args=ecore_libs + ecore_file_libs + )) # === Ecore Input === - ecore_input_cflags, ecore_input_libs = pkg_config('EcoreInput', - 'ecore-input', - EFL_MIN_VER) - ecore_input_ext = Extension("efl.ecore_input", - ["efl/ecore_input/efl.ecore_input" + module_suffix], - include_dirs=['include/'], - extra_compile_args=list(set(ecore_cflags + - ecore_file_cflags + - ecore_input_cflags + - common_cflags)), - extra_link_args=ecore_libs + ecore_file_libs + - ecore_input_libs) - ext_modules.append(ecore_input_ext) + ecore_input_cflags, ecore_input_libs = pkg_config('EcoreInput', 'ecore-input', EFL_MIN_VER) + ext_modules.append(Extension( + 'efl.ecore_input', ['efl/ecore_input/efl.ecore_input.' + MODULES_EXT], + extra_compile_args=ecore_input_cflags + common_cflags, + extra_link_args=ecore_input_libs + )) # === Ecore Con === - ecore_con_cflags, ecore_con_libs = pkg_config('EcoreCon', 'ecore-con', - EFL_MIN_VER) - ecore_con_ext = Extension("efl.ecore_con", - ["efl/ecore_con/efl.ecore_con" + module_suffix], - include_dirs=['include/'], - extra_compile_args=list(set(ecore_cflags + - ecore_file_cflags + - ecore_con_cflags + - common_cflags)), - extra_link_args=ecore_libs + ecore_file_libs + - ecore_con_libs + eina_libs) - ext_modules.append(ecore_con_ext) + ecore_con_cflags, ecore_con_libs = pkg_config('EcoreCon', 'ecore-con', EFL_MIN_VER) + ext_modules.append(Extension( + 'efl.ecore_con', ['efl/ecore_con/efl.ecore_con.' + MODULES_EXT], + extra_compile_args=ecore_con_cflags + ecore_file_cflags + common_cflags, + extra_link_args=ecore_con_libs + )) # === Ecore X === try: - ecore_x_cflags, ecore_x_libs = pkg_config('EcoreX', 'ecore-x', - EFL_MIN_VER) + ecore_x_cflags, ecore_x_libs = pkg_config('EcoreX', 'ecore-x', EFL_MIN_VER) except SystemExit: - print("Not found, will not be built") + print('Not found, will not be built') else: - ecore_x_ext = Extension("efl.ecore_x", - ["efl/ecore_x/efl.ecore_x" + module_suffix], - include_dirs=['include/'], - extra_compile_args=list(set(ecore_cflags + - ecore_file_cflags + - ecore_x_cflags + - ecore_input_cflags + - common_cflags)), - extra_link_args=ecore_libs + ecore_file_libs + - ecore_x_libs + ecore_input_libs + - eina_libs + evas_libs) - ext_modules.append(ecore_x_ext) + ext_modules.append(Extension( + 'efl.ecore_x', ['efl/ecore_x/efl.ecore_x.' + MODULES_EXT], + extra_compile_args=ecore_x_cflags + common_cflags, + extra_link_args=ecore_x_libs + )) # === Ethumb === ethumb_cflags, ethumb_libs = pkg_config('Ethumb', 'ethumb', EFL_MIN_VER) - ethumb_ext = Extension("efl.ethumb", - ["efl/ethumb/efl.ethumb" + module_suffix], - include_dirs=['include/'], - extra_compile_args=ethumb_cflags + common_cflags, - extra_link_args=ethumb_libs + eina_libs) - ext_modules.append(ethumb_ext) + ext_modules.append(Extension( + 'efl.ethumb', ['efl/ethumb/efl.ethumb.' + MODULES_EXT], + extra_compile_args=ethumb_cflags + common_cflags, + extra_link_args=ethumb_libs + )) # === Ethumb Client === - ethumb_client_cflags, ethumb_client_libs = pkg_config('Ethumb_Client', - 'ethumb_client', EFL_MIN_VER) - ethumb_client_ext = Extension("efl.ethumb_client", - ["efl/ethumb/efl.ethumb_client" + module_suffix], - include_dirs=['include/'], - extra_compile_args=ethumb_client_cflags + - common_cflags, - extra_link_args=ethumb_client_libs + eina_libs) - ext_modules.append(ethumb_client_ext) + ethumb_cl_cflags, ethumb_cl_libs = pkg_config('Ethumb_Client', 'ethumb_client', EFL_MIN_VER) + ext_modules.append(Extension( + 'efl.ethumb_client', ['efl/ethumb/efl.ethumb_client.' + MODULES_EXT], + extra_compile_args=ethumb_cl_cflags + common_cflags, + extra_link_args=ethumb_cl_libs + )) # === Edje === edje_cflags, edje_libs = pkg_config('Edje', 'edje', EFL_MIN_VER) - edje_ext = Extension("efl.edje", - ["efl/edje/efl.edje" + module_suffix], - include_dirs=['include/'], - extra_compile_args=edje_cflags + common_cflags, - extra_link_args=edje_libs + eina_libs + evas_libs) - ext_modules.append(edje_ext) + ext_modules.append(Extension( + 'efl.edje', ['efl/edje/efl.edje.' + MODULES_EXT], + extra_compile_args=edje_cflags + common_cflags, + extra_link_args=edje_libs + )) # === Edje_Edit === - edje_edit_ext = Extension("efl.edje_edit", - ["efl/edje_edit/efl.edje_edit" + module_suffix], - define_macros=[('EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT', None)], - include_dirs=['include/'], - extra_compile_args=edje_cflags + common_cflags, - extra_link_args=edje_libs + eina_libs + evas_libs) - ext_modules.append(edje_edit_ext) + ext_modules.append(Extension( + 'efl.edje_edit', ['efl/edje_edit/efl.edje_edit.' + MODULES_EXT], + define_macros=[('EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT', None)], + extra_compile_args=edje_cflags + common_cflags, + extra_link_args=edje_libs + )) # === Emotion === emotion_cflags, emotion_libs = pkg_config('Emotion', 'emotion', EFL_MIN_VER) - emotion_ext = Extension("efl.emotion", - ["efl/emotion/efl.emotion" + module_suffix], - include_dirs=['include/'], - extra_compile_args=emotion_cflags + common_cflags, - extra_link_args=emotion_libs + eina_libs + evas_libs) - ext_modules.append(emotion_ext) + ext_modules.append(Extension( + 'efl.emotion', ['efl/emotion/efl.emotion.' + MODULES_EXT], + extra_compile_args=emotion_cflags + common_cflags, + extra_link_args=emotion_libs + )) # === dbus mainloop integration === - dbus_cflags, dbus_libs = pkg_config('DBus', 'dbus-python', "0.83.0") - dbus_ml_ext = Extension("efl.dbus_mainloop", - ["efl/dbus_mainloop/efl.dbus_mainloop" + module_suffix, - "efl/dbus_mainloop/e_dbus.c"], - extra_compile_args=list(set(dbus_cflags + - ecore_cflags + - common_cflags)), - extra_link_args=dbus_libs + ecore_libs) - ext_modules.append(dbus_ml_ext) + dbus_cflags, dbus_libs = pkg_config('DBus', 'dbus-python', '0.83.0') + ext_modules.append(Extension( + 'efl.dbus_mainloop', ['efl/dbus_mainloop/efl.dbus_mainloop.' + MODULES_EXT, + 'efl/dbus_mainloop/e_dbus.c'], + extra_compile_args=dbus_cflags + ecore_cflags + common_cflags, + extra_link_args=dbus_libs + ecore_libs + )) # === Elementary === - elm_cflags, elm_libs = pkg_config('Elementary', 'elementary', ELM_MIN_VER) - e = Extension("efl.elementary.__init__", - ["efl/elementary/__init__" + module_suffix], - define_macros=[ - ('EFL_BETA_API_SUPPORT', 1), - ('EFL_EO_API_SUPPORT', 1) - ], - include_dirs=["include/"], - extra_compile_args=elm_cflags + common_cflags, - extra_link_args=elm_libs + eina_libs + eo_libs + evas_libs) - ext_modules.append(e) - - packages.append("efl.elementary") - - # Cythonize all the external modules (if needed) + elm_cflags, elm_libs = pkg_config('Elementary', 'elementary', EFL_MIN_VER) + ext_modules.append(Extension( + 'efl.elementary.__init__', ['efl/elementary/__init__.' + MODULES_EXT], + extra_compile_args=elm_cflags + common_cflags, + extra_link_args=elm_libs + )) + packages.append('efl.elementary') + + # Cythonize all ext_modules if USE_CYTHON: - ext_modules = cythonize(ext_modules, - include_path=["include"], - compiler_directives={ - #"c_string_type": "unicode", - #"c_string_encoding": "utf-8", - "embedsignature": True, - "binding": True, - "language_level": 2, - }) + from Cython.Build import cythonize + ext_modules = cythonize( + ext_modules, + include_path=['include'], + compiler_directives={ + #'c_string_type': 'unicode', + #'c_string_encoding': 'utf-8', + 'embedsignature': True, + 'binding': True, + 'language_level': 2, + } + ) + + +# === setup.py test command === +class Test(Command): + description = 'Run all the available unit tests using efl in build/' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + sys.path.insert(0, 'build/lib.%s-%s-%d.%d' % ( + platform.system().lower(), platform.machine(), + sys.version_info[0], sys.version_info[1])) + if 'efl' in sys.modules: + del sys.modules['efl'] + + loader = unittest.TestLoader() + suite = loader.discover('./tests') + runner = unittest.TextTestRunner(verbosity=1, buffer=True) + runner.run(suite) + + +# === setup.py build_doc command === +try: + from sphinx.setup_command import BuildDoc +except ImportError: + class BuildDoc(Command): + description = 'build docs using sphinx, that must be installed.' + version = '' + release = '' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + print('Error: sphinx not found') + + +# === setup.py clean_generated_files command === +class CleanGenerated(Command): + description = 'Clean C and html files generated by Cython' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + for lib in ('eo', 'evas', 'ecore', 'ecore_x', 'ecore_input', 'ecore_con', 'edje', + 'emotion', 'elementary', 'ethumb', 'dbus_mainloop', 'utils'): + lib_path = os.path.join(script_path, 'efl', lib) + for root, _dirs, files in os.walk(lib_path): + for fname in files: + if fname.endswith(('.c', '.html')) and fname != 'e_dbus.c': + self.remove(os.path.join(root, fname)) + + def remove(self, fullpath): + print('removing %s' % fullpath.replace(script_path, '').lstrip('/')) + os.remove(fullpath) + + +# === setup.py uninstall command === +RECORD_FILE = 'installed_files-%d.%d.txt' % sys.version_info[:2] +class Uninstall(Command): + description = 'remove all the installed files recorded at installation time' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def remove_entry(self, entry): + if os.path.isfile(entry): + try: + print('removing file %s' % entry) + os.unlink(entry) + except OSError as err: + print(err) + return + + directory = os.path.dirname(entry) + while os.listdir(directory) == []: + try: + print('removing empty directory %s' % directory) + os.rmdir(directory) + except OSError as err: + print(err) + break + directory = os.path.dirname(directory) + + def run(self): + if not os.path.exists(RECORD_FILE): + print('ERROR: No %s file found!' % RECORD_FILE) + else: + for entry in open(RECORD_FILE).read().split(): + self.remove_entry(entry) setup( - name="python-efl", - fullname="Python bindings for Enlightenment Foundation Libraries", - description="Python bindings for Enlightenment Foundation Libraries", - long_description=open(os.path.join(script_path, 'README.md')).read(), + name='python-efl', + fullname='Python bindings for Enlightenment Foundation Libraries', + description='Python bindings for Enlightenment Foundation Libraries', + long_description=read_file('README.md'), version=RELEASE, author='Davide Andreoli, Kai Huuhko, and others', - author_email="d...@gurumeditation.it, kai.huu...@gmail.com", - contact="Enlightenment developer mailing list", - contact_email="enlightenment-devel@lists.sourceforge.net", - url="http://www.enlightenment.org", - license="GNU Lesser General Public License (LGPL)", - keywords="efl wrapper binding enlightenment eo evas ecore edje emotion elementary ethumb", + author_email='d...@gurumeditation.it, kai.huu...@gmail.com', + contact='Enlightenment developer mailing list', + contact_email='enlightenment-devel@lists.sourceforge.net', + url='http://www.enlightenment.org', + license='GNU Lesser General Public License (LGPL)', + keywords='efl wrapper binding enlightenment eo evas ecore edje emotion elementary ethumb', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: X11 Applications', @@ -503,11 +454,10 @@ setup( 'build_doc': BuildDoc, 'clean_generated_files': CleanGenerated, 'uninstall': Uninstall, - 'build_ext': build_ext, }, command_options={ 'build_doc': { - 'version': ('setup.py', VERSION), + 'version': ('setup.py', RELEASE), 'release': ('setup.py', RELEASE), }, 'install': { @@ -517,4 +467,5 @@ setup( packages=packages, ext_modules=ext_modules, py_modules=py_modules, + zip_safe=False, ) --