From fdfa51a8c752d7b820de993cbdfffa4cdd3688be Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Sun, 24 May 2015 22:35:12 +0200 Subject: [PATCH] A first version of the obidistutils adapted to Python3 --- distutils.ext/obidistutils/__init__.py | 0 .../obidistutils/command/__init__.py | 0 distutils.ext/obidistutils/command/build.py | 42 ++++ .../obidistutils/command/build_cexe.py | 73 ++++++ .../obidistutils/command/build_ctools.py | 55 +++++ .../obidistutils/command/build_exe.py | 210 ++++++++++++++++++ .../obidistutils/command/build_ext.py | 93 ++++++++ .../obidistutils/command/build_files.py | 53 +++++ .../obidistutils/command/build_scripts.py | 104 +++++++++ .../obidistutils/command/build_sphinx.py | 26 +++ distutils.ext/obidistutils/command/install.py | 19 ++ .../obidistutils/command/install_scripts.py | 43 ++++ .../obidistutils/command/install_sphinx.py | 46 ++++ .../obidistutils/command/littlebigman.py | 59 +++++ distutils.ext/obidistutils/command/pidname.py | 51 +++++ distutils.ext/obidistutils/command/sdist.py | 42 ++++ distutils.ext/obidistutils/core.py | 170 ++++++++++++++ distutils.ext/obidistutils/dist.py | 45 ++++ .../obidistutils/serenity/__init__.py | 0 .../obidistutils/serenity/checkpackage.py | 156 +++++++++++++ .../obidistutils/serenity/checkpython.py | 79 +++++++ .../obidistutils/serenity/checksystem.py | 18 ++ .../obidistutils/serenity/globals.py | 14 ++ distutils.ext/obidistutils/serenity/rerun.py | 59 +++++ distutils.ext/obidistutils/serenity/snake.py | 35 +++ distutils.ext/src/littlebigman.c | 24 ++ distutils.ext/src/pidname.c | 24 ++ 27 files changed, 1540 insertions(+) create mode 100644 distutils.ext/obidistutils/__init__.py create mode 100644 distutils.ext/obidistutils/command/__init__.py create mode 100644 distutils.ext/obidistutils/command/build.py create mode 100644 distutils.ext/obidistutils/command/build_cexe.py create mode 100644 distutils.ext/obidistutils/command/build_ctools.py create mode 100644 distutils.ext/obidistutils/command/build_exe.py create mode 100644 distutils.ext/obidistutils/command/build_ext.py create mode 100644 distutils.ext/obidistutils/command/build_files.py create mode 100644 distutils.ext/obidistutils/command/build_scripts.py create mode 100644 distutils.ext/obidistutils/command/build_sphinx.py create mode 100644 distutils.ext/obidistutils/command/install.py create mode 100644 distutils.ext/obidistutils/command/install_scripts.py create mode 100644 distutils.ext/obidistutils/command/install_sphinx.py create mode 100644 distutils.ext/obidistutils/command/littlebigman.py create mode 100644 distutils.ext/obidistutils/command/pidname.py create mode 100644 distutils.ext/obidistutils/command/sdist.py create mode 100644 distutils.ext/obidistutils/core.py create mode 100644 distutils.ext/obidistutils/dist.py create mode 100644 distutils.ext/obidistutils/serenity/__init__.py create mode 100644 distutils.ext/obidistutils/serenity/checkpackage.py create mode 100644 distutils.ext/obidistutils/serenity/checkpython.py create mode 100644 distutils.ext/obidistutils/serenity/checksystem.py create mode 100644 distutils.ext/obidistutils/serenity/globals.py create mode 100644 distutils.ext/obidistutils/serenity/rerun.py create mode 100644 distutils.ext/obidistutils/serenity/snake.py create mode 100644 distutils.ext/src/littlebigman.c create mode 100644 distutils.ext/src/pidname.c diff --git a/distutils.ext/obidistutils/__init__.py b/distutils.ext/obidistutils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/distutils.ext/obidistutils/command/__init__.py b/distutils.ext/obidistutils/command/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/distutils.ext/obidistutils/command/build.py b/distutils.ext/obidistutils/command/build.py new file mode 100644 index 0000000..6996b88 --- /dev/null +++ b/distutils.ext/obidistutils/command/build.py @@ -0,0 +1,42 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + +from distutils.command.build import build as ori_build +from obidistutils.serenity.checksystem import is_mac_system + + +class build(ori_build): + + def has_ctools(self): + return self.distribution.has_ctools() + + def has_files(self): + return self.distribution.has_files() + + def has_executables(self): + return self.distribution.has_executables() + + def has_ext_modules(self): + return self.distribution.has_ext_modules() + + def has_littlebigman(self): + return True + + def has_pidname(self): + return is_mac_system() + + def has_doc(self): + return True + + + sub_commands = [('littlebigman', has_littlebigman), + ('pidname',has_pidname), + ('build_ctools', has_ctools), + ('build_files', has_files), + ('build_cexe', has_executables)] \ + + ori_build.sub_commands + \ + [('build_sphinx',has_doc)] + diff --git a/distutils.ext/obidistutils/command/build_cexe.py b/distutils.ext/obidistutils/command/build_cexe.py new file mode 100644 index 0000000..a39e661 --- /dev/null +++ b/distutils.ext/obidistutils/command/build_cexe.py @@ -0,0 +1,73 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + +from obidistutils.command.build_ctools import build_ctools +from distutils.errors import DistutilsSetupError +from distutils import log + + +class build_cexe(build_ctools): + + description = "build C/C++ executable distributed with Python extensions" + + + def initialize_options(self): + build_ctools.initialize_options(self) + self.built_files = None + + + def finalize_options(self): + # This might be confusing: both build-cexe and build-temp default + # to build-temp as defined by the "build" command. This is because + # I think that C libraries are really just temporary build + # by-products, at least from the point of view of building Python + # extensions -- but I want to keep my options open. + + build_cexe_dir = self.build_cexe + build_ctools.finalize_options(self) + + if build_cexe_dir is None: + self.build_cexe=None + + self.set_undefined_options('build', + ('build_scripts', 'build_cexe')) + + self.set_undefined_options('build_files', + ('files', 'built_files')) + + self.executables = self.distribution.executables + + if self.executables: + self.check_executable_list(self.executables) + + + # XXX same as for build_ext -- what about 'self.define' and + # 'self.undef' ? + + def substitute_sources(self,exe_name,sources): + """ + Substitutes source file name starting by an @ by the actual + name of the built file (see --> build_files) + """ + sources = list(sources) + for i in range(len(sources)): + message = "%s :-> %s" % (exe_name,sources[i]) + if sources[i][0]=='@': + try: + filename = self.built_files[sources[i][1:]] + except KeyError: + raise DistutilsSetupError( + 'The %s filename declared in the source ' + 'files of the program %s have not been ' + 'built by the installation process' % (sources[i], + exe_name)) + sources[i]=filename + log.info("%s changed to %s",message,filename) + else: + log.info("%s ok",message) + + return sources + diff --git a/distutils.ext/obidistutils/command/build_ctools.py b/distutils.ext/obidistutils/command/build_ctools.py new file mode 100644 index 0000000..103d8c7 --- /dev/null +++ b/distutils.ext/obidistutils/command/build_ctools.py @@ -0,0 +1,55 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + + +from obidistutils.command.build_exe import build_exe + +class build_ctools(build_exe): + description = "build C/C++ executable not distributed with Python extensions" + + def initialize_options(self): + build_exe.initialize_options(self) + + # List of built tools + self.ctools = None + self.littlebigman = None + + + def finalize_options(self): + # This might be confusing: both build-cexe and build-temp default + # to build-temp as defined by the "build" command. This is because + # I think that C libraries are really just temporary build + # by-products, at least from the point of view of building Python + # extensions -- but I want to keep my options open. + + build_exe.finalize_options(self) + + + self.set_undefined_options('build', + ('build_temp', 'build_cexe')) + + self.set_undefined_options('littlebigman', + ('littlebigman', 'littlebigman')) + + self.executables = self.distribution.ctools + self.check_executable_list(self.executables) + + if self.littlebigman =='-DLITTLE_END': + if self.define is None: + self.define=[('LITTLE_END',None)] + else: + self.define.append('LITTLE_END',None) + + self.ctools = set() + + def run(self): + + build_exe.run(self) + for e,p in self.executables: # @UnusedVariable + self.ctools.add(e) + + + diff --git a/distutils.ext/obidistutils/command/build_exe.py b/distutils.ext/obidistutils/command/build_exe.py new file mode 100644 index 0000000..5fcd6a5 --- /dev/null +++ b/distutils.ext/obidistutils/command/build_exe.py @@ -0,0 +1,210 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + +import os + +from distutils.core import Command +from distutils.sysconfig import customize_compiler +from distutils.errors import DistutilsSetupError +from distutils import log +from distutils.ccompiler import show_compilers + +class build_exe(Command): + + description = "build an executable -- Abstract command " + + user_options = [ + ('build-cexe', 'x', + "directory to build C/C++ libraries to"), + ('build-temp', 't', + "directory to put temporary build by-products"), + ('debug', 'g', + "compile with debugging information"), + ('force', 'f', + "forcibly build everything (ignore file timestamps)"), + ('compiler=', 'c', + "specify the compiler type"), + ] + + boolean_options = ['debug', 'force'] + + help_options = [ + ('help-compiler', None, + "list available compilers", show_compilers), + ] + + def initialize_options(self): + self.build_cexe = None + self.build_temp = None + + # List of executables to build + self.executables = None + + # Compilation options for all libraries + self.include_dirs = None + self.define = None + self.undef = None + self.extra_compile_args = None + self.debug = None + self.force = 0 + self.compiler = None + self.sse = None + self.built_files=None + + def finalize_options(self): + # This might be confusing: both build-cexe and build-temp default + # to build-temp as defined by the "build" command. This is because + # I think that C libraries are really just temporary build + # by-products, at least from the point of view of building Python + # extensions -- but I want to keep my options open. + self.set_undefined_options('build', + ('build_temp', 'build_temp'), + ('compiler', 'compiler'), + ('debug', 'debug'), + ('force', 'force')) + + if self.include_dirs is None: + self.include_dirs = self.distribution.include_dirs or [] + + if isinstance(self.include_dirs, str): + self.include_dirs = self.include_dirs.split(os.pathsep) + + self.sse = self.distribution.sse + + if self.sse is not None: + if self.extra_compile_args is None: + self.extra_compile_args=['-m%s' % self.sse] + else: + self.extra_compile_args.append('-m%s' % self.sse) + + # XXX same as for build_ext -- what about 'self.define' and + # 'self.undef' ? + + def run(self): + + if not self.executables: + return + + self.mkpath(self.build_cexe) + + # Yech -- this is cut 'n pasted from build_ext.py! + from distutils.ccompiler import new_compiler + self.compiler = new_compiler(compiler=self.compiler, + dry_run=self.dry_run, + force=self.force) + customize_compiler(self.compiler) + + if self.include_dirs is not None: + self.compiler.set_include_dirs(self.include_dirs) + if self.define is not None: + # 'define' option is a list of (name,value) tuples + for (name,value) in self.define: + self.compiler.define_macro(name, value) + + if self.undef is not None: + for macro in self.undef: + self.compiler.undefine_macro(macro) + + self.build_executables(self.executables) + + + def check_executable_list(self, executables): + """Ensure that the list of executables is valid. + + `executable` is presumably provided as a command option 'executables'. + This method checks that it is a list of 2-tuples, where the tuples + are (executable_name, build_info_dict). + + Raise DistutilsSetupError if the structure is invalid anywhere; + just returns otherwise. + """ + if not isinstance(executables, list): + raise DistutilsSetupError("'executables' option must be a list of tuples") + + for exe in executables: + if not isinstance(exe, tuple) and len(exe) != 2: + raise DistutilsSetupError("each element of 'executables' must a 2-tuple") + + name, build_info = exe + + if not isinstance(name, str): + raise DistutilsSetupError( + "first element of each tuple in 'executables' " + "must be a string (the executables name)") + + if '/' in name or (os.sep != '/' and os.sep in name): + raise DistutilsSetupError( + "bad executable name '%s': " + "may not contain directory separators" % exe[0]) + + if not isinstance(build_info, dict): + raise DistutilsSetupError( + "second element of each tuple in 'executables' " + "must be a dictionary (build info)") + + def get_executable_names(self): + # Assume the executables list is valid -- 'check_executable_list()' is + # called from 'finalize_options()', so it should be! + if not self.executables: + return None + + exe_names = [] + for (exe_name, build_info) in self.executables: # @UnusedVariable + exe_names.append(exe_name) + return exe_names + + + def get_source_files(self): + self.check_executable_list(self.executables) + filenames = [] + for (exe_name, build_info) in self.executables: # @UnusedVariable + sources = build_info.get('sources') + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'executables' option (library '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % exe_name) + + filenames.extend(sources) + return filenames + + def substitute_sources(self,exe_name,sources): + return list(sources) + + def build_executables(self, executables): + for (exe_name, build_info) in executables: + sources = build_info.get('sources') + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'executables' option (library '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % exe_name) + + sources = self.substitute_sources(exe_name,sources) + + log.info("building '%s' program", exe_name) + + # First, compile the source code to object files in the library + # directory. (This should probably change to putting object + # files in a temporary build directory.) + macros = build_info.get('macros') + include_dirs = build_info.get('include_dirs') + extra_args = self.extra_compile_args or [] + + objects = self.compiler.compile(sources, + output_dir=self.build_temp, + macros=macros, + include_dirs=include_dirs, + extra_postargs=extra_args, + debug=self.debug) + + # Now "link" the object files together into a static library. + # (On Unix at least, this isn't really linking -- it just + # builds an archive. Whatever.) + self.compiler.link_executable(objects, exe_name, + output_dir=self.build_cexe, + debug=self.debug) + diff --git a/distutils.ext/obidistutils/command/build_ext.py b/distutils.ext/obidistutils/command/build_ext.py new file mode 100644 index 0000000..5bf7665 --- /dev/null +++ b/distutils.ext/obidistutils/command/build_ext.py @@ -0,0 +1,93 @@ +''' +Created on 13 fevr. 2014 + +@author: coissac +''' + +from distutils import log +import os + +from Cython.Distutils import build_ext as ori_build_ext # @UnresolvedImport + +from distutils.errors import DistutilsSetupError + +class build_ext(ori_build_ext): + def modifyDocScripts(self): + build_dir_file=open("doc/sphinx/build_dir.txt","w") + print(self.build_lib,file=build_dir_file) + build_dir_file.close() + + def initialize_options(self): + ori_build_ext.initialize_options(self) # @UndefinedVariable + self.littlebigman = None + self.built_files = None + + + def finalize_options(self): + ori_build_ext.finalize_options(self) # @UndefinedVariable + + self.set_undefined_options('littlebigman', + ('littlebigman', 'littlebigman')) + + self.set_undefined_options('build_files', + ('files', 'built_files')) + + self.cython_c_in_temp = 1 + + if self.littlebigman =='-DLITTLE_END': + if self.define is None: + self.define=[('LITTLE_END',None)] + else: + self.define.append('LITTLE_END',None) + + def substitute_sources(self,exe_name,sources): + """ + Substitutes source file name starting by an @ by the actual + name of the built file (see --> build_files) + """ + sources = list(sources) + for i in range(len(sources)): + message = "%s :-> %s" % (exe_name,sources[i]) + if sources[i][0]=='@': + try: + filename = self.built_files[sources[i][1:]] + except KeyError: + tmpfilename = os.path.join(self.build_temp,sources[i][1:]) + if os.path.isfile (tmpfilename): + filename = tmpfilename + else: + raise DistutilsSetupError( + 'The %s filename declared in the source ' + 'files of the program %s have not been ' + 'built by the installation process' % (sources[i], + exe_name)) + sources[i]=filename + log.info("%s changed to %s",message,filename) + else: + log.info("%s ok",message) + + return sources + + def build_extensions(self): + # First, sanity-check the 'extensions' list + + for ext in self.extensions: + ext.sources = self.substitute_sources(ext.name,ext.sources) + + self.check_extensions_list(self.extensions) + + for ext in self.extensions: + log.info("%s :-> %s",ext.name,ext.sources) + ext.sources = self.cython_sources(ext.sources, ext) + self.build_extension(ext) + + + def run(self): + self.modifyDocScripts() + ori_build_ext.run(self) # @UndefinedVariable + + + + + + \ No newline at end of file diff --git a/distutils.ext/obidistutils/command/build_files.py b/distutils.ext/obidistutils/command/build_files.py new file mode 100644 index 0000000..2adafef --- /dev/null +++ b/distutils.ext/obidistutils/command/build_files.py @@ -0,0 +1,53 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + +import os.path + +from distutils.core import Command +from distutils import log + +class build_files(Command): + + def initialize_options(self): + self.files=None + self.ctools=None + self.build_temp=None + self.build_cexe=None + + def finalize_options(self): + + self.set_undefined_options('build_ctools', + ('ctools', 'ctools'), + ('build_temp','build_temp'), + ('build_cexe','build_cexe'), + ) + + self.files = {} + + def run(self): + + for dest,prog,command in self.distribution.files: + destfile = os.path.join(self.build_temp,dest) + if prog in self.ctools: + progfile = os.path.join(self.build_cexe,prog) + else: + progfile = prog + + log.info("Building file : %s" % dest) + + commandline = command % {'prog' : progfile, + 'dest' : destfile} + + log.info(" --> %s" % commandline) + + os.system(commandline) + self.files[dest]=destfile + + log.info("Done.\n") + + + + diff --git a/distutils.ext/obidistutils/command/build_scripts.py b/distutils.ext/obidistutils/command/build_scripts.py new file mode 100644 index 0000000..68a4feb --- /dev/null +++ b/distutils.ext/obidistutils/command/build_scripts.py @@ -0,0 +1,104 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + +import os.path + +from distutils.command.build_scripts import build_scripts as ori_build_scripts,\ + first_line_re +from distutils.util import convert_path +from distutils import log, sysconfig +from distutils.dep_util import newer +from stat import ST_MODE + + + +class build_scripts(ori_build_scripts): + + def copy_scripts (self): + """Copy each script listed in 'self.scripts'; if it's marked as a + Python script in the Unix way (first line matches 'first_line_re', + ie. starts with "\#!" and contains "python"), then adjust the first + line to refer to the current Python interpreter as we copy. + """ + self.mkpath(self.build_dir) + rawbuild_dir = os.path.join(os.path.dirname(self.build_dir),'raw_scripts') + self.mkpath(rawbuild_dir) + + outfiles = [] + for script in self.scripts: + adjust = 0 + script = convert_path(script) + outfile = os.path.join(self.build_dir, os.path.splitext(os.path.basename(script))[0]) + rawoutfile = os.path.join(rawbuild_dir, os.path.basename(script)) + outfiles.append(outfile) + + if not self.force and not newer(script, outfile): + log.debug("not copying %s (up-to-date)", script) + continue + + # Always open the file but ignore failures in dry-run mode -- + # that way, we'll get accurate feedback if we can read the + # script. + try: + f = open(script, "r") + except IOError: + if not self.dry_run: + raise + f = None + else: + first_line = f.readline() + if not first_line: + self.warn("%s is an empty file (skipping)" % script) + continue + + match = first_line_re.match(first_line) + if match: + adjust = 1 + post_interp = match.group(1) or '' + + log.info("Store the raw script %s -> %s", script,rawoutfile) + self.copy_file(script, rawoutfile) + + + if adjust: + log.info("copying and adjusting %s -> %s", script, + self.build_dir) + if not self.dry_run: + outf = open(outfile, "w") + if not sysconfig.python_build: + outf.write("#!%s%s\n" % + (self.executable, + post_interp)) + else: + outf.write("#!%s%s\n" % + (os.path.join( + sysconfig.get_config_var("BINDIR"), + "python%s%s" % (sysconfig.get_config_var("VERSION"), + sysconfig.get_config_var("EXE"))), + post_interp)) + outf.writelines(f.readlines()) + outf.close() + if f: + f.close() + else: + if f: + f.close() + self.copy_file(script, outfile) + + if os.name == 'posix': + for F in outfiles: + if self.dry_run: + log.info("changing mode of %s", F) + else: + oldmode = os.stat(F)[ST_MODE] + oldmode = oldmode & 0o7777 + + newmode = (oldmode | 0o555) & 0o7777 + if newmode != oldmode: + log.info("changing mode of %s from %o to %o", + F, oldmode, newmode) + os.chmod(F, newmode) + diff --git a/distutils.ext/obidistutils/command/build_sphinx.py b/distutils.ext/obidistutils/command/build_sphinx.py new file mode 100644 index 0000000..48a4402 --- /dev/null +++ b/distutils.ext/obidistutils/command/build_sphinx.py @@ -0,0 +1,26 @@ +''' +Created on 10 mars 2015 + +@author: coissac +''' + +from sphinx.setup_command import BuildDoc as ori_build_sphinx # @UnresolvedImport + +class build_sphinx(ori_build_sphinx): + ''' + Build Sphinx documentation in html, epub and man formats + ''' + + description = __doc__ + + def run(self): + self.builder='html' + self.finalize_options() + ori_build_sphinx.run(self) + self.builder='epub' + self.finalize_options() + ori_build_sphinx.run(self) + self.builder='man' + self.finalize_options() + ori_build_sphinx.run(self) + \ No newline at end of file diff --git a/distutils.ext/obidistutils/command/install.py b/distutils.ext/obidistutils/command/install.py new file mode 100644 index 0000000..23641b0 --- /dev/null +++ b/distutils.ext/obidistutils/command/install.py @@ -0,0 +1,19 @@ +''' +Created on 6 oct. 2014 + +@author: coissac +''' + +try: + from setuptools.command.install import install as install_ori + has_setuptools=True +except ImportError: + from distutils.command.install import install as install_ori + has_setuptools=False + +class install(install_ori): + + def __init__(self,dist): + install_ori.__init__(self, dist) + self.sub_commands.insert(0, ('build',lambda self: True)) + self.sub_commands.append(('install_sphinx',lambda self: self.distribution.serenity)) diff --git a/distutils.ext/obidistutils/command/install_scripts.py b/distutils.ext/obidistutils/command/install_scripts.py new file mode 100644 index 0000000..50b03fd --- /dev/null +++ b/distutils.ext/obidistutils/command/install_scripts.py @@ -0,0 +1,43 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' +from distutils.command.install_scripts import install_scripts as ori_install_scripts + +import os.path +from distutils import log + +class install_scripts(ori_install_scripts): + + def initialize_options(self): + ori_install_scripts.initialize_options(self) + self.public_dir = None + + + def install_public_link(self): + self.mkpath(self.public_dir) + for file in self.get_outputs(): + if self.dry_run: + log.info("changing mode of %s", file) + else: + log.info("exporting file %s -> %s", file,os.path.join(self.public_dir, + os.path.split(file)[1] + )) + dest = os.path.join(self.public_dir, + os.path.split(file)[1] + ) + if os.path.exists(dest): + os.unlink(dest) + os.symlink(file,dest) + + + + def run(self): + ori_install_scripts.run(self) + if self.distribution.serenity: + self.public_dir=os.path.join(self.install_dir,"../export/bin") + self.public_dir=os.path.abspath(self.public_dir) + self.install_public_link() + + diff --git a/distutils.ext/obidistutils/command/install_sphinx.py b/distutils.ext/obidistutils/command/install_sphinx.py new file mode 100644 index 0000000..1c631d9 --- /dev/null +++ b/distutils.ext/obidistutils/command/install_sphinx.py @@ -0,0 +1,46 @@ +''' +Created on 10 mars 2015 + +@author: coissac +''' +from distutils.core import Command +import os.path +import glob + +class install_sphinx(Command): + ''' + Install the sphinx documentation + ''' + + description = "Install the sphinx documentation in serenity mode" + + boolean_options = ['force', 'skip-build'] + + + def initialize_options (self): + self.install_doc = None + self.build_dir = None + + def finalize_options (self): + self.set_undefined_options('build_sphinx', ('build_dir', 'build_dir')) + self.set_undefined_options('install', + ('install_scripts', 'install_doc')) + + def run (self): + if self.distribution.serenity: + self.install_doc = os.path.join(self.install_doc,"../export/share") + self.install_doc=os.path.abspath(self.install_doc) + self.mkpath(self.install_doc) + self.mkpath(os.path.join(self.install_doc,'html')) + outfiles = self.copy_tree(os.path.join(self.build_dir,'html'), # @UnusedVariable + os.path.join(self.install_doc,'html')) + + self.mkpath(os.path.join(self.install_doc,'man','man1')) + outfiles = self.copy_tree(os.path.join(self.build_dir,'man'), # @UnusedVariable + os.path.join(self.install_doc,'man','man1')) + + for epub in glob.glob(os.path.join(self.build_dir,'epub/*.epub')): + self.copy_file(os.path.join(epub), + os.path.join(self.install_doc,os.path.split(epub)[1])) + + \ No newline at end of file diff --git a/distutils.ext/obidistutils/command/littlebigman.py b/distutils.ext/obidistutils/command/littlebigman.py new file mode 100644 index 0000000..572ecf6 --- /dev/null +++ b/distutils.ext/obidistutils/command/littlebigman.py @@ -0,0 +1,59 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + +import os + +from obidistutils.command.build_exe import build_exe +from distutils import log + +import subprocess + +class littlebigman(build_exe): + + description = "build the littlebigman executable testing endianness of the CPU" + + + def initialize_options(self): + build_exe.initialize_options(self) + + self.littlebigman = None + + + def finalize_options(self): + # This might be confusing: both build-cexe and build-temp default + # to build-temp as defined by the "build" command. This is because + # I think that C libraries are really just temporary build + # by-products, at least from the point of view of building Python + # extensions -- but I want to keep my options open. + + build_exe.finalize_options(self) + + self.set_undefined_options('build', + ('build_temp', 'build_cexe')) + + # self.ctools = self.distribution.ctools + + if os.path.isfile("distutils.ext/src/littlebigman.c"): + self.executables = [('littlebigman',{"sources":["distutils.ext/src/littlebigman.c"]})] + self.check_executable_list(self.executables) + else: + self.executables = [] + + + def run_littlebigman(self): + p = subprocess.Popen("'%s'" % os.path.join(self.build_temp, + 'littlebigman'), + shell=True, + stdout=subprocess.PIPE) + little = p.communicate()[0] + return little + + def run(self): + build_exe.run(self) + self.littlebigman=self.run_littlebigman() + log.info("Your CPU is in mode : %s" % self.littlebigman) + + \ No newline at end of file diff --git a/distutils.ext/obidistutils/command/pidname.py b/distutils.ext/obidistutils/command/pidname.py new file mode 100644 index 0000000..327af8a --- /dev/null +++ b/distutils.ext/obidistutils/command/pidname.py @@ -0,0 +1,51 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + +import os + +from obidistutils.command.build_exe import build_exe +from obidistutils.serenity.checksystem import is_mac_system + + +class pidname(build_exe): + + description = "build the pidname executable returning the executable path from a PID on a mac" + + + def initialize_options(self): + build_exe.initialize_options(self) + + self.pidname = False + + + def finalize_options(self): + # This might be confusing: both build-cexe and build-temp default + # to build-temp as defined by the "build" command. This is because + # I think that C libraries are really just temporary build + # by-products, at least from the point of view of building Python + # extensions -- but I want to keep my options open. + + build_exe.finalize_options(self) + + self.set_undefined_options('build', + ('build_scripts', 'build_cexe')) + + # self.ctools = self.distribution.ctools + + if os.path.isfile("distutils.ext/src/pidname.c"): + self.executables = [('pidname',{"sources":["distutils.ext/src/pidname.c"]})] + self.check_executable_list(self.executables) + else: + self.executables = [] + + + def run(self): + if is_mac_system(): + build_exe.run(self) + self.pidname=True + else: + self.pidname=False + \ No newline at end of file diff --git a/distutils.ext/obidistutils/command/sdist.py b/distutils.ext/obidistutils/command/sdist.py new file mode 100644 index 0000000..9293c86 --- /dev/null +++ b/distutils.ext/obidistutils/command/sdist.py @@ -0,0 +1,42 @@ +''' +Created on 10 mars 2015 + +@author: coissac +''' + +import os.path + +from distutils.command.sdist import sdist as orig_sdist +from distutils import dir_util + +class sdist(orig_sdist): + + def make_distribution(self): + """Create the source distribution(s). First, we create the release + tree with 'make_release_tree()'; then, we create all required + archive files (according to 'self.formats') from the release tree. + Finally, we clean up by blowing away the release tree (unless + 'self.keep_temp' is true). The list of archive files created is + stored so it can be retrieved later by 'get_archive_files()'. + """ + # Don't warn about missing meta-data here -- should be (and is!) + # done elsewhere. + base_dir = self.distribution.get_fullname() + base_name = os.path.join(self.dist_dir,base_dir) + + self.make_release_tree(os.path.join('tmp',base_dir), self.filelist.files) + archive_files = [] # remember names of files we create + # tar archive must be created last to avoid overwrite and remove + if 'tar' in self.formats: + self.formats.append(self.formats.pop(self.formats.index('tar'))) + + for fmt in self.formats: + file = self.make_archive(base_name, fmt, root_dir='tmp',base_dir=base_dir, + owner=self.owner, group=self.group) + archive_files.append(file) + self.distribution.dist_files.append(('sdist', '', file)) + + self.archive_files = archive_files + + if not self.keep_temp: + dir_util.remove_tree(os.path.join('tmp',base_dir), dry_run=self.dry_run) diff --git a/distutils.ext/obidistutils/core.py b/distutils.ext/obidistutils/core.py new file mode 100644 index 0000000..beb7d65 --- /dev/null +++ b/distutils.ext/obidistutils/core.py @@ -0,0 +1,170 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + +from os import path +import os.path +import glob +import sys + + +from distutils.core import setup as ori_setup +from distutils.extension import Extension + +from obidistutils.serenity.checkpackage import install_requirements,\ + check_requirements, \ + RequirementError + +from obidistutils.serenity.rerun import enforce_good_python +from obidistutils.serenity.rerun import rerun_with_anothe_python +from distutils import log + +from obidistutils.dist import Distribution + +from obidistutils.command.build import build +from obidistutils.command.littlebigman import littlebigman +from obidistutils.command.build_cexe import build_cexe +from obidistutils.command.build_sphinx import build_sphinx +from obidistutils.command import build_ext +from obidistutils.command.build_ctools import build_ctools +from obidistutils.command.build_files import build_files +from obidistutils.command.build_scripts import build_scripts +from obidistutils.command.install_scripts import install_scripts +from obidistutils.command.install_sphinx import install_sphinx +from obidistutils.command.install import install +from obidistutils.command.pidname import pidname +from obidistutils.command.sdist import sdist + + + +def findPackage(root,base=None): + modules=[] + if base is None: + base=[] + for module in (path.basename(path.dirname(x)) + for x in glob.glob(path.join(root,'*','__init__.py'))): + modules.append('.'.join(base+[module])) + modules.extend(findPackage(path.join(root,module),base+[module])) + return modules + +def findCython(root,base=None,pyrexs=None): + setupdir = os.path.dirname(sys.argv[0]) + pyrexs=[] + + if base is None: + base=[] + for module in (path.basename(path.dirname(x)) + for x in glob.glob(path.join(root,'*','__init__.py'))): + + + for pyrex in glob.glob(path.join(root,module,'*.pyx')): + pyrexs.append(Extension('.'.join(base+[module,path.splitext(path.basename(pyrex))[0]]), + [pyrex] + ) + ) + try: + cfiles = os.path.splitext(pyrex)[0]+".cfiles" + cfilesdir = os.path.dirname(cfiles) + cfiles = open(cfiles) + cfiles = [os.path.relpath(os.path.join(cfilesdir,y),setupdir).strip() + if y[0] !='@' else y.strip() + for y in cfiles] + + log.info("Cython module : %s",cfiles) + incdir = set(os.path.dirname(x) for x in cfiles if x[-2:]==".h") + cfiles = [x for x in cfiles if x[-2:]==".c"] + pyrexs[-1].sources.extend(cfiles) + pyrexs[-1].include_dirs.extend(incdir) + pyrexs[-1].extra_compile_args.extend(['-msse2']) + + except IOError: + pass + + pyrexs.extend(findCython(path.join(root,module),base+[module])) + return pyrexs + + +def rootname(x): + return os.path.splitext(x.sources[0])[0] + +COMMANDS = {'build':build, + 'littlebigman':littlebigman, + 'pidname':pidname, + 'build_ctools':build_ctools, + 'build_files':build_files, + 'build_cexe':build_cexe, + 'build_ext': build_ext, + 'build_scripts':build_scripts, + 'build_sphinx':build_sphinx, + 'install_scripts':install_scripts, + 'install_sphinx':install_sphinx, + 'install':install, + 'sdist':sdist} + + +CTOOLS =[] +CEXES =[] +FILES =[] + +def setup(**attrs): + + minversion = attrs.get("PYTHONMIN",'3.4') + maxversion = attrs.get('PYTHONMAX',None) + fork = attrs.get('FORK',False) + requirementfile = attrs.get('REQUIREMENTS','requirements.txt') + + enforce_good_python(minversion, maxversion, fork) + + if (install_requirements(requirementfile)): + rerun_with_anothe_python(sys.executable,minversion,maxversion,fork) + + try: + check_requirements(requirementfile) + except RequirementError as e : + log.error(e) + sys.exit(1) + + if 'distclass' not in attrs: + attrs['distclass']=Distribution + + if 'python_src' not in attrs: + SRC = 'python' + else: + SRC = attrs['python_src'] + del(attrs['python_src']) + + if 'scripts' not in attrs: + attrs['scripts'] = glob.glob('%s/*.py' % SRC) + + if 'package_dir' not in attrs: + attrs['package_dir'] = {'': SRC} + + if 'packages' not in attrs: + attrs['packages'] = findPackage(SRC) + + if 'cmdclass' not in attrs: + attrs['cmdclass'] = COMMANDS + + if 'ctools' not in attrs: + attrs['ctools'] = CTOOLS + + if 'executables' not in attrs: + attrs['executables'] = CEXES + + if 'files' not in attrs: + attrs['files'] = FILES + + if 'sse' not in attrs: + attrs['sse']=None + + if 'serenity' not in attrs: + attrs['serenity']=False + + EXTENTION=findCython(SRC) + + if 'ext_modules' not in attrs: + attrs['ext_modules'] = EXTENTION + + ori_setup(**attrs) diff --git a/distutils.ext/obidistutils/dist.py b/distutils.ext/obidistutils/dist.py new file mode 100644 index 0000000..39c30cd --- /dev/null +++ b/distutils.ext/obidistutils/dist.py @@ -0,0 +1,45 @@ +''' +Created on 20 oct. 2012 + +@author: coissac +''' + +from distutils.dist import Distribution as ori_Distribution + +class Distribution(ori_Distribution): + + def __init__(self,attrs=None): + self.executables = None + self.ctools = None + self.files = None + self.build_cexe = None + self.deprecated_scripts = None + self.zip_safe=False + self.sse = None + self.serenity=attrs['serenity'] + + ori_Distribution.__init__(self, attrs) + + self.global_options.insert(0,('serenity', None, "install or build the package in a python virtualenv " + "without polluting the installed python and with many " + "checks during the installation process" + )) + self.global_options.insert(0,('virtualenv', None, "if the installation is done using the serenity mode " + "this option allows for specifying the virtualenv name. " + "By default the name is PACKAGE-VERSION" + )) + + + def has_executables(self): + return self.executables is not None and self.executables + + def has_ctools(self): + return self.ctools is not None and self.ctools + + def has_files(self): + return self.files is not None and self.files + + def has_deprecated_scripts(self): + return self.deprecated_scripts is not None and self.deprecated_scripts + + \ No newline at end of file diff --git a/distutils.ext/obidistutils/serenity/__init__.py b/distutils.ext/obidistutils/serenity/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/distutils.ext/obidistutils/serenity/checkpackage.py b/distutils.ext/obidistutils/serenity/checkpackage.py new file mode 100644 index 0000000..4727433 --- /dev/null +++ b/distutils.ext/obidistutils/serenity/checkpackage.py @@ -0,0 +1,156 @@ +''' +Created on 2 oct. 2014 + +@author: coissac +''' + +import re +import os + +import pip # @UnresolvedImport +from pip.utils import get_installed_distributions # @UnresolvedImport +from distutils.version import StrictVersion # @UnusedImport +from distutils.errors import DistutilsError +from distutils import log + +class RequirementError(Exception): + pass + +def is_installed(requirement): + + + requirement_project,requirement_relation,requirement_version = parse_package_requirement(requirement) + + package = [x for x in get_installed_distributions() if x.project_name==requirement_project] + + if len(package)==1: + if requirement_version is not None and requirement_relation is not None: + rep = (len(package)==1) and eval("StrictVersion('%s') %s StrictVersion('%s')" % (package[0].version, + requirement_relation, + requirement_version) + ) + else: + rep=True + else: + rep=False + + if rep: + if requirement_version is not None and requirement_relation is not None: + log.info("Look for package %s (%s%s) : ok version %s installed" % (requirement_project, + requirement_relation, + requirement_version, + package[0].version)) + else: + log.info("Look for package %s : ok version %s installed" % (requirement_project, + package[0].version)) + else: + if len(package)!=1: + log.info("Look for package %s (%s%s) : not installed" % (requirement_project, + requirement_relation, + requirement_version)) + else: + log.info("Look for package %s (%s%s) : failed only version %s installed" % (requirement_project, + requirement_relation, + requirement_version, + package[0].version)) + + return rep + + +def get_requirements(requirementfile='requirements.txt'): + + try: + requirements = open(requirementfile).readlines() + requirements = [x.strip() for x in requirements] + requirements = [x for x in requirements if x[0]!='-'] + + except IOError: + requirements = [] + + return requirements + + +def install_requirements(requirementfile='requirements.txt'): + + install_something=False + + requirements = get_requirements(requirementfile) + + log.info("Required packages for the installation :") + for x in requirements: + ok = is_installed(x) + if not ok: + log.info(" Installing requirement : %s" % x) + pip_install_package(x) + install_something=True + + return install_something + + +def check_requirements(requirementfile='requirements.txt'): + + requirements = get_requirements(requirementfile) + + log.info("Required packages for the installation :") + for x in requirements: + ok = is_installed(x) + if not ok: + raise RequirementError(" Missing requirement : %s -- Package installation stopped" % x) + + + + +def parse_package_requirement(requirement): + + version_pattern = re.compile('[=><]+(.*)$') + project_pattern = re.compile('[^=><]+') + relationship_pattern = re.compile('[=><]+') + + try: + requirement_project = project_pattern.search(requirement).group(0) + requirement_version = version_pattern.search(requirement) + if requirement_version is not None: + requirement_version=requirement_version.group(1) + requirement_relation= relationship_pattern.search(requirement) + if requirement_relation is not None: + requirement_relation=requirement_relation.group(0) + except: + raise DistutilsError("Requirement : %s not correctly formated" % requirement) + + return requirement_project,requirement_relation,requirement_version + + +def get_package_requirement(package,requirementfile='requirements.txt'): + requirements = get_requirements(requirementfile) + req = [x for x in requirements + if x[0:len(package)]==package + ] + + if len(req)==1: + return req[0] + else: + return None + + +def pip_install_package(package,directory=None,upgrade=True): + + log.info('installing %s in directory %s' % (package,str(directory))) + + if 'http_proxy' in os.environ and 'https_proxy' not in os.environ: + os.environ['https_proxy']=os.environ['http_proxy'] + + args = ['install'] + + if upgrade: + args.append('--upgrade') + + if 'http_proxy' in os.environ: + args.append('--proxy=%s' % os.environ['http_proxy']) + + if directory is not None: + args.append('--target=%s' % directory) + + args.append(package) + + return pip.main(args) + diff --git a/distutils.ext/obidistutils/serenity/checkpython.py b/distutils.ext/obidistutils/serenity/checkpython.py new file mode 100644 index 0000000..f1a5afe --- /dev/null +++ b/distutils.ext/obidistutils/serenity/checkpython.py @@ -0,0 +1,79 @@ +''' +Created on 24 mai 2015 + +@author: coissac +''' +from distutils.version import StrictVersion +from distutils import sysconfig +import subprocess +import os +import glob +import re + +from obidistutils.serenity.checksystem import is_windows_system + + +def is_python_version(path=None,minversion='3.4',maxversion=None): + ''' + Checks that the python version is in the range {minversion,maxversion[ + + @param path: if None consider the running python + otherwise the python pointed by the path + @param minversion: the minimum version to consider + @param maxversion: the maximum version to consider (strictly inferior to) + + @return: True if the python version match + @rtype: bool + ''' + if path is None: + pythonversion = StrictVersion(sysconfig.get_python_version()) + else: + command = """'%s' -c 'from distutils import sysconfig; """ \ + """print(sysconfig.get_python_version())'""" % path + + p = subprocess.Popen(command, + shell=True, + stdout=subprocess.PIPE) + pythonversion=str(p.communicate()[0],'utf8').strip() + pythonversion = StrictVersion(pythonversion) + + return ( pythonversion >=StrictVersion(minversion) + and ( maxversion is None + or pythonversion < StrictVersion(maxversion)) + ) + + +def lookfor_good_python(minversion='3.4',maxversion=None,followLink=False): + ''' + Look for all python interpreters present in the system path that + match the version constraints. + + @param minversion: the minimum version to consider + @param maxversion: the maximum version to consider (strictly inferior to) + @param followLink: a boolean value indicating if link must be substituted + by their real path. + + @return: a list of path to interpreters + ''' + exe = [] + if not is_windows_system(): + paths = os.environ['PATH'].split(os.pathsep) + for p in paths: + candidates = glob.glob(os.path.join(p,'python*')) + pexe = [] + pythonpat=re.compile('python([0-9]|[0-9]\.[0-9])?$') + for e in candidates: + print(e) + if pythonpat.search(e) is not None: + if followLink and os.path.islink(e): + e = os.path.realpath(e) + if (os.path.isfile(e) and + os.access(e, os.X_OK) and + is_python_version(e,minversion,maxversion)): + pexe.append(e) + exe.extend(set(pexe)) + + return exe + + + diff --git a/distutils.ext/obidistutils/serenity/checksystem.py b/distutils.ext/obidistutils/serenity/checksystem.py new file mode 100644 index 0000000..511ffca --- /dev/null +++ b/distutils.ext/obidistutils/serenity/checksystem.py @@ -0,0 +1,18 @@ +''' +Created on 24 mai 2015 + +@author: coissac +''' + +from distutils import util + +def is_mac_system(): + platform = util.get_platform().split('-')[0] + + return platform=='macosx' + +def is_windows_system(): + platform = util.get_platform().split('-')[0] + + return platform=='Windows' + \ No newline at end of file diff --git a/distutils.ext/obidistutils/serenity/globals.py b/distutils.ext/obidistutils/serenity/globals.py new file mode 100644 index 0000000..0185b8b --- /dev/null +++ b/distutils.ext/obidistutils/serenity/globals.py @@ -0,0 +1,14 @@ +''' +Created on 24 mai 2015 + +@author: coissac +''' + + +saved_args=[] +tmpdir=[] +local_pip=[] +local_virtualenv=[] +local_cython=[] +local_serenity=[] + \ No newline at end of file diff --git a/distutils.ext/obidistutils/serenity/rerun.py b/distutils.ext/obidistutils/serenity/rerun.py new file mode 100644 index 0000000..1d334ad --- /dev/null +++ b/distutils.ext/obidistutils/serenity/rerun.py @@ -0,0 +1,59 @@ +''' +Created on 24 mai 2015 + +@author: coissac +''' + +import sys +import os +from distutils import log +from distutils.errors import DistutilsError + + +from obidistutils.serenity.globals import saved_args +from obidistutils.serenity.checkpython import is_python_version,\ + lookfor_good_python + + +def rerun_with_anothe_python(path, minversion='3.4',maxversion=None, fork=False): + + if saved_args: + args = saved_args + else: + args = list(sys.argv) + + + assert is_python_version(path,minversion,maxversion), \ + 'the selected python is not adapted to the installation of this package' + + args.insert(0, path) + + sys.stderr.flush() + sys.stdout.flush() + + if fork: + log.info('Forking a new install process') + os.system(' '.join(list(args))) + log.info('External process ended') + sys.exit(0) + else: + os.execv(path,list(args)) + +def enforce_good_python(minversion='3.4',maxversion=None, fork=False): + if is_python_version(minversion=minversion,maxversion=maxversion): + return True + + goodpython = lookfor_good_python(minversion,maxversion) + + if not goodpython: + raise DistutilsError('No good python identified on your system') + + goodpython=goodpython[0] + + log.warn("========================================") + log.warn("") + log.warn(" Switching to python : %s" % goodpython) + log.warn("") + log.warn("========================================") + + rerun_with_anothe_python(goodpython) diff --git a/distutils.ext/obidistutils/serenity/snake.py b/distutils.ext/obidistutils/serenity/snake.py new file mode 100644 index 0000000..79c1f39 --- /dev/null +++ b/distutils.ext/obidistutils/serenity/snake.py @@ -0,0 +1,35 @@ +''' +Created on 2 oct. 2014 + +@author: coissac +''' + +snake =""" + + ___ + ,'._,`. + (-.___.-) + (-.___.-) + `-.___.-' + (( @ @| . __ + \ ` | ,\ |`. @| | | _.-._ + __`.`=-=mm===mm:: | | |`. | | | ,'=` '=`. + ( `-'|:/ /:/ `/ @| | | |, @| @| /---)W(---\ + \ \ / / / / @| | ' (----| |----) ,~ + |\ \ / /| / / @| \---| |---/ | + | \ V /||/ / `.-| |-,' | + | `-' |V / \| |/ @' + | , |-' __| |__ + | .;: _,-. ,--""..| |..""--. + ;;:::' " ) (`--::__|_|__::--') + ,-" _, / \`--...___...--'/ + ( -:--'/ / /`--...___...--'\ + "-._ `"'._/ /`---...___...---'\ + "-._ "---. (`---....___....---') + .' ",._ ,' ) |`---....___....---'| + /`._| `| | (`---....___....---') + ( \ | / \`---...___...---'/ + `. `, ^"" `:--...___...--;' + `.,' hh `-._______.-' + +""" \ No newline at end of file diff --git a/distutils.ext/src/littlebigman.c b/distutils.ext/src/littlebigman.c new file mode 100644 index 0000000..5e2ea2a --- /dev/null +++ b/distutils.ext/src/littlebigman.c @@ -0,0 +1,24 @@ +/* + * littlebigman.c + * + * Created on: 11 juil. 2012 + * Author: coissac + */ + +#include + +int main(int argc, char *argv[]) +{ + union { int entier; + char caractere[4] ; + } test; + + test.entier=0x01020304; + + if (test.caractere[3] == 1) + printf("-DLITTLE_END"); + else + printf("-DBIG_END"); + + return 0; +} diff --git a/distutils.ext/src/pidname.c b/distutils.ext/src/pidname.c new file mode 100644 index 0000000..ff61eb4 --- /dev/null +++ b/distutils.ext/src/pidname.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include + +int main (int argc, char* argv[]) +{ + pid_t pid; int ret; + char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; + + if ( argc > 1 ) { + pid = (pid_t) atoi(argv[1]); + ret = proc_pidpath (pid, pathbuf, sizeof(pathbuf)); + if ( ret <= 0 ) { + fprintf(stderr, "PID %d: proc_pidpath ();\n", pid); + fprintf(stderr, " %s\n", strerror(errno)); + } else { + printf("proc %d: %s\n", pid, pathbuf); + } + } + + return 0; +}