setup.py 7.38 KB
Newer Older
Adrien Di Mascio's avatar
Adrien Di Mascio committed
1
#!/usr/bin/env python
Sylvain Thénault's avatar
Sylvain Thénault committed
2
# pylint: disable=W0142,W0403,W0404,W0613,W0622,W0622,W0704,R0904,C0103,E0611
Adrien Di Mascio's avatar
Adrien Di Mascio committed
3
#
4
# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5
6
7
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
Adrien Di Mascio's avatar
Adrien Di Mascio committed
8
#
9
10
11
12
13
# CubicWeb is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
14
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
Adrien Di Mascio's avatar
Adrien Di Mascio committed
15
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
17
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
Adrien Di Mascio's avatar
Adrien Di Mascio committed
18
#
19
20
21
22
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
"""Generic Setup script, takes package info from __pkginfo__.py file
"""
Adrien Di Mascio's avatar
Adrien Di Mascio committed
23

24
import io
Adrien Di Mascio's avatar
Adrien Di Mascio committed
25
26
27
import os
import sys
import shutil
28
from os.path import dirname, exists, isdir, join
Adrien Di Mascio's avatar
Adrien Di Mascio committed
29

30
31
from setuptools import setup
from setuptools.command import install_lib
32
from distutils.command import install_data
33

34
35
here = dirname(__file__)

36
# import required features
37
38
39
40
41
42
43
44
45
46
47
pkginfo = join(here, 'cubicweb', '__pkginfo__.py')
__pkginfo__ = {}
with open(pkginfo) as f:
    exec(f.read(), __pkginfo__)
modname = __pkginfo__['modname']
version = __pkginfo__['version']
license = __pkginfo__['license']
description = __pkginfo__['description']
web = __pkginfo__['web']
author = __pkginfo__['author']
author_email = __pkginfo__['author_email']
48

49
50
with io.open('README', encoding='utf-8') as f:
    long_description = f.read()
51
52

# import optional features
53
54
55
56
57
requires = {}
for entry in ("__depends__",): # "__recommends__"):
    requires.update(__pkginfo__.get(entry, {}))
install_requires = [("%s %s" % (d, v and v or "")).strip()
                   for d, v in requires.items()]
58

59
60
61
62
63
distname = __pkginfo__['distname']
scripts = __pkginfo__['scripts']
include_dirs = __pkginfo__['include_dirs']
data_files = __pkginfo__['data_files']
package_data = __pkginfo__['package_data']
Adrien Di Mascio's avatar
Adrien Di Mascio committed
64

65
BASE_BLACKLIST = ('CVS', 'dist', 'build', '__buildlog')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
66
IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc')
67

Adrien Di Mascio's avatar
Adrien Di Mascio committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

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 get_packages(directory, prefix):
    """return a list of subpackages for the given directory
    """
    result = []
    for package in os.listdir(directory):
        absfile = join(directory, package)
        if isdir(absfile):
            if exists(join(absfile, '__init__.py')) or \
                   package in ('test', 'tests'):
                if prefix:
                    result.append('%s.%s' % (prefix, package))
                else:
                    result.append(package)
                result += get_packages(absfile, result[-1])
    return result

def export(from_dir, to_dir,
           blacklist=BASE_BLACKLIST,
100
101
           ignore_ext=IGNORED_EXTENSIONS,
           verbose=True):
102
103
104
105
106
107
108
    try:
        os.mkdir(to_dir)
    except OSError as ex:
        # file exists ?
        import errno
        if ex.errno != errno.EEXIST:
            raise
109
110
111
    else:
        if verbose:
            print('created %s directory' % to_dir)
112
    for dirpath, dirnames, filenames in os.walk(from_dir):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
113
114
        for norecurs in blacklist:
            try:
115
                dirnames.remove(norecurs)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
116
117
            except ValueError:
                pass
118
119
120
            else:
                if verbose:
                    print('not recursing in %s' % join(dirpath, norecurs))
121
        for dirname in dirnames:
122
123
            src = join(dirpath, dirname)
            dest = to_dir + src[len(from_dir):]
124
            if not exists(dest):
125
126
                if verbose:
                    print('creating %s directory' % dest)
127
128
                os.mkdir(dest)
        for filename in filenames:
Adrien Di Mascio's avatar
Adrien Di Mascio committed
129
            # don't include binary files
130
131
            src = join(dirpath, filename)
            dest = to_dir + src[len(from_dir):]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
132
133
134
135
            if filename[-4:] in ignore_ext:
                continue
            if filename[-1] == '~':
                continue
136
137
            if exists(dest):
                os.remove(dest)
138
139
            if verbose:
                print('copying %s to %s' % (src, dest))
140
            shutil.copy2(src, dest)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
141
142
143
144
145
146
147
148
149
150
151
152
153


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)
        # create Products.__init__.py if needed
        # manually install included directories if any
        if include_dirs:
            for directory in include_dirs:
154
155
156
                src = join(modname, directory)
                dest = join(self.install_dir, src)
                export(src, dest, verbose=self.verbose)
157

158
# write required share/cubicweb/cubes/__init__.py
159
class MyInstallData(install_data.install_data):
160
    """A class That manages data files installation"""
161
162
163
164
165
166
167
168
    def run(self):
        """overridden from install_data class"""
        install_data.install_data.run(self)
        path = join(self.install_dir, 'share', 'cubicweb', 'cubes', '__init__.py')
        ini = open(path, 'w')
        ini.write('# Cubicweb cubes directory\n')
        ini.close()

169
# re-enable copying data files in sys.prefix
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# overwrite MyInstallData to use sys.prefix instead of the egg directory
MyInstallMoreData = MyInstallData
class MyInstallData(MyInstallMoreData): # pylint: disable=E0102
    """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
        MyInstallMoreData.run(self)
        self.install_dir = _old_install_dir
try:
    import setuptools.command.easy_install # only if easy_install available
    # 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
196

Adrien Di Mascio's avatar
Adrien Di Mascio committed
197
198
def install(**kwargs):
    """setup entry point"""
199
    packages = [modname] + get_packages(join(here, modname), modname)
200
201
    kwargs['install_requires'] = install_requires
    kwargs['zip_safe'] = False
Adrien Di Mascio's avatar
Adrien Di Mascio committed
202
    kwargs['packages'] = packages
203
    kwargs['package_data'] = package_data
204
205
206
207
    return setup(name=distname, version=version, license=license, url=web,
                 description=description, long_description=long_description,
                 author=author, author_email=author_email,
                 scripts=ensure_scripts(scripts), data_files=data_files,
208
209
                 cmdclass={'install_lib': MyInstallLib,
                           'install_data': MyInstallData},
Adrien Di Mascio's avatar
Adrien Di Mascio committed
210
211
                 **kwargs
                 )
212

Adrien Di Mascio's avatar
Adrien Di Mascio committed
213
214
if __name__ == '__main__' :
    install()