diff setup.py @ 1124:28e3eb3bb217

files reorganisation and installation rework: - files have been reorganised to follow other SàT projects and usual Python organisation (no more "/src" directory) - VERSION file is now used, as for other SàT projects - replace the overcomplicated setup.py be a more sane one. Pyjamas part is not compiled anymore by setup.py, it must be done separatly - removed check for data_dir if it's empty - installation tested working in virtual env - libervia launching script is now in bin/libervia
author Goffi <goffi@goffi.org>
date Sat, 25 Aug 2018 17:59:48 +0200
parents 6d6c0694f72a
children b251c8bb6776
line wrap: on
line diff
--- a/setup.py	Sat Aug 11 18:35:37 2018 +0200
+++ b/setup.py	Sat Aug 25 17:59:48 2018 +0200
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # Libervia: a Salut à Toi frontend
-# Copyright (C) 2011-2016  Jérôme Poisson (goffi@goffi.org)
+# Copyright (C) 2011-2018  Jérôme Poisson (goffi@goffi.org)
 # Copyright (C) 2013-2016 Adrien Cossa (souliane@mailoo.org)
 
 # This program is free software: you can redistribute it and/or modify
@@ -18,293 +18,74 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from ez_setup import use_setuptools
-use_setuptools()
-from setuptools.command.install import install
 from setuptools import setup
-from distutils.file_util import copy_file
 import os
-import sys
-import subprocess
-from stat import ST_MODE
-import shutil
-from src.server.constants import Const as C
-import tempfile
 
-# seen here: http://stackoverflow.com/questions/7275295
-try:
-    from setuptools.command import egg_info
-    egg_info.write_toplevel_names
-except (ImportError, AttributeError):
-    pass
-else:
-    def _top_level_package(name):
-        return name.split('.', 1)[0]
+NAME = "libervia"
 
-    def _hacked_write_toplevel_names(cmd, basename, filename):
-        pkgs = dict.fromkeys(
-            [_top_level_package(k)
-                for k in cmd.distribution.iter_distribution_names()
-                if _top_level_package(k) != "twisted"
-            ]
-        )
-        cmd.write_file("top-level names", filename, '\n'.join(pkgs) + '\n')
-
-    egg_info.write_toplevel_names = _hacked_write_toplevel_names
-
-
-NAME = 'libervia'
-LAUNCH_DAEMON_COMMAND = 'libervia'
+install_requires = [
+    "sat",
+    "sat-templates",
+    "twisted",
+    "txJSON-RPC==0.3.1",
+    "zope.interface",
+    "pyopenssl",
+    "jinja2>=2.9",
+    "shortuuid",
+    "autobahn",
+]
+long_description = u"""\
+Libervia is a web frontend for Salut à Toi (SàT), a multi-frontends and multi-purposes XMPP client.
+It features chat, blog, forums, events, tickets, merge requests, file sharing, photo albums, etc.
+It is also a decentralized, XMPP based web framework.
+"""
 
-ENV_LIBERVIA_INSTALL = "LIBERVIA_INSTALL"  # environment variable to customise installation
-JS_DEBUG = "jsdebug" # use debug mode with pyjsbuild
-NO_PREINSTALL_OPT = 'nopreinstall'  # skip all preinstallation checks
-AUTO_DEB_OPT = 'autodeb'  # automaticaly install debs
-CLEAN_OPT = 'clean'  # remove previous installation directories
-PURGE_OPT = 'purge'  # remove building and previous installation directories
-
-
-class MercurialException(Exception):
-    pass
-
-
-def module_installed(module_name):
-    """Try to import module_name, and return False if it failed
-    @param module_name: name of the module to test
-    @return: True if successful"""
-    try:
-        __import__(module_name)
-    except ImportError:
-        return False
-    return True
+with open(os.path.join(NAME, "VERSION")) as v:
+    VERSION = v.read().strip()
+is_dev_version = VERSION.endswith("D")
 
 
-class CustomInstall(install):
-
-    def custom_auto_options(self):
-        """Change options for twistd in the shell script
-        Mainly change the paths"""
-        sh_buffer = ""
-        with open(self.sh_script_path, 'r') as sh_file:
-            for ori_line in sh_file:
-                if ori_line.startswith('PLUGIN_OPTIONS='):
-                    dest_line = 'PLUGIN_OPTIONS="-d %s"\n' % self.install_data_dir
-                elif ori_line.startswith('PYTHON='):
-                    dest_line = 'PYTHON="%s"\n' % sys.executable
-                else:
-                    dest_line = ori_line
-                sh_buffer += dest_line
-
-        with open(self.sh_script_path, 'w') as sh_file:
-            sh_file.write(sh_buffer)
-
-    def custom_create_links(self):
-        """Create symbolic links to executables"""
-        # the script which launch the daemon
-        for source, dest in self.sh_script_links:
-            if os.path.islink(dest) and os.readlink(dest) != source:
-                os.remove(dest)  # copy_file doesn't force the link update
-            dest_name, copied = copy_file(source, dest, link='sym')
-            assert (copied)
-            # we change the perm in the same way as in the original install_scripts
-            mode = ((os.stat(dest_name)[ST_MODE]) | 0555) & 07777
-            os.chmod(dest_name, mode)
-
-    def pyjs_build(self):
-        """Build the browser side JS files from Python source."""
-        cwd = os.getcwd()
-        os.chdir(os.path.join('src', 'browser'))
-        # we must have only certain package in the path, so we create a tmp dir to link only what we need
-        tmp_dir = tempfile.mkdtemp()
-        import sat, sat_frontends
-        os.symlink(os.path.dirname(sat.__file__), os.path.join(tmp_dir,"sat")) # FIXME: only work on unixes
-        os.symlink(os.path.dirname(sat_frontends.__file__), os.path.join(tmp_dir,"sat_frontends")) # FIXME: only work on unixes
-        libervia_files = os.path.abspath("../../src")
-        os.symlink(libervia_files, os.path.join(tmp_dir,"libervia")) # FIXME: only work on unixes
-        for module in ('libervia_main', 'libervia_test'):
-            build_args = ['pyjsbuild', module] + (['-d'] if JS_DEBUG in install_opt else []) + ['--no-compile-inplace', '-I', tmp_dir, '-o', self.pyjamas_output_dir]
-            result = subprocess.call(build_args)
-            if result != 0:
-                continue
-        shutil.rmtree(tmp_dir)
-        os.chdir(cwd)
-        return result
-
-    def copy_data_files(self):
-        # XXX: To copy the JS files couldn't be done with the data_files parameter
-        # of setuptools.setup because all the files to be copied must exist before
-        # the call. Also, we need the value of self.install_lib to build the JS
-        # files (it's not easily predictable as it may vary from one system to
-        # another), so we can't call pyjsbuild before setuptools.setup.
-
-        html = os.path.join(self.install_data_dir, C.HTML_DIR)
-        if os.path.isdir(html):
-            shutil.rmtree(html, ignore_errors=True)
-        shutil.copytree(self.pyjamas_output_dir, html)
+def libervia_dev_version():
+    """Use mercurial data to compute version"""
 
-    def run(self):
-        self.sh_script_path = os.path.join(self.install_lib, NAME, 'libervia.sh')
-        self.sh_script_links = [(self.sh_script_path, os.path.join(self.install_scripts, LAUNCH_DAEMON_COMMAND))]
-        self.install_data_dir = os.path.join(self.install_data, 'share', NAME)
-        self.pyjamas_output_dir = os.path.join(os.getcwd(), 'html')
-        sys.stdout.write('running pre installation stuff\n')
-        sys.stdout.flush()
-        if PURGE_OPT in install_opt:
-            self.purge()
-        elif CLEAN_OPT in install_opt:
-            self.clean()
-        install.run(self)
-        sys.stdout.write('running post installation stuff\n')
-        sys.stdout.flush()
-        try:
-            build_result = self.pyjs_build()  # build after libervia.common is accessible
-        except OSError as e:
-            print "can't run pyjsbuild, are you sure pyjamas is installed?\nexception: {}".format(e)
-            return
-        if build_result == 127:  # TODO: remove magic string  # FIXME: seems useless as an OSError is raised if pyjsbuild is not accessible
-            print "pyjsbuild is not installed or not accessible from the PATH of user '%s'" % os.getenv('USERNAME')
-            return
-        if build_result != 0:
-            print "pyjsbuild failed to build libervia"
-            return
-        self.copy_data_files()
-        self.custom_auto_options()
-        if not "arch" in install_opt:
-            self.custom_create_links()
+    def version_scheme(version):
+        return VERSION.replace("D", ".dev0")
 
-    def confirm(self, message):
-        """Ask the user for a confirmation"""
-        message += 'Proceed'
-        while True:
-            res = raw_input("%s (y/n)? " % message)
-            if res not in ['y', 'Y', 'n', 'N']:
-                print "Your response ('%s') was not one of the expected responses: y, n" % res
-                message = 'Proceed'
-                continue
-            if res in ('y', 'Y'):
-                return True
-            return False
-
-    def clean(self, message=None, to_remove=None):
-        """Clean previous installation directories
+    def local_scheme(version):
+        return "+{rev}.{distance}".format(rev=version.node[1:], distance=version.distance)
 
-        @param message (str): to use a non-default confirmation message
-        @param to_remove (str): extra files/directories to remove
-        """
-        if message is None:
-            message = "Cleaning previous installation directories"
-        if to_remove is None:
-            to_remove = []
-        for path in [os.path.join(self.install_lib, NAME),
-                     self.install_data_dir,
-                     os.path.join(self.install_data, 'share', 'doc', NAME),
-                     os.path.join(self.install_lib, "%s.egg-info" % self.config_vars['dist_fullname']),
-                     os.path.join(self.install_lib, "%s-py%s.egg-info" % (self.config_vars['dist_fullname'], self.config_vars['py_version_short'])),
-                     ]:
-            if os.path.isdir(path):
-                to_remove.append(path)
-        for source, dest in self.sh_script_links:
-            if os.path.islink(dest):
-                to_remove.append(dest)
-        plugin_file = os.path.join(self.install_lib, 'twisted', 'plugins', NAME)
-        if os.path.isfile(plugin_file):
-            to_remove.append(plugin_file)
-
-        message = "%s:\n%s\n" % (message, "\n".join(["    %s" % path for path in to_remove]))
-        if not self.confirm(message):
-            return
-        sys.stdout.write('cleaning previous installation directories...\n')
-        sys.stdout.flush()
-        for path in to_remove:
-            if os.path.isdir(path):
-                shutil.rmtree(path, ignore_errors=True)
-            else:
-                os.remove(path)
-
-    def purge(self):
-        """Clean building and previous installation directories"""
-        message = "Cleaning building and previous installation directories"
-        to_remove = [os.path.join(os.getcwd(), 'build'), self.pyjamas_output_dir]
-        self.clean(message, to_remove)
+    return {"version_scheme": version_scheme, "local_scheme": local_scheme}
 
 
-def preinstall_check(install_opt):
-    """Check presence of problematic dependencies, and try to install them with package manager
-    This ugly stuff is necessary as distributions are not installed correctly with setuptools/distribute
-    Hope to remove this at some point"""
-
-    modules_tocheck = []  # if empty this method is dummy
-
-    package = {'twisted': 'python-twisted-core',
-               'twisted.words': 'python-twisted-words',
-               'twisted.web': 'python-twisted-web',
-               'mercurial': 'mercurial'}  # this dict map dependencies to packages names for debian distributions
-
-    sys.stdout.write("Running pre-installation dependencies check\n")
-
-    # which modules are not installed ?
-    modules_toinstall = [mod for mod in modules_tocheck if not module_installed(mod)]
-    """# is mercurial available ?
-    hg_installed = subprocess.call('which hg', stdout=open('/dev/null', 'w'), shell=True) == 0
-    if not hg_installed:
-        modules_toinstall.append('mercurial')"""  # hg can be installed from pypi
-
-    if modules_toinstall:
-        if AUTO_DEB_OPT in install_opt:  # auto debian installation is requested
-            # are we on a distribution using apt ?
-            apt_path = subprocess.Popen('which apt-get', stdout=subprocess.PIPE, shell=True).communicate()[0][:-1]
-        else:
-            apt_path = None
-
-        not_installed = set()
-        if apt_path:
-            # we have apt, we'll try to use it
-            for module_name in modules_toinstall:
-                package_name = package[module_name]
-                sys.stdout.write("Installing %s\n" % package_name)
-                success = subprocess.call('%s -qy install %s' % (apt_path, package_name), shell=True) == 0
-                if not success:
-                    not_installed.add(module_name)
-        else:
-            not_installed = set(modules_toinstall)
-
-        if not_installed:
-            # some packages can't be automatically installed, we print their name for manual installation
-            sys.stdout.write("You should install the following dependencies with your distribution recommanded tool before installing %s:\n" % NAME)
-            for module_name in not_installed:
-                sys.stdout.write("- %s (Debian name: %s)\n" % (module_name, package[module_name]))
-            sys.exit(2)
-
-
-if sys.argv[1].lower() in ['egg_info', 'install']:
-    # we only check dependencies if egg_info or install is used
-    install_opt = os.environ.get(ENV_LIBERVIA_INSTALL, "").split()
-    if not NO_PREINSTALL_OPT in install_opt:  # user can force preinstall skipping
-        preinstall_check(install_opt)
-
-setup(name=NAME,
-      version='0.7.0a2.post1',
-      description=u'Web frontend for Salut à Toi',
-      long_description=u'Libervia is a web frontend for Salut à Toi (SàT), a multi-frontends and multi-purposes XMPP client.',
-      author='Association « Salut à Toi »',
-      author_email='contact@goffi.org',
-      url='http://www.salut-a-toi.org',
-      classifiers=['Development Status :: 3 - Alpha',
-                   'Environment :: Web Environment',
-                   'Framework :: Twisted',
-                   'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
-                   'Operating System :: POSIX :: Linux',
-                   'Topic :: Communications :: Chat'],
-      package_dir={'libervia': 'src', 'twisted.plugins': 'src/twisted/plugins'},
-      packages=['libervia', 'libervia.common', 'libervia.server', 'twisted.plugins'],
-      package_data={'libervia': ['libervia.sh']},
-      include_package_data=True,
-      data_files=[(os.path.join('share', 'doc', NAME), ['COPYING', 'README', 'INSTALL']), ] +
-                 [(os.path.join('share', NAME, root),
-                   [os.path.join(root, f) for f in files])
-                  for root, dirs, files in os.walk(C.THEMES_DIR)],
-      scripts=[],
-      zip_safe=False,
-      install_requires=['sat', 'twisted', 'txJSON-RPC==0.3.1', 'zope.interface', 'pyopenssl', 'jinja2>=2.9', 'shortuuid', 'autobahn'],
-      cmdclass={'install': CustomInstall},
-      )
+setup(
+    name=NAME,
+    version=VERSION,
+    description=u"Web frontend for Salut à Toi",
+    long_description=long_description,
+    author="Association « Salut à Toi »",
+    author_email="contact@goffi.org",
+    url="https://www.salut-a-toi.org",
+    classifiers=[
+        "Development Status :: 3 - Alpha",
+        "Environment :: Web Environment",
+        "Framework :: Twisted",
+        "License :: OSI Approved :: GNU Affero General Public License v3 "
+        "or later (AGPLv3+)",
+        "Operating System :: POSIX :: Linux",
+        "Topic :: Communications :: Chat",
+    ],
+    packages=["libervia", "libervia.common", "libervia.server", "twisted.plugins"],
+    include_package_data=True,
+    data_files=[(os.path.join("share", "doc", NAME), ["COPYING", "README", "INSTALL"])]
+    + [
+        (os.path.join("share", NAME, root), [os.path.join(root, f) for f in files])
+        for root, dirs, files in os.walk(u"themes")
+    ],
+    scripts=["bin/libervia"],
+    zip_safe=False,
+    setup_requires=["setuptools_scm"] if is_dev_version else [],
+    use_scm_version=libervia_dev_version if is_dev_version else False,
+    install_requires=install_requires,
+    package_data={"libervia": ["VERSION"]},
+    python_requires="~=2.7",
+)