source: trunk/setup.py

Last change on this file was ae6e1e9, checked in by Sajith Sasidharan <sajith@…>, at 2021-04-05T23:11:58Z

Use io.open() instead of builtin open()

Windows does not like when we open README.rst using builtin open():

Traceback (most recent call last):

File "setup.py", line 360, in <module>

long_description=open('README.rst', 'rU').read(),

File "c:\hostedtoolcache\windows\python\3.6.8\x64\lib\encodings\cp1252.py", line 23, in decode

return codecs.charmap_decode(input,self.errors,decoding_table)[0]

UnicodeDecodeError?: 'charmap' codec can't decode byte 0x9d in position 1720: character maps to <undefined>

  • Property mode set to 100644
File size: 16.5 KB
Line 
1#! /usr/bin/env python
2# -*- coding: utf-8 -*-
3import sys
4
5# Tahoe-LAFS -- secure, distributed storage grid
6#
7# Copyright © 2006-2012 The Tahoe-LAFS Software Foundation
8#
9# This file is part of Tahoe-LAFS.
10#
11# See the docs/about.rst file for licensing information.
12
13import os, subprocess, re
14from io import open
15
16basedir = os.path.dirname(os.path.abspath(__file__))
17
18# locate our version number
19
20def read_version_py(infname):
21    try:
22        verstrline = open(infname, "rt").read()
23    except EnvironmentError:
24        return None
25    else:
26        VSRE = r"^verstr = ['\"]([^'\"]*)['\"]"
27        mo = re.search(VSRE, verstrline, re.M)
28        if mo:
29            return mo.group(1)
30
31VERSION_PY_FILENAME = 'src/allmydata/_version.py'
32version = read_version_py(VERSION_PY_FILENAME)
33
34install_requires = [
35    # we don't need much out of setuptools but the version checking stuff
36    # needs pkg_resources and PEP 440 version specifiers.
37    "setuptools >= 28.8.0",
38
39    "zfec >= 1.1.0",
40
41    # zope.interface >= 3.6.0 is required for Twisted >= 12.1.0.
42    "zope.interface >= 3.6.0",
43
44    # * foolscap < 0.5.1 had a performance bug which spent O(N**2) CPU for
45    #   transferring large mutable files of size N.
46    # * foolscap < 0.6 is incompatible with Twisted 10.2.0.
47    # * foolscap 0.6.1 quiets a DeprecationWarning.
48    # * foolscap < 0.6.3 is incompatible with Twisted 11.1.0 and newer.
49    # * foolscap 0.8.0 generates 2048-bit RSA-with-SHA-256 signatures,
50    #   rather than 1024-bit RSA-with-MD5. This also allows us to work
51    #   with a FIPS build of OpenSSL.
52    # * foolscap >= 0.12.3 provides tcp/tor/i2p connection handlers we need,
53    #   and allocate_tcp_port
54    # * foolscap >= 0.12.5 has ConnectionInfo and ReconnectionInfo
55    # * foolscap >= 0.12.6 has an i2p.sam_endpoint() that takes kwargs
56    # * foolscap 0.13.2 drops i2p support completely
57    # * foolscap >= 20.4 is necessary for Python 3
58    "foolscap == 0.13.1 ; python_version < '3.0'",
59    "foolscap >= 20.4.0 ; python_version > '3.0'",
60
61    # * cryptography 2.6 introduced some ed25519 APIs we rely on.  Note that
62    #   Twisted[conch] also depends on cryptography and Twisted[tls]
63    #   transitively depends on cryptography.  So it's anyone's guess what
64    #   version of cryptography will *really* be installed.
65    "cryptography >= 2.6",
66
67    # * The SFTP frontend depends on Twisted 11.0.0 to fix the SSH server
68    #   rekeying bug <https://twistedmatrix.com/trac/ticket/4395>
69    # * The SFTP frontend and manhole depend on the conch extra. However, we
70    #   can't explicitly declare that without an undesirable dependency on gmpy,
71    #   as explained in ticket #2740.
72    # * Due to a setuptools bug, we need to declare a dependency on the tls
73    #   extra even though we only depend on it via foolscap.
74    # * Twisted >= 15.1.0 is the first version that provided the [tls] extra.
75    # * Twisted-16.1.0 fixes https://twistedmatrix.com/trac/ticket/8223,
76    #   which otherwise causes test_system to fail (DirtyReactorError, due to
77    #   leftover timers)
78    # * Twisted-16.4.0 introduces `python -m twisted.trial` which is needed
79    #   for coverage testing
80    # * Twisted 16.6.0 drops the undesirable gmpy dependency from the conch
81    #   extra, letting us use that extra instead of trying to duplicate its
82    #   dependencies here.  Twisted[conch] >18.7 introduces a dependency on
83    #   bcrypt.  It is nice to avoid that if the user ends up with an older
84    #   version of Twisted.  That's hard to express except by using the extra.
85    #
86    # * Twisted 18.4.0 adds `client` and `host` attributes to `Request` in the
87    # * initializer, needed by logic in our custom `Request` subclass.
88    #
89    #   In a perfect world, Twisted[conch] would be a dependency of an "sftp"
90    #   extra.  However, pip fails to resolve the dependencies all
91    #   dependencies when asked for Twisted[tls] *and* Twisted[conch].
92    #   Specifically, "Twisted[conch]" (as the later requirement) is ignored.
93    #   If there were an Tahoe-LAFS sftp extra that dependended on
94    #   Twisted[conch] and install_requires only included Twisted[tls] then
95    #   `pip install tahoe-lafs[sftp]` would not install requirements
96    #   specified by Twisted[conch].  Since this would be the *whole point* of
97    #   an sftp extra in Tahoe-LAFS, there is no point in having one.
98    # * Twisted 19.10 introduces Site.getContentFile which we use to get
99    #   temporary upload files placed into a per-node temporary directory.
100    "Twisted[tls,conch] >= 19.10.0",
101
102    "PyYAML >= 3.11",
103
104    "six >= 1.10.0",
105
106    # for 'tahoe invite' and 'tahoe join'
107    "magic-wormhole >= 0.10.2",
108
109    # Eliot is contemplating dropping Python 2 support.  Stick to a version we
110    # know works on Python 2.7.
111    "eliot ~= 1.7 ; python_version < '3.0'",
112    # On Python 3, we want a new enough version to support custom JSON encoders.
113    "eliot >= 1.13.0 ; python_version > '3.0'",
114
115    # Pyrsistent 0.17.0 (which we use by way of Eliot) has dropped
116    # Python 2 entirely; stick to the version known to work for us.
117    # XXX: drop this bound: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3404
118    "pyrsistent < 0.17.0",
119
120    # A great way to define types of values.
121    # XXX: drop the upper bound: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3390
122    "attrs >= 18.2.0, < 20",
123
124    # WebSocket library for twisted and asyncio
125    "autobahn >= 19.5.2",
126
127    # Support for Python 3 transition
128    "future >= 0.18.2",
129
130    # Discover local network configuration
131    "netifaces",
132
133    # Utility code:
134    "pyutil >= 3.3.0",
135
136    # Linux distribution detection:
137    "distro >= 1.4.0",
138
139    # Backported configparser for Python 2:
140    "configparser ; python_version < '3.0'",
141]
142
143setup_requires = [
144    'setuptools >= 28.8.0',  # for PEP-440 style versions
145]
146
147tor_requires = [
148    # This is exactly what `foolscap[tor]` means but pip resolves the pair of
149    # dependencies "foolscap[i2p] foolscap[tor]" to "foolscap[i2p]" so we lose
150    # this if we don't declare it ourselves!
151    "txtorcon >= 0.17.0",
152]
153
154i2p_requires = [
155    # txi2p has Python 3 support in master branch, but it has not been
156    # released -- see https://github.com/str4d/txi2p/issues/10.  We
157    # could use a fork for Python 3 until txi2p's maintainers are back
158    # in action.  For Python 2, we could continue using the txi2p
159    # version about which no one has complained to us so far.
160    "txi2p; python_version < '3.0'",
161    "txi2p-tahoe >= 0.3.5; python_version > '3.0'",
162]
163
164if len(sys.argv) > 1 and sys.argv[1] == '--fakedependency':
165    del sys.argv[1]
166    install_requires += ["fakedependency >= 1.0.0"]
167
168from setuptools import find_packages, setup
169from setuptools import Command
170from setuptools.command import install
171
172
173trove_classifiers=[
174    "Development Status :: 5 - Production/Stable",
175    "Environment :: Console",
176    "Environment :: Web Environment",
177    "License :: OSI Approved :: GNU General Public License (GPL)",
178    "License :: DFSG approved",
179    "License :: Other/Proprietary License",
180    "Intended Audience :: Developers",
181    "Intended Audience :: End Users/Desktop",
182    "Intended Audience :: System Administrators",
183    "Operating System :: Microsoft",
184    "Operating System :: Microsoft :: Windows",
185    "Operating System :: Unix",
186    "Operating System :: POSIX :: Linux",
187    "Operating System :: POSIX",
188    "Operating System :: MacOS :: MacOS X",
189    "Operating System :: OS Independent",
190    "Natural Language :: English",
191    "Programming Language :: C",
192    "Programming Language :: Python",
193    "Programming Language :: Python :: 2",
194    "Programming Language :: Python :: 2.7",
195    "Topic :: Utilities",
196    "Topic :: System :: Systems Administration",
197    "Topic :: System :: Filesystems",
198    "Topic :: System :: Distributed Computing",
199    "Topic :: Software Development :: Libraries",
200    "Topic :: System :: Archiving :: Backup",
201    "Topic :: System :: Archiving :: Mirroring",
202    "Topic :: System :: Archiving",
203    ]
204
205
206GIT_VERSION_BODY = '''
207# This _version.py is generated from git metadata by the tahoe setup.py.
208
209__pkgname__ = "%(pkgname)s"
210real_version = "%(version)s"
211full_version = "%(full)s"
212branch = "%(branch)s"
213verstr = "%(normalized)s"
214__version__ = verstr
215'''
216
217def run_command(args, cwd=None):
218    use_shell = sys.platform == "win32"
219    try:
220        p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd, shell=use_shell)
221    except EnvironmentError as e:  # if this gives a SyntaxError, note that Tahoe-LAFS requires Python 2.7+
222        print("Warning: unable to run %r." % (" ".join(args),))
223        print(e)
224        return None
225    stdout = p.communicate()[0].strip()
226    if p.returncode != 0:
227        print("Warning: %r returned error code %r." % (" ".join(args), p.returncode))
228        return None
229    return stdout
230
231
232def versions_from_git(tag_prefix):
233    # This runs 'git' from the directory that contains this file. That either
234    # means someone ran a setup.py command (and this code is in
235    # versioneer.py, thus the containing directory is the root of the source
236    # tree), or someone ran a project-specific entry point (and this code is
237    # in _version.py, thus the containing directory is somewhere deeper in
238    # the source tree). This only gets called if the git-archive 'subst'
239    # variables were *not* expanded, and _version.py hasn't already been
240    # rewritten with a short version string, meaning we're inside a checked
241    # out source tree.
242
243    # versions_from_git (as copied from python-versioneer) returns strings
244    # like "1.9.0-25-gb73aba9-dirty", which means we're in a tree with
245    # uncommited changes (-dirty), the latest checkin is revision b73aba9,
246    # the most recent tag was 1.9.0, and b73aba9 has 25 commits that weren't
247    # in 1.9.0 . The narrow-minded NormalizedVersion parser that takes our
248    # output (meant to enable sorting of version strings) refuses most of
249    # that. Tahoe uses a function named suggest_normalized_version() that can
250    # handle "1.9.0.post25", so dumb down our output to match.
251
252    try:
253        source_dir = os.path.dirname(os.path.abspath(__file__))
254    except NameError as e:
255        # some py2exe/bbfreeze/non-CPython implementations don't do __file__
256        print("Warning: unable to find version because we could not obtain the source directory.")
257        print(e)
258        return {}
259    stdout = run_command(["git", "describe", "--tags", "--dirty", "--always"],
260                         cwd=source_dir)
261    if stdout is None:
262        # run_command already complained.
263        return {}
264    stdout = stdout.decode("ascii")
265    if not stdout.startswith(tag_prefix):
266        print("Warning: tag %r doesn't start with prefix %r." % (stdout, tag_prefix))
267        return {}
268    version = stdout[len(tag_prefix):]
269    pieces = version.split("-")
270    if len(pieces) == 1:
271        normalized_version = pieces[0]
272    else:
273        normalized_version = "%s.post%s" % (pieces[0], pieces[1])
274
275    stdout = run_command(["git", "rev-parse", "HEAD"], cwd=source_dir)
276    if stdout is None:
277        # run_command already complained.
278        return {}
279    full = stdout.decode("ascii").strip()
280    if version.endswith("-dirty"):
281        full += "-dirty"
282        normalized_version += ".dev0"
283
284    # Thanks to Jistanidiot at <http://stackoverflow.com/questions/6245570/get-current-branch-name>.
285    stdout = run_command(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=source_dir)
286    branch = (stdout or b"unknown").decode("ascii").strip()
287
288    # this returns native strings (bytes on py2, unicode on py3)
289    return {"version": version, "normalized": normalized_version,
290            "full": full, "branch": branch}
291
292# setup.cfg has an [aliases] section which runs "update_version" before many
293# commands (like "build" and "sdist") that need to know our package version
294# ahead of time. If you add different commands (or if we forgot some), you
295# may need to add it to setup.cfg and configure it to run update_version
296# before your command.
297
298class UpdateVersion(Command):
299    description = "update _version.py from revision-control metadata"
300    user_options = install.install.user_options
301
302    def initialize_options(self):
303        pass
304    def finalize_options(self):
305        pass
306    def run(self):
307        global version
308        verstr = version
309        if os.path.isdir(os.path.join(basedir, ".git")):
310            verstr = self.try_from_git()
311
312        if verstr:
313            self.distribution.metadata.version = verstr
314        else:
315            print("""\
316********************************************************************
317Warning: no version information found. This may cause tests to fail.
318********************************************************************
319""")
320
321    def try_from_git(self):
322        # If we change the release tag names, we must change this too
323        versions = versions_from_git("tahoe-lafs-")
324
325        # setup.py might be run by either py2 or py3 (when run by tox, which
326        # uses py3 on modern debian/ubuntu distros). We want this generated
327        # file to contain native strings on both (str=bytes in py2,
328        # str=unicode in py3)
329        if versions:
330            body = GIT_VERSION_BODY % {
331                "pkgname": self.distribution.get_name(),
332                "version": versions["version"],
333                "normalized": versions["normalized"],
334                "full": versions["full"],
335                "branch": versions["branch"],
336                }
337            f = open(VERSION_PY_FILENAME, "wb")
338            f.write(body.encode("ascii"))
339            f.close()
340            print("Wrote normalized version %r into '%s'" % (versions["normalized"], VERSION_PY_FILENAME))
341
342        return versions.get("normalized", None)
343
344class PleaseUseTox(Command):
345    user_options = []
346    def initialize_options(self):
347        pass
348    def finalize_options(self):
349        pass
350
351    def run(self):
352        print("ERROR: Please use 'tox' to run the test suite.")
353        sys.exit(1)
354
355setup_args = {}
356if version:
357    setup_args["version"] = version
358
359setup(name="tahoe-lafs", # also set in __init__.py
360      description='secure, decentralized, fault-tolerant file store',
361      long_description=open('README.rst', 'r', encoding='utf-8').read(),
362      author='the Tahoe-LAFS project',
363      author_email='tahoe-dev@tahoe-lafs.org',
364      url='https://tahoe-lafs.org/',
365      license='GNU GPL', # see README.rst -- there is an alternative licence
366      cmdclass={"update_version": UpdateVersion,
367                "test": PleaseUseTox,
368                },
369      package_dir = {'':'src'},
370      packages=find_packages('src') + ['allmydata.test.plugins'],
371      classifiers=trove_classifiers,
372      # We support Python 2.7, and we're working on support for 3.6 (the
373      # highest version that PyPy currently supports).
374      python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*",
375      install_requires=install_requires,
376      extras_require={
377          # Duplicate the Twisted pywin32 dependency here.  See
378          # https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2392 for some
379          # discussion.
380          ':sys_platform=="win32"': ["pywin32 != 226"],
381          "test": [
382              "flake8",
383              # Pin a specific pyflakes so we don't have different folks
384              # disagreeing on what is or is not a lint issue.  We can bump
385              # this version from time to time, but we will do it
386              # intentionally.
387              "pyflakes == 2.2.0",
388              "coverage ~= 5.0",
389              "mock",
390              "tox",
391              "pytest",
392              "pytest-twisted",
393              # XXX: decorator isn't a direct dependency, but pytest-twisted
394              # depends on decorator, and decorator 5.x isn't compatible with
395              # Python 2.7.
396              "decorator < 5",
397              "hypothesis >= 3.6.1",
398              "treq",
399              "towncrier",
400              "testtools",
401              "fixtures",
402              "beautifulsoup4",
403              "html5lib",
404              "junitxml",
405              "tenacity",
406              "paramiko",
407              "pytest-timeout",
408          ] + tor_requires + i2p_requires,
409          "tor": tor_requires,
410          "i2p": i2p_requires,
411      },
412      package_data={"allmydata.web": ["*.xhtml",
413                                      "static/*.js", "static/*.png", "static/*.css",
414                                      "static/img/*.png",
415                                      "static/css/*.css",
416                                      ],
417                    "allmydata": ["ported-modules.txt"],
418                    },
419      include_package_data=True,
420      setup_requires=setup_requires,
421      entry_points = { 'console_scripts': [ 'tahoe = allmydata.scripts.runner:run' ] },
422      **setup_args
423      )
Note: See TracBrowser for help on using the repository browser.