Commit 44d4d59a authored by Carsten Richter's avatar Carsten Richter

Merge branch 'project' into 'master'

Update project files

Closes #22 and #19

See merge request !62
parents 07b03582 6777983f
Pipeline #4192 passed with stages
in 3 minutes and 11 seconds
......@@ -5,6 +5,10 @@ __pycache__/
# C extensions
*.so
# Cython generated files
xsocs/util/filt_utils/filt_utils.c
xsocs/util/filt_utils/histogramnd_lut.c
# Distribution / packaging
.Python
env/
......
......@@ -10,7 +10,7 @@ example: ./bootstrap.py ipython
__authors__ = ["Frédéric-Emmanuel Picca", "Jérôme Kieffer"]
__contact__ = "jerome.kieffer@esrf.eu"
__license__ = "MIT"
__date__ = "08/01/2018"
__date__ = "02/03/2018"
import sys
......@@ -193,6 +193,9 @@ os.chdir(home)
build = subprocess.Popen([sys.executable, "setup.py", "build"],
shell=False, cwd=os.path.dirname(os.path.abspath(__file__)))
build_rc = build.wait()
if not os.path.exists(LIBPATH):
logger.warning("`lib` directory does not exist, trying common Python3 lib")
LIBPATH = os.path.join(os.path.split(LIBPATH)[0], "lib")
os.chdir(cwd)
if build_rc == 0:
......
......@@ -32,7 +32,7 @@ Test coverage dependencies: coverage, lxml.
"""
__authors__ = ["Jérôme Kieffer", "Thomas Vincent"]
__date__ = "29/01/2018"
__date__ = "02/03/2018"
__license__ = "MIT"
import distutils.util
......@@ -76,7 +76,11 @@ def createBasicHandler():
# Use an handler compatible with unittests, else use_buffer is not working
logging.root.addHandler(createBasicHandler())
# Capture all default warnings
logging.captureWarnings(True)
import warnings
warnings.simplefilter('default')
logger = logging.getLogger("run_tests")
logger.setLevel(logging.WARNING)
......@@ -292,7 +296,12 @@ def build_project(name, root_dir):
p = subprocess.Popen([sys.executable, "setup.py", "build"],
shell=False, cwd=root_dir)
logger.debug("subprocess ended with rc= %s", p.wait())
return home
if os.path.isdir(home):
return home
alt_home = os.path.join(os.path.dirname(home), "lib")
if os.path.isdir(alt_home):
return alt_home
def import_project_module(project_name, project_dir):
......@@ -311,7 +320,8 @@ def import_project_module(project_name, project_dir):
PROJECT_NAME)
else: # Use built source
build_dir = build_project(project_name, project_dir)
if build_dir is None:
logging.error("Built project is not available !!! investigate")
sys.path.insert(0, build_dir)
logger.warning("Patched sys.path, added: '%s'", build_dir)
module = importer(project_name)
......
......@@ -2,7 +2,7 @@
# coding: utf8
# /*##########################################################################
#
# Copyright (c) 2015-2017 European Synchrotron Radiation Facility
# Copyright (c) 2015-2018 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -25,21 +25,20 @@
# ###########################################################################*/
__authors__ = ["Jérôme Kieffer", "Thomas Vincent"]
__date__ = "11/05/2017"
__date__ = "23/04/2018"
__license__ = "MIT"
# This import is here only to fix a bug on Debian 7 with python2.7
# Without this, the system io module is not loaded from numpy.distutils
# the xsocs.io module seems to be loaded instead
import io
import sys
import os
import platform
import shutil
import logging
import glob
# io import has to be here also to fix a bug on Debian 7 with python2.7
# Without this, the system io module is not loaded from numpy.distutils.
# The silx.io module seems to be loaded instead.
import io
logging.basicConfig(level=logging.INFO)
......@@ -112,6 +111,8 @@ classifiers = ["Development Status :: 4 - Beta",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: Scientific/Engineering :: Physics",
"Topic :: Software Development :: Libraries :: Python Modules",
......@@ -138,9 +139,11 @@ class build_py(_build_py):
########
class PyTest(Command):
"""Command to start tests running the script: run_tests.py -i"""
"""Command to start tests running the script: run_tests.py"""
user_options = []
description = "Execute the unittests"
def initialize_options(self):
pass
......@@ -149,7 +152,7 @@ class PyTest(Command):
def run(self):
import subprocess
errno = subprocess.call([sys.executable, 'run_tests.py', '-i'])
errno = subprocess.call([sys.executable, 'run_tests.py'])
if errno != 0:
raise SystemExit(errno)
......@@ -242,6 +245,7 @@ if sphinx is not None:
else:
TestDocCommand = SphinxExpectedCommand
# ############################# #
# numpy.distutils Configuration #
# ############################# #
......@@ -402,7 +406,7 @@ class BuildExt(build_ext):
COMPILE_ARGS_CONVERTER = {'-fopenmp': '/openmp'}
LINK_ARGS_CONVERTER = {'-fopenmp': ' '}
LINK_ARGS_CONVERTER = {'-fopenmp': ''}
description = 'Build xsocs extensions'
......@@ -452,8 +456,7 @@ class BuildExt(build_ext):
patched_exts = cythonize(
[ext],
compiler_directives={'embedsignature': True},
force=self.force_cython,
compile_time_env={"HAVE_OPENMP": self.use_openmp}
force=self.force_cython
)
ext.sources = patched_exts[0].sources
......@@ -471,6 +474,15 @@ class BuildExt(build_ext):
ext.extra_link_args = [self.LINK_ARGS_CONVERTER.get(f, f)
for f in ext.extra_link_args]
elif self.compiler.compiler_type == 'unix':
# Avoids runtime symbol collision for manylinux1 platform
# See issue #1070
extern = 'extern "C" ' if ext.language == 'c++' else ''
return_type = 'void' if sys.version_info[0] <= 2 else 'PyObject*'
ext.extra_compile_args.append(
'''-fvisibility=hidden -D'PyMODINIT_FUNC=%s__attribute__((visibility("default"))) %s ' ''' % (extern, return_type))
def is_debug_interpreter(self):
"""
Returns true if the script is executed with a debug interpreter.
......@@ -532,7 +544,6 @@ class BuildExt(build_ext):
self.patch_extension(ext)
build_ext.build_extensions(self)
################################################################################
# Clean command
################################################################################
......@@ -557,12 +568,35 @@ class CleanCommand(Clean):
path_list2.append(path)
return path_list2
def find(self, path_list):
"""Find a file pattern if directories.
Could be done using "**/*.c" but it is only supported in Python 3.5.
:param list[str] path_list: A list of path which may contains magic
:rtype: list[str]
:returns: A list of path without magic
"""
import fnmatch
path_list2 = []
for pattern in path_list:
for root, _, filenames in os.walk('.'):
for filename in fnmatch.filter(filenames, pattern):
path_list2.append(os.path.join(root, filename))
return path_list2
def run(self):
Clean.run(self)
cython_files = self.find(["*.pyx"])
cythonized_files = [path.replace(".pyx", ".c") for path in cython_files]
cythonized_files += [path.replace(".pyx", ".cpp") for path in cython_files]
# really remove the directories
# and not only if they are empty
to_remove = [self.build_base]
to_remove = self.expand(to_remove)
to_remove += cythonized_files
if not self.dry_run:
for path in to_remove:
......@@ -575,6 +609,37 @@ class CleanCommand(Clean):
except OSError:
pass
################################################################################
# Source tree
################################################################################
class SourceDistWithCython(sdist):
"""
Force cythonization of the extensions before generating the source
distribution.
To provide the widest compatibility the cythonized files are provided
without suppport of OpenMP.
"""
description = "Create a source distribution including cythonozed files (tarball, zip file, etc.)"
def finalize_options(self):
sdist.finalize_options(self)
self.extensions = self.distribution.ext_modules
def run(self):
self.cythonize_extensions()
sdist.run(self)
def cythonize_extensions(self):
from Cython.Build import cythonize
cythonize(
self.extensions,
compiler_directives={'embedsignature': True},
force=True
)
################################################################################
# Debian source tree
################################################################################
......@@ -585,10 +650,13 @@ class sdist_debian(sdist):
Tailor made sdist for debian
* remove auto-generated doc
* remove cython generated .c files
* remove cython generated .c files
* remove cython generated .cpp files
* remove .bat files
* include .l man files
"""
description = "Create a source distribution for Debian (tarball, zip file, etc.)"
@staticmethod
def get_debian_name():
import version
......@@ -623,10 +691,10 @@ class sdist_debian(sdist):
base, ext = os.path.splitext(basename)
while ext in [".zip", ".tar", ".bz2", ".gz", ".Z", ".lz", ".orig"]:
base, ext = os.path.splitext(base)
if ext:
dest = "".join((base, ext))
else:
dest = base
# if ext:
# dest = "".join((base, ext))
# else:
# dest = base
# sp = dest.split("-")
# base = sp[:-1]
# nr = sp[-1]
......@@ -642,13 +710,22 @@ class sdist_debian(sdist):
def get_project_configuration(dry_run):
"""Returns project arguments for setup"""
# Use installed numpy version as minimal required version
# This is useful for wheels to advertise the numpy version they were built with
if dry_run:
numpy_requested_version = ""
else:
from numpy.version import version as numpy_version
numpy_requested_version = ">=%s" % numpy_version
logger.info("Install requires: numpy %s", numpy_requested_version)
install_requires = [
# for most of the computation
"numpy",
"numpy%s" % numpy_requested_version,
# for the script launcher
"setuptools"]
setup_requires = ["setuptools", "numpy"]
setup_requires = ["setuptools", "numpy", "Cython>=0.21.1"]
package_data = {
'xsocs.resources': [
......@@ -671,6 +748,7 @@ def get_project_configuration(dry_run):
test_doc=TestDocCommand,
build_ext=BuildExt,
clean=CleanCommand,
sdist=SourceDistWithCython,
debian_src=sdist_debian)
if dry_run:
......@@ -717,7 +795,7 @@ def setup_package():
'clean', '--name')))
if dry_run:
# DRY_RUN implies actions which do not require dependancies, like NumPy
# DRY_RUN implies actions which do not require dependencies, like NumPy
try:
from setuptools import setup
logger.info("Use setuptools.setup")
......@@ -729,7 +807,7 @@ def setup_package():
from setuptools import setup
except ImportError:
from numpy.distutils.core import setup
logger.info("Use numpydistutils.setup")
logger.info("Use numpy.distutils.setup")
setup_kwargs = get_project_configuration(dry_run)
setup(**setup_kwargs)
......
#!/usr/bin/env python
# coding: utf-8
# /*##########################################################################
#
# Copyright (c) 2015-2016 European Synchrotron Radiation Facility
# Copyright (c) 2015-2017 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -22,13 +23,48 @@
# THE SOFTWARE.
#
# ###########################################################################*/
"""Unique place where the version number is defined."""
"""Unique place where the version number is defined.
provides:
* version = "1.2.3" or "1.2.3-beta4"
* version_info = named tuple (1,2,3,"beta",4)
* hexversion: 0x010203B4
* strictversion = "1.2.3b4
* debianversion = "1.2.3~beta4"
* calc_hexversion: the function to transform a version_tuple into an integer
This is called hexversion since it only really looks meaningful when viewed as the
result of passing it to the built-in hex() function.
The version_info value may be used for a more human-friendly encoding of the same information.
The hexversion is a 32-bit number with the following layout:
Bits (big endian order) Meaning
1-8 PY_MAJOR_VERSION (the 2 in 2.1.0a3)
9-16 PY_MINOR_VERSION (the 1 in 2.1.0a3)
17-24 PY_MICRO_VERSION (the 0 in 2.1.0a3)
25-28 PY_RELEASE_LEVEL (0xA for alpha, 0xB for beta, 0xC for release candidate and 0xF for final)
29-32 PY_RELEASE_SERIAL (the 3 in 2.1.0a3, zero for final releases)
Thus 2.1.0a3 is hexversion 0x020100a3.
"""
from __future__ import absolute_import, print_function, division
__authors__ = ["Jérôme Kieffer"]
__license__ = "MIT"
__date__ = "18/10/2016"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "28/02/2018"
__status__ = "production"
__docformat__ = 'restructuredtext'
__all__ = ["date", "version_info", "strictversion", "hexversion", "debianversion",
"calc_hexversion"]
# Do not copy into the source folder !
RELEASE_LEVEL_VALUE = {"dev": 0,
"alpha": 10,
"beta": 11,
"gamma": 12,
"rc": 13,
"final": 15}
MAJOR = 0
MINOR = 6
......@@ -36,29 +72,48 @@ MICRO = 0
RELEV = "dev" # <16
SERIAL = 0 # <16
date = __date__
from collections import namedtuple
_version_info = namedtuple(
"version_info", ["major", "minor", "micro", "releaselevel", "serial"])
_version_info = namedtuple("version_info", ["major", "minor", "micro", "releaselevel", "serial"])
version_info = _version_info(MAJOR, MINOR, MICRO, RELEV, SERIAL)
strictversion = version = "%d.%d.%d" % version_info[:3]
RELEASE_LEVEL_VALUE = {"dev": 0,
"alpha": 10,
"beta": 11,
"rc": 12,
"final": 15}
strictversion = version = debianversion = "%d.%d.%d" % version_info[:3]
if version_info.releaselevel != "final":
version += "-%s%s" % version_info[-2:]
debianversion += "~adev%i" % version_info[-1] if RELEV == "dev" else "~%s%i" % version_info[-2:]
prerel = "a" if RELEASE_LEVEL_VALUE.get(version_info[3], 0) < 10 else "b"
if prerel not in "ab":
prerel = "a"
strictversion += prerel + str(version_info[-1])
hexversion = version_info[4]
hexversion |= RELEASE_LEVEL_VALUE.get(version_info[3], 0) * 1 << 4
hexversion |= version_info[2] * 1 << 8
hexversion |= version_info[1] * 1 << 16
hexversion |= version_info[0] * 1 << 24
def calc_hexversion(major=0, minor=0, micro=0, releaselevel="dev", serial=0):
"""Calculate the hexadecimal version number from the tuple version_info:
:param major: integer
:param minor: integer
:param micro: integer
:param relev: integer or string
:param serial: integer
:return: integer always increasing with revision numbers
"""
try:
releaselevel = int(releaselevel)
except ValueError:
releaselevel = RELEASE_LEVEL_VALUE.get(releaselevel, 0)
hex_version = int(serial)
hex_version |= releaselevel * 1 << 4
hex_version |= int(micro) * 1 << 8
hex_version |= int(minor) * 1 << 16
hex_version |= int(major) * 1 << 24
return hex_version
hexversion = calc_hexversion(*version_info)
if __name__ == "__main__":
print(version)
# coding: utf-8
# /*##########################################################################
#
# Copyright (c) 2015-2016 European Synchrotron Radiation Facility
# Copyright (c) 2015-2018 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -27,14 +27,19 @@ from __future__ import absolute_import, print_function, division
__authors__ = ["Jérôme Kieffer"]
__license__ = "MIT"
__date__ = "28/01/2016"
__date__ = "26/04/2018"
import os as _os
import logging as _logging
# Attach a do nothing logging handler for xsocs
_logging.getLogger(__name__).addHandler(_logging.NullHandler())
project = _os.path.basename(_os.path.dirname(_os.path.abspath(__file__)))
import os
project = os.path.basename(os.path.dirname(os.path.abspath(__file__)))
try:
from ._version import __date__ as date # noqa
from ._version import version, version_info, hexversion, strictversion
# noqa
from ._version import version, version_info, hexversion, strictversion # noqa
except ImportError:
raise RuntimeError("Do NOT use %s from its sources: "
"build it and use the built version" % project)
raise RuntimeError("Do NOT use %s from its sources: build it and use the built version" % project)
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment