setup.py 8.23 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
from setuptools import setup
31
from setuptools.command import develop, 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
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
58

59
BASE_BLACKLIST = ('CVS', 'dist', 'build', '__buildlog')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
60
IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc')
61

Adrien Di Mascio's avatar
Adrien Di Mascio committed
62
63
64
65
66
67
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

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


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:
148
149
150
                src = join(modname, directory)
                dest = join(self.install_dir, src)
                export(src, dest, verbose=self.verbose)
151

152
# write required share/cubicweb/cubes/__init__.py
153
class MyInstallData(install_data.install_data):
154
    """A class That manages data files installation"""
155
156
157
158
159
160
161
162
    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()

163
164
165
166
167
168
169
170
171
172

class CWDevelop(develop.develop):
    """Custom "develop" command warning about (legacy) cubes directory not
    installed.
    """

    def run(self):
        cubespath = join(sys.prefix, 'share', 'cubicweb', 'cubes')
        self.warn('develop command does not install (legacy) cubes directory (%s)'
                  % cubespath)
173
        return develop.develop.run(self)
174
175


176
# re-enable copying data files in sys.prefix
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# 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
203

204
205
206
207
208
209
210
211
212
213
214
215
216
217

setup(
    name=distname,
    version=version,
    license=license,
    url=web,
    description=description,
    long_description=long_description,
    author=author,
    author_email=author_email,
    packages=[modname] + get_packages(join(here, modname), modname),
    package_data=package_data,
    scripts=ensure_scripts(scripts),
    data_files=data_files,
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
    install_requires=[
        'six >= 1.4.0',
        'logilab-common >= 1.2.2',
        'logilab-mtconverter >= 0.8.0',
        'rql >= 0.34.0',
        'yams >= 0.44.0',
        'lxml',
        'logilab-database >= 1.15.0',
        'passlib',
        'pytz',
        'Markdown',
        'unittest2 >= 0.7.0',
    ],
    extra_requires={
        'captcha': [
            'Pillow',
        ],
        'crypto': [
            'pycrypto',
        ],
        'etwist': [
            'Twisted < 16.0.0',
        ],
        'ext': [
            'docutils >= 0.6',
        ],
        'ical': [
            'vobject >= 0.6.0',
        ],
        'pyramid': [
            'pyramid >= 1.5.0',
            'waitress >= 0.8.9',
            'wsgicors >= 0.3',
            'pyramid_multiauth',
        ],
        'rdf': [
            'rdflib',
        ],
        'sparql': [
            'fyzz >= 0.1.0',
        ],
        'zmq': [
            'pyzmq',
        ],
    },
263
264
265
266
267
    cmdclass={
        'install_lib': MyInstallLib,
        'install_data': MyInstallData,
        'develop': CWDevelop,
    },
268
269
    zip_safe=False,
)