# HG changeset patch # User Denis Laxalde # Date 1467819999 -7200 # Node ID 077f32a7a4c3f43dbdbc5af9dfc33cbea1e7993f # Parent d686c4e8cdb2d0f69a7b5e2260c91572bc8d106c [devtools] Update skeleton's setup.py to install cube as a package Most of the prior logic of skeleton's setup.py gets dropped as installing a cube as a "classic package" (i.e. in site-packages) is just the default behavior of distutils. Also add a test checking installation of new cube. Related to #13001466. diff -r d686c4e8cdb2 -r 077f32a7a4c3 cubicweb/devtools/test/unittest_devctl.py --- a/cubicweb/devtools/test/unittest_devctl.py Thu May 19 14:57:41 2016 +0200 +++ b/cubicweb/devtools/test/unittest_devctl.py Wed Jul 06 17:46:39 2016 +0200 @@ -22,7 +22,7 @@ import sys import tempfile import shutil -from subprocess import Popen, PIPE, STDOUT +from subprocess import Popen, PIPE, STDOUT, check_output from unittest import TestCase @@ -94,6 +94,35 @@ finally: shutil.rmtree(tmpdir, ignore_errors=True) + def test_newcube_install(self): + """Ensure a new cube can be installed""" + tmpdir = tempfile.mkdtemp(prefix="temp-cwctl-newcube-install") + try: + newcube(tmpdir, 'foo') + projectdir = osp.join(tmpdir, 'cubicweb-foo') + env = os.environ.copy() + env['HOME'] = tmpdir + cmd = [sys.executable, 'setup.py', 'install', '--user'] + proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, + cwd=projectdir, env=env) + retcode = proc.wait() + stdout = to_unicode(proc.stdout.read()) + self.assertEqual(retcode, 0, stdout) + targetdir = check_output([sys.executable, '-m', 'site', '--user-site'], + env=env, cwd=projectdir).strip() + target_egg = 'cubicweb_foo-0.1.0-py{0}.egg'.format(sys.version[:3]).encode() + self.assertTrue(osp.isdir(osp.join(targetdir, target_egg)), + 'target directory content: %s' % os.listdir(targetdir)) + pkgdir = osp.join(targetdir, target_egg, b'cubicweb_foo') + self.assertTrue(osp.isdir(pkgdir), + os.listdir(osp.join(targetdir, target_egg))) + pkgcontent = [f for f in os.listdir(pkgdir) if f.endswith(b'.py')] + self.assertItemsEqual(pkgcontent, + [b'schema.py', b'entities.py', b'hooks.py', b'__init__.py', + b'__pkginfo__.py', b'views.py']) + finally: + shutil.rmtree(tmpdir, ignore_errors=True) + if __name__ == '__main__': from unittest import main diff -r d686c4e8cdb2 -r 077f32a7a4c3 cubicweb/skeleton/cubicweb_CUBENAME/__pkginfo__.py.tmpl --- a/cubicweb/skeleton/cubicweb_CUBENAME/__pkginfo__.py.tmpl Thu May 19 14:57:41 2016 +0200 +++ b/cubicweb/skeleton/cubicweb_CUBENAME/__pkginfo__.py.tmpl Wed Jul 06 17:46:39 2016 +0200 @@ -1,10 +1,6 @@ # pylint: disable=W0622 """%(distname)s application packaging information""" -from os import listdir as _listdir -from os.path import join, isdir -from glob import glob - modname = '%(cubename)s' distname = '%(distname)s' @@ -27,24 +23,3 @@ 'Programming Language :: Python', 'Programming Language :: JavaScript', ] - -THIS_CUBE_DIR = join('share', 'cubicweb', 'cubes', modname) - - -def listdir(dirpath): - return [join(dirpath, fname) for fname in _listdir(dirpath) - if fname[0] != '.' and not fname.endswith('.pyc') and - not fname.endswith('~') and - not isdir(join(dirpath, fname))] - -data_files = [ - # common files - [THIS_CUBE_DIR, [fname for fname in glob('*.py') if fname != 'setup.py']], -] -# check for possible extended cube layout -for dname in ('entities', 'views', 'sobjects', 'hooks', 'schema', 'data', - 'wdoc', 'i18n', 'migration'): - if isdir(dname): - data_files.append([join(THIS_CUBE_DIR, dname), listdir(dname)]) -# Note: here, you'll need to add subdirectories if you want -# them to be included in the debian package diff -r d686c4e8cdb2 -r 077f32a7a4c3 cubicweb/skeleton/setup.py.tmpl --- a/cubicweb/skeleton/setup.py.tmpl Thu May 19 14:57:41 2016 +0200 +++ b/cubicweb/skeleton/setup.py.tmpl Wed Jul 06 17:46:39 2016 +0200 @@ -18,18 +18,14 @@ # # You should have received a copy of the GNU Lesser General Public License # along with CubicWeb. If not, see . -"""Generic Setup script, takes package info from __pkginfo__.py file +"""cubicweb_%(cubename)s setup module using data from +cubicweb_%(cubename)s/__pkginfo__.py file """ -__docformat__ = "restructuredtext en" -import os -import sys -import shutil -from os.path import exists, join, dirname +from os.path import join, dirname -from setuptools import setup -from setuptools.command import install_lib -from distutils.command import install_data +from setuptools import find_packages, setup + here = dirname(__file__) @@ -55,10 +51,7 @@ # get optional metadatas distname = __pkginfo__.get('distname', modname) -scripts = __pkginfo__.get('scripts', ()) -include_dirs = __pkginfo__.get('include_dirs', ()) data_files = __pkginfo__.get('data_files', None) -ext_modules = __pkginfo__.get('ext_modules', None) dependency_links = __pkginfo__.get('dependency_links', ()) requires = {} @@ -67,134 +60,18 @@ install_requires = ["{0} {1}".format(d, v and v or "").strip() for d, v in requires.items()] -BASE_BLACKLIST = ('CVS', '.svn', '.hg', '.git', 'debian', 'dist', 'build') -IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc', '~') - -def ensure_scripts(linux_scripts): - """ - Creates the proper script names required for each platform - (taken from 4Suite) - """ - from distutils import util - if util.get_platform()[:3] == 'win': - scripts_ = [script + '.bat' for script in linux_scripts] - else: - scripts_ = linux_scripts - return scripts_ - - -def export(from_dir, to_dir, - blacklist=BASE_BLACKLIST, - ignore_ext=IGNORED_EXTENSIONS, - verbose=True): - try: - os.mkdir(to_dir) - except OSError as ex: - # file exists ? - import errno - if ex.errno != errno.EEXIST: - raise - for dirpath, dirnames, filenames in os.walk(from_dir): - for norecurs in blacklist: - try: - dirnames.remove(norecurs) - except ValueError: - pass - for dir_name in dirnames: - dest = join(to_dir, dir_name) - if not exists(dest): - os.mkdir(dest) - for filename in filenames: - # don't include binary files - src = join(dirpath, filename) - dest = to_dir + src[len(from_dir):] - if filename[-4:] in ignore_ext: - continue - if filename[-1] == '~': - continue - if exists(dest): - os.remove(dest) - if verbose: - sys.stderr.write('{0} -> {1}\n'.format(src, dest)) - shutil.copy2(src, dest) - - -class MyInstallLib(install_lib.install_lib): - """extend install_lib command to handle package __init__.py and - include_dirs variable if necessary - """ - def run(self): - """overridden from install_lib class""" - install_lib.install_lib.run(self) - # manually install included directories if any - if include_dirs: - base = modname - for directory in include_dirs: - dest = join(self.install_dir, base, directory) - export(directory, dest, verbose=False) - - -# re-enable copying data files in sys.prefix -old_install_data = install_data.install_data -# overwrite InstallData to use sys.prefix instead of the egg directory -class MyInstallData(old_install_data): - """A class that manages data files installation""" - def run(self): - _old_install_dir = self.install_dir - if self.install_dir.endswith('egg'): - self.install_dir = sys.prefix - old_install_data.run(self) - self.install_dir = _old_install_dir -try: - # only if easy_install available - import setuptools.command.easy_install # noqa - # monkey patch: Crack SandboxViolation verification - from setuptools.sandbox import DirectorySandbox as DS - old_ok = DS._ok - - def _ok(self, path): - """Return True if ``path`` can be written during installation.""" - out = old_ok(self, path) # here for side effect from setuptools - realpath = os.path.normcase(os.path.realpath(path)) - allowed_path = os.path.normcase(sys.prefix) - if realpath.startswith(allowed_path): - out = True - return out - DS._ok = _ok -except ImportError: - pass - - -def install(**kwargs): - """setup entry point""" - if '--force-manifest' in sys.argv: - sys.argv.remove('--force-manifest') - # install-layout option was introduced in 2.5.3-1~exp1 - elif sys.version_info < (2, 5, 4) and '--install-layout=deb' in sys.argv: - sys.argv.remove('--install-layout=deb') - cmdclass = {'install_lib': MyInstallLib} - kwargs['install_requires'] = install_requires - kwargs['dependency_links'] = dependency_links - kwargs['zip_safe'] = False - cmdclass['install_data'] = MyInstallData - - return setup(name=distname, - version=version, - license=license, - description=description, - long_description=long_description, - author=author, - author_email=author_email, - url=web, - scripts=ensure_scripts(scripts), - data_files=data_files, - ext_modules=ext_modules, - cmdclass=cmdclass, - classifiers=classifiers, - **kwargs - ) - - -if __name__ == '__main__': - install() +setup( + name=distname, + version=version, + license=license, + description=description, + long_description=long_description, + author=author, + author_email=author_email, + url=web, + classifiers=classifiers, + packages=find_packages(exclude=['test']), + install_requires=install_requires, + zip_safe=False, +)