[pkg] Use setuptools

Move sources to a 'rql' subdirectory, drop the NO_SETUPTOOLS code path (essentially rewriting all of setup.py). This avoids a conflict between our parser.py and the stdlib when running setup.py. Closes #278637.

authorJulien Cristau <julien.cristau@logilab.fr>
changesetd9762b5a4604
branchdefault
phasepublic
hiddenno
parent revision#5b44acfd687b [py3k] fix relative import
child revision#5aa92d744e2d [pkg] make pkginfo's gecode version check a bit less ugly
files modified by this revision
__init__.py
__pkginfo__.py
_exceptions.py
analyze.py
base.py
compare.py
editextensions.py
gecode_solver.cpp
interfaces.py
nodes.py
parser.g
parser.py
parser_main.py
pygments_ext.py
rql/__init__.py
rql/_exceptions.py
rql/analyze.py
rql/base.py
rql/compare.py
rql/editextensions.py
rql/gecode_solver.cpp
rql/interfaces.py
rql/nodes.py
rql/parser.g
rql/parser.py
rql/parser_main.py
rql/pygments_ext.py
rql/rqlgen.py
rql/stcheck.py
rql/stmts.py
rql/undo.py
rql/utils.py
rqlgen.py
setup.py
stcheck.py
stmts.py
undo.py
utils.py
# HG changeset patch
# User Julien Cristau <julien.cristau@logilab.fr>
# Date 1432768408 -7200
# Thu May 28 01:13:28 2015 +0200
# Node ID d9762b5a4604f3616c7f8501a29fd0878e8e1a88
# Parent 5b44acfd687b253fe5ca76ed3cf0356c0842aeba
[pkg] Use setuptools

Move sources to a 'rql' subdirectory, drop the NO_SETUPTOOLS code path
(essentially rewriting all of setup.py). This avoids a conflict between
our parser.py and the stdlib when running setup.py. Closes #278637.

diff --git a/__pkginfo__.py b/__pkginfo__.py
@@ -58,19 +58,19 @@
1      return ((a<<16)+(b<<8)+c)
2 
3  GECODE_VERSION = encode_version(*gecode_version())
4 
5  if sys.platform != 'win32':
6 -    ext_modules = [Extension('rql_solve',
7 -                             ['gecode_solver.cpp'],
8 +    ext_modules = [Extension('rql.rql_solve',
9 +                             ['rql/gecode_solver.cpp'],
10                                libraries=['gecodeint', 'gecodekernel', 'gecodesearch',],
11                               extra_compile_args=['-DGE_VERSION=%s' % GECODE_VERSION],
12                           )
13                     ]
14  else:
15 -    ext_modules = [ Extension('rql_solve',
16 -                              ['gecode_solver.cpp'],
17 +    ext_modules = [ Extension('rql.rql_solve',
18 +                              ['rql/gecode_solver.cpp'],
19                                libraries=['GecodeInt-3-3-1-r-x86',
20                                           'GecodeKernel-3-3-1-r-x86',
21                                           'GecodeSearch-3-3-1-r-x86',
22                                           'GecodeSupport-3-3-1-r-x86',
23                                           ],
@@ -83,6 +83,7 @@
24      'logilab-common >= 0.47.0',
25      'logilab-database >= 1.6.0',
26      'yapps >= 2.2.0', # XXX to ensure we don't use the broken pypi version
27      'logilab-constraint >= 0.5.0', # fallback if the gecode compiled module is missing
28      'six >= 1.4.0',
29 +    'setuptools',
30      ]
diff --git a/__init__.py b/rql/__init__.py
@@ -16,22 +16,25 @@
31  # You should have received a copy of the GNU Lesser General Public License along
32  # with rql. If not, see <http://www.gnu.org/licenses/>.
33  """RQL library (implementation independant)."""
34  __docformat__ = "restructuredtext en"
35 
36 -from rql.__pkginfo__ import version as __version__
37  from math import log
38 
39  import sys
40  import threading
41 
42 +import pkg_resources
43  from six import StringIO
44 
45  from rql._exceptions import *
46 
47 +
48 +__version__ = pkg_resources.get_distribution('rql').version
49  #REQUIRED_TYPES = ['String', 'Float', 'Int', 'Boolean', 'Date']
50 
51 +
52  class RQLHelper(object):
53      """Helper class for RQL handling
54 
55      give access to methods for :
56        - parsing RQL strings
diff --git a/_exceptions.py b/rql/_exceptions.py
diff --git a/analyze.py b/rql/analyze.py
diff --git a/base.py b/rql/base.py
diff --git a/compare.py b/rql/compare.py
diff --git a/editextensions.py b/rql/editextensions.py
diff --git a/gecode_solver.cpp b/rql/gecode_solver.cpp
diff --git a/interfaces.py b/rql/interfaces.py
diff --git a/nodes.py b/rql/nodes.py
diff --git a/parser.g b/rql/parser.g
diff --git a/parser.py b/rql/parser.py
diff --git a/parser_main.py b/rql/parser_main.py
diff --git a/pygments_ext.py b/rql/pygments_ext.py
diff --git a/rqlgen.py b/rql/rqlgen.py
diff --git a/stcheck.py b/rql/stcheck.py
diff --git a/stmts.py b/rql/stmts.py
diff --git a/undo.py b/rql/undo.py
diff --git a/utils.py b/rql/utils.py
diff --git a/setup.py b/setup.py
@@ -17,208 +17,42 @@
57  #
58  # You should have received a copy of the GNU Lesser General Public License along
59  # with rql. If not, see <http://www.gnu.org/licenses/>.
60  """Generic Setup script, takes package info from __pkginfo__.py file.
61  """
62 -__docformat__ = "restructuredtext en"
63 -
64 -import os
65 -import sys
66 -import shutil
67 -from os.path import isdir, exists, join, walk
68 
69 -try:
70 -    if os.environ.get('NO_SETUPTOOLS'):
71 -        raise ImportError()
72 -    from setuptools import setup
73 -    from setuptools.command import install_lib, build_ext
74 -    USE_SETUPTOOLS = 1
75 -except ImportError:
76 -    from distutils.core import setup
77 -    from distutils.command import install_lib, build_ext
78 -    USE_SETUPTOOLS = 0
79 -
80 +from setuptools import setup, find_packages
81 +from io import open
82 +from os import path
83 
84 -sys.modules.pop('__pkginfo__', None)
85 -# import required features
86 -from __pkginfo__ import modname, version, license, description, long_desc, \
87 -     web, author, author_email
88 -# import optional features
89 -import __pkginfo__
90 -distname = getattr(__pkginfo__, 'distname', modname)
91 -scripts = getattr(__pkginfo__, 'scripts', [])
92 -data_files = getattr(__pkginfo__, 'data_files', None)
93 -subpackage_of = getattr(__pkginfo__, 'subpackage_of', None)
94 -include_dirs = getattr(__pkginfo__, 'include_dirs', [])
95 -ext_modules = getattr(__pkginfo__, 'ext_modules', None)
96 -install_requires = getattr(__pkginfo__, 'install_requires', None)
97 -dependency_links = getattr(__pkginfo__, 'dependency_links', [])
98 +here = path.abspath(path.dirname(__file__))
99 
100 -STD_BLACKLIST = ('CVS', '.svn', '.hg', 'debian', 'dist', 'build')
101 -
102 -IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc', '~')
103 -
104 -
105 +pkginfo = {}
106 +with open(path.join(here, '__pkginfo__.py')) as f:
107 +    exec(f.read(), pkginfo)
108 
109 -def ensure_scripts(linux_scripts):
110 -    """
111 -    Creates the proper script names required for each platform
112 -    (taken from 4Suite)
113 -    """
114 -    from distutils import util
115 -    if util.get_platform()[:3] == 'win':
116 -        scripts_ = [script + '.bat' for script in linux_scripts]
117 -    else:
118 -        scripts_ = linux_scripts
119 -    return scripts_
120 -
121 +# Get the long description from the relevant file
122 +with open(path.join(here, 'README'), encoding='utf-8') as f:
123 +    long_description = f.read()
124 
125 -def get_packages(directory, prefix):
126 -    """return a list of subpackages for the given directory
127 -    """
128 -    result = []
129 -    for package in os.listdir(directory):
130 -        absfile = join(directory, package)
131 -        if isdir(absfile):
132 -            if exists(join(absfile, '__init__.py')) or \
133 -                   package in ('test', 'tests'):
134 -                if prefix:
135 -                    result.append('%s.%s' % (prefix, package))
136 -                else:
137 -                    result.append(package)
138 -                result += get_packages(absfile, result[-1])
139 -    return result
140 +kwargs = {}
141 +if 'subpackage_of' in pkginfo:
142 +    kwargs['namespace_packages'] = [pkginfo['subpackage_of']],
143 
144 -def export(from_dir, to_dir,
145 -           blacklist=STD_BLACKLIST,
146 -           ignore_ext=IGNORED_EXTENSIONS,
147 -           verbose=True):
148 -    """make a mirror of from_dir in to_dir, omitting directories and files
149 -    listed in the black list
150 -    """
151 -    def make_mirror(arg, directory, fnames):
152 -        """walk handler"""
153 -        for norecurs in blacklist:
154 -            try:
155 -                fnames.remove(norecurs)
156 -            except ValueError:
157 -                pass
158 -        for filename in fnames:
159 -            # don't include binary files
160 -            if filename[-4:] in ignore_ext:
161 -                continue
162 -            if filename[-1] == '~':
163 -                continue
164 -            src = join(directory, filename)
165 -            dest = to_dir + src[len(from_dir):]
166 -            if verbose:
167 -                print >> sys.stderr, src, '->', dest
168 -            if os.path.isdir(src):
169 -                if not exists(dest):
170 -                    os.mkdir(dest)
171 -            else:
172 -                if exists(dest):
173 -                    os.remove(dest)
174 -                shutil.copy2(src, dest)
175 -    try:
176 -        os.mkdir(to_dir)
177 -    except OSError as ex:
178 -        # file exists ?
179 -        import errno
180 -        if ex.errno != errno.EEXIST:
181 -            raise
182 -    walk(from_dir, make_mirror, None)
183 -
184 -
185 -EMPTY_FILE = '''"""generated file, don\'t modify or your data will be lost"""
186 -try:
187 -    __import__('pkg_resources').declare_namespace(__name__)
188 -except ImportError:
189 -    pass
190 -'''
191 -
192 -class MyInstallLib(install_lib.install_lib):
193 -    """extend install_lib command to handle  package __init__.py and
194 -    include_dirs variable if necessary
195 -    """
196 -    def run(self):
197 -        """overridden from install_lib class"""
198 -        install_lib.install_lib.run(self)
199 -        # create Products.__init__.py if needed
200 -        if subpackage_of:
201 -            product_init = join(self.install_dir, subpackage_of, '__init__.py')
202 -            if not exists(product_init):
203 -                self.announce('creating %s' % product_init)
204 -                stream = open(product_init, 'w')
205 -                stream.write(EMPTY_FILE)
206 -                stream.close()
207 -        # manually install included directories if any
208 -        if include_dirs:
209 -            if subpackage_of:
210 -                base = join(subpackage_of, modname)
211 -            else:
212 -                base = modname
213 -            for directory in include_dirs:
214 -                dest = join(self.install_dir, base, directory)
215 -                export(directory, dest, verbose=False)
216 -
217 -if os.environ.get('RQL_FORCE_GECODE'):
218 -    MyBuildExt = build_ext.build_ext
219 -else:
220 -    class MyBuildExt(build_ext.build_ext):
221 -        """Extend build_ext command to pass through compilation error.
222 -        In fact, if gecode extension fail, rql will use logilab.constraint
223 -        """
224 -        def run(self):
225 -            try:
226 -                build_ext.build_ext.run(self)
227 -            except Exception:
228 -                import traceback
229 -                traceback.print_exc()
230 -                sys.stderr.write('================================\n'
231 -                                 'The compilation of the gecode C extension failed. '
232 -                                 'rql will use logilab.constraint which is a pure '
233 -                                 'python implementation. '
234 -                                 'Please note that the C extension run faster. '
235 -                                 'So, install a compiler then install rql again with'
236 -                                 ' the "force" option for better performance.\n'
237 -                                 '================================\n')
238 -
239 -def install(**kwargs):
240 -    """setup entry point"""
241 -    if USE_SETUPTOOLS:
242 -        if '--force-manifest' in sys.argv:
243 -            sys.argv.remove('--force-manifest')
244 -    # install-layout option was introduced in 2.5.3-1~exp1
245 -    elif sys.version_info < (2, 5, 4) and '--install-layout=deb' in sys.argv:
246 -        sys.argv.remove('--install-layout=deb')
247 -    if subpackage_of:
248 -        package = subpackage_of + '.' + modname
249 -        kwargs['package_dir'] = {package : '.'}
250 -        packages = [package] + get_packages(os.getcwd(), package)
251 -        if USE_SETUPTOOLS:
252 -            kwargs['namespace_packages'] = [subpackage_of]
253 -    else:
254 -        kwargs['package_dir'] = {modname : '.'}
255 -        packages = [modname] + get_packages(os.getcwd(), modname)
256 -    if USE_SETUPTOOLS and install_requires:
257 -        kwargs['install_requires'] = install_requires
258 -        kwargs['dependency_links'] = dependency_links
259 -    kwargs['packages'] = packages
260 -    return setup(name = distname,
261 -                 version = version,
262 -                 license = license,
263 -                 description = description,
264 -                 long_description = long_desc,
265 -                 author = author,
266 -                 author_email = author_email,
267 -                 url = web,
268 -                 scripts = ensure_scripts(scripts),
269 -                 data_files = data_files,
270 -                 ext_modules = ext_modules,
271 -                 cmdclass = {'install_lib': MyInstallLib,
272 -                             'build_ext':MyBuildExt},
273 -                 **kwargs
274 -                 )
275 -
276 -if __name__ == '__main__' :
277 -    install()
278 +setup(
279 +    name=pkginfo.get('distname', pkginfo['modname']),
280 +    version=pkginfo['version'],
281 +    description=pkginfo['description'],
282 +    long_description=long_description,
283 +    url=pkginfo['web'],
284 +    author=pkginfo['author'],
285 +    author_email=pkginfo['author_email'],
286 +    license=pkginfo['license'],
287 +    # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
288 +    classifiers=pkginfo.get('classifiers', []),
289 +    packages=find_packages(exclude=['contrib', 'docs', 'test*']),
290 +    install_requires=pkginfo.get('install_requires'),
291 +    tests_require=pkginfo.get('tests_require'),
292 +    scripts=pkginfo.get('scripts', []),
293 +    ext_modules=pkginfo.get('ext_modules'),
294 +    **kwargs
295 +)