Changeset a0a39d3 in trunk


Ignore:
Timestamp:
2020-11-26T02:27:49Z (5 years ago)
Author:
meejah <meejah@…>
Branches:
master
Children:
4450a7a4
Parents:
da0fe23 (diff), fba386c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge remote-tracking branch 'origin/master' into 2916.grid-manager-proposal.5

Files:
13 added
3 deleted
29 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified .github/workflows/ci.yml

    rda0fe23 ra0a39d3  
    2222    steps:
    2323
    24       # Get vcpython27 on Windows + Python 2.7, to build zfec
     24      # Get vcpython27 on Windows + Python 2.7, to build netifaces
    2525      # extension.  See https://chocolatey.org/packages/vcpython27 and
    2626      # https://github.com/crazy-max/ghaction-chocolatey
     
    7979    steps:
    8080
     81      # Get vcpython27 for Windows + Python 2.7, to build netifaces
     82      # extension.  See https://chocolatey.org/packages/vcpython27 and
     83      # https://github.com/crazy-max/ghaction-chocolatey
     84      - name: Install MSVC 9.0 for Python 2.7 [Windows]
     85        if: matrix.os == 'windows-latest' && matrix.python-version == '2.7'
     86        uses: crazy-max/ghaction-chocolatey@v1
     87        with:
     88          args: install vcpython27
     89
    8190      - name: Install Tor [Ubuntu]
    8291        if: matrix.os == 'ubuntu-latest'
     
    92101        with:
    93102          args: install tor
    94 
    95       - name: Install MSVC 9.0 for Python 2.7 [Windows]
    96         if: matrix.os == 'windows-latest' && matrix.python-version == '2.7'
    97         uses: crazy-max/ghaction-chocolatey@v1
    98         with:
    99           args: install vcpython27
    100103
    101104      - name: Check out Tahoe-LAFS sources
     
    142145    steps:
    143146
    144       # Get vcpython27 on Windows + Python 2.7, to build zfec
     147      # Get vcpython27 for Windows + Python 2.7, to build netifaces
    145148      # extension.  See https://chocolatey.org/packages/vcpython27 and
    146149      # https://github.com/crazy-max/ghaction-chocolatey
  • TabularUnified docs/INSTALL.rst

    rda0fe23 ra0a39d3  
    4040
    4141If you are on a Mac, you can either follow these instructions, or use the
    42 pre-packaged bundle described in :doc:`OS-X`. The Tahoe project hosts
    43 pre-compiled "wheels" for all dependencies, so use the ``--find-links=``
    44 option described below to avoid needing a compiler.
     42pre-packaged bundle described in :doc:`OS-X`.
    4543
    4644Many Linux distributions include Tahoe-LAFS packages. Debian and Ubuntu users
     
    5553
    5654If you don't use a pre-packaged copy of Tahoe, you can build it yourself.
    57 You'll need Python2.7, pip, and virtualenv. On unix-like platforms, you will
    58 need a C compiler, the Python development headers, and some libraries
    59 (libffi-dev and libssl-dev).
     55You'll need Python2.7, pip, and virtualenv.
     56Tahoe-LAFS depends on some libraries which require a C compiler to build.
     57However, for many platforms, PyPI hosts already-built packages of libraries.
     58
     59If there is no already-built package for your platform,
     60you will need a C compiler,
     61the Python development headers,
     62and some libraries (libffi-dev and libssl-dev).
    6063
    6164On a modern Debian/Ubuntu-derived distribution, this command will get you
     
    6568
    6669On OS-X, install pip and virtualenv as described below. If you want to
    67 compile the dependencies yourself (instead of using ``--find-links`` to take
    68 advantage of the pre-compiled ones we host), you'll also need to install
     70compile the dependencies yourself, you'll also need to install
    6971Xcode and its command-line tools.
    7072
     
    151153 New python executable in ~/venv/bin/python2.7
    152154 Installing setuptools, pip, wheel...done.
    153  
     155
    154156 % venv/bin/pip install -U pip setuptools
    155157 Downloading/unpacking pip from https://pypi.python.org/...
    156158 ...
    157159 Successfully installed pip setuptools
    158  
     160
    159161 % venv/bin/pip install tahoe-lafs
    160162 Collecting tahoe-lafs
     
    162164 Installing collected packages: ...
    163165 Successfully installed ...
    164  
     166
    165167 % venv/bin/tahoe --version
    166168 tahoe-lafs: 1.14.0
    167169 foolscap: ...
    168  
     170
    169171 %
    170 
    171 On OS-X, instead of ``pip install tahoe-lafs``, use this command to take
    172 advantage of the hosted pre-compiled wheels::
    173 
    174  venv/bin/pip install --find-links=https://tahoe-lafs.org/deps tahoe-lafs
    175 
    176172
    177173Install From a Source Tarball
     
    183179 New python executable in ~/venv/bin/python2.7
    184180 Installing setuptools, pip, wheel...done.
    185  
     181
    186182 % venv/bin/pip install https://tahoe-lafs.org/downloads/tahoe-lafs-1.14.0.tar.bz2
    187183 Collecting https://tahoe-lafs.org/downloads/tahoe-lafs-1.14.0.tar.bz2
     
    189185 Installing collected packages: ...
    190186 Successfully installed ...
    191  
     187
    192188 % venv/bin/tahoe --version
    193189 tahoe-lafs: 1.14.0
     
    214210
    215211 % git clone https://github.com/tahoe-lafs/tahoe-lafs.git
    216  
     212
    217213 % cd tahoe-lafs
    218  
     214
    219215 % virtualenv venv
    220  
     216
    221217 % venv/bin/pip install --editable .[test]
    222218 Obtaining file::~/tahoe-lafs
    223219 ...
    224220 Successfully installed ...
    225  
     221
    226222 % venv/bin/tahoe --version
    227223 tahoe-lafs: 1.14.0.post34.dev0
     
    283279  ...
    284280 Ran 1186 tests in 423.179s
    285  
     281
    286282 PASSED (skips=7, expectedFailures=3, successes=1176)
    287283 __________________________ summary ___________________________________
  • TabularUnified docs/windows.rst

    rda0fe23 ra0a39d3  
    3434into this virtualenv::
    3535
    36     PS C:\Users\me> venv\Scripts\pip install --find-links=https://tahoe-lafs.org/deps/ tahoe-lafs
     36    PS C:\Users\me> venv\Scripts\pip install tahoe-lafs
    3737    Collecting tahoe-lafs
    3838    ...
     
    7070git checkout)::
    7171
    72     $ venv\Scripts\pip install --find-links=https://tahoe-lafs.org/deps/ .
     72    $ venv\Scripts\pip install .
    7373
    7474If you're planning to hack on the source code, you might want to add
     
    7878------------
    7979
    80 Tahoe-LAFS depends upon several packages that use compiled C code
    81 (such as zfec). This code must be built separately for each platform
    82 (Windows, OS-X, and different flavors of Linux).
    83 
    84 Pre-compiled "wheels" of all Tahoe's dependencies are hosted on the
    85 tahoe-lafs.org website in the ``deps/`` directory. The ``--find-links=``
    86 argument (used in the examples above) instructs ``pip`` to look at that URL
    87 for dependencies. This should avoid the need for anything to be compiled
    88 during the install.
     80Tahoe-LAFS depends upon several packages that use compiled C code (such as zfec).
     81This code must be built separately for each platform (Windows, OS-X, and different flavors of Linux).
     82Fortunately, this is now done by upstream packages for most platforms.
     83The result is that a C compiler is usually not required to install Tahoe-LAFS.
  • TabularUnified integration/util.py

    rda0fe23 ra0a39d3  
    258258            config_path = join(node_dir, 'tahoe.cfg')
    259259            config = get_config(config_path)
    260             set_config(config, 'node', 'log_gatherer.furl', flog_gatherer)
     260            set_config(
     261                config,
     262                u'node',
     263                u'log_gatherer.furl',
     264                flog_gatherer.decode("utf-8"),
     265            )
    261266            write_config(config_path, config)
    262267        created_d.addCallback(created)
  • TabularUnified nix/overlays.nix

    rda0fe23 ra0a39d3  
    1616      # is too old.
    1717      pyutil = python-super.callPackage ./pyutil.nix { };
     18
     19      # Need a newer version of Twisted, too.
     20      twisted = python-super.callPackage ./twisted.nix { };
    1821    };
    1922  };
  • TabularUnified setup.py

    rda0fe23 ra0a39d3  
    9999    #   specified by Twisted[conch].  Since this would be the *whole point* of
    100100    #   an sftp extra in Tahoe-LAFS, there is no point in having one.
    101     "Twisted[tls,conch] >= 18.4.0",
     101    # * Twisted 19.10 introduces Site.getContentFile which we use to get
     102    #   temporary upload files placed into a per-node temporary directory.
     103    "Twisted[tls,conch] >= 19.10.0",
    102104
    103105    "PyYAML >= 3.11",
  • TabularUnified src/allmydata/client.py

    rda0fe23 ra0a39d3  
    3939    hashutil, base32, pollmixin, log, idlib,
    4040    yamlutil, configutil,
     41    fileutil,
    4142)
    4243from allmydata.util.encodingutil import get_filesystem_encoding
     
    520521            str(allmydata.__full_version__),
    521522            str(_Client.OLDEST_SUPPORTED_VERSION),
    522             list(node.get_app_versions()),
    523523            partial(_sequencer, config),
    524524            introducer_cache_filepath,
     
    10711071        self._key_generator.set_default_keysize(keysize)
    10721072
     1073    def _get_tempdir(self):
     1074        """
     1075        Determine the path to the directory where temporary files for this node
     1076        should be written.
     1077
     1078        :return bytes: The path which will exist and be a directory.
     1079        """
     1080        tempdir_config = self.config.get_config("node", "tempdir", "tmp")
     1081        if isinstance(tempdir_config, bytes):
     1082            tempdir_config = tempdir_config.decode('utf-8')
     1083        tempdir = self.config.get_config_path(tempdir_config)
     1084        if not os.path.exists(tempdir):
     1085            fileutil.make_dirs(tempdir)
     1086        return tempdir
     1087
    10731088    def init_web(self, webport):
    10741089        self.log("init_web(webport=%s)", args=(webport,))
     
    10781093        staticdir_config = self.config.get_config("node", "web.static", "public_html")
    10791094        staticdir = self.config.get_config_path(staticdir_config)
    1080         ws = WebishServer(self, webport, nodeurl_path, staticdir)
     1095        ws = WebishServer(
     1096            self,
     1097            webport,
     1098            self._get_tempdir(),
     1099            nodeurl_path,
     1100            staticdir,
     1101        )
    10811102        ws.setServiceParent(self)
    10821103
  • TabularUnified src/allmydata/introducer/client.py

    rda0fe23 ra0a39d3  
    2525    def __init__(self, tub, introducer_furl,
    2626                 nickname, my_version, oldest_supported,
    27                  app_versions, sequencer, cache_filepath):
     27                 sequencer, cache_filepath):
    2828        self._tub = tub
    2929        self.introducer_furl = introducer_furl
     
    3333        self._my_version = my_version
    3434        self._oldest_supported = oldest_supported
    35         self._app_versions = app_versions
    3635        self._sequencer = sequencer
    3736        self._cache_filepath = cache_filepath
    3837
    39         self._my_subscriber_info = {
    40             "version": 0,
    41             "nickname": self._nickname,
    42             "app-versions": self._app_versions,
    43             "my-version": self._my_version,
    44             "oldest-supported": self._oldest_supported,
    45         }
     38        self._my_subscriber_info = { "version": 0,
     39                                     "nickname": self._nickname,
     40                                     "app-versions": [],
     41                                     "my-version": self._my_version,
     42                                     "oldest-supported": self._oldest_supported,
     43                                     }
    4644
    4745        self._outbound_announcements = {} # not signed
     
    192190                  # publish(), each time we make a change
    193191                  "nickname": self._nickname,
    194                   "app-versions": self._app_versions,
     192                  "app-versions": [],
    195193                  "my-version": self._my_version,
    196194                  "oldest-supported": self._oldest_supported,
  • TabularUnified src/allmydata/mutable/layout.py

    rda0fe23 ra0a39d3  
     1"""
     2Ported to Python 3.
     3"""
     4from __future__ import absolute_import
     5from __future__ import division
     6from __future__ import print_function
     7from __future__ import unicode_literals
     8
     9from future.utils import PY2
     10if PY2:
     11    # Omit dict so Python 3 changes don't leak into API callers on Python 2.
     12    from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, list, object, range, str, max, min  # noqa: F401
    113from past.utils import old_div
    214
     
    17451757
    17461758    def _read(self, readvs, force_remote=False):
    1747         unsatisfiable = list(filter(lambda x: x[0] + x[1] > len(self._data), readvs))
     1759        unsatisfiable = [x for x in readvs if x[0] + x[1] > len(self._data)]
    17481760        # TODO: It's entirely possible to tweak this so that it just
    17491761        # fulfills the requests that it can, and not demand that all
  • TabularUnified src/allmydata/mutable/repairer.py

    rda0fe23 ra0a39d3  
     1"""
     2Ported to Python 3.
     3"""
     4from __future__ import absolute_import
     5from __future__ import division
     6from __future__ import print_function
     7from __future__ import unicode_literals
     8
     9from future.utils import PY2
     10if PY2:
     11    from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min  # noqa: F401
    112
    213from zope.interface import implementer
  • TabularUnified src/allmydata/mutable/retrieve.py

    rda0fe23 ra0a39d3  
    1 from past.builtins import unicode
     1"""
     2Ported to Python 3.
     3"""
     4from __future__ import absolute_import
     5from __future__ import division
     6from __future__ import print_function
     7from __future__ import unicode_literals
     8
     9from future.utils import PY2
     10if PY2:
     11    # Don't import bytes and str, to prevent API leakage
     12    from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, dict, list, object, range, max, min  # noqa: F401
    213
    314import time
     
    750761        blockhashes = dict(enumerate(blockhashes))
    751762        self.log("the reader gave me the following blockhashes: %s" % \
    752                  blockhashes.keys())
     763                 list(blockhashes.keys()))
    753764        self.log("the reader gave me the following sharehashes: %s" % \
    754                  sharehashes.keys())
     765                 list(sharehashes.keys()))
    755766        bht = self._block_hash_trees[reader.shnum]
    756767
     
    909920
    910921    def notify_server_corruption(self, server, shnum, reason):
    911         if isinstance(reason, unicode):
     922        if isinstance(reason, str):
    912923            reason = reason.encode("utf-8")
    913924        storage_server = server.get_storage_server()
  • TabularUnified src/allmydata/mutable/servermap.py

    rda0fe23 ra0a39d3  
     1"""
     2Ported to Python 3.
     3"""
    14from __future__ import print_function
    2 
     5from __future__ import absolute_import
     6from __future__ import division
     7from __future__ import unicode_literals
     8
     9from future.utils import PY2
     10if PY2:
     11    # Doesn't import str to prevent API leakage on Python 2
     12    from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, max, min  # noqa: F401
    313from past.builtins import unicode
    414
     
    189199        print("servermap:", file=out)
    190200
    191         for ( (server, shnum), (verinfo, timestamp) ) in self._known_shares.items():
     201        for ( (server, shnum), (verinfo, timestamp) ) in list(self._known_shares.items()):
    192202            (seqnum, root_hash, IV, segsize, datalength, k, N, prefix,
    193203             offsets_tuple) = verinfo
     
    227237        timestamp) tuples."""
    228238        versionmap = DictOfSets()
    229         for ( (server, shnum), (verinfo, timestamp) ) in self._known_shares.items():
     239        for ( (server, shnum), (verinfo, timestamp) ) in list(self._known_shares.items()):
    230240            versionmap.add(verinfo, (shnum, server, timestamp))
    231241        return versionmap
     
    246256        versionmap = self.make_versionmap()
    247257        all_shares = {}
    248         for verinfo, shares in versionmap.items():
     258        for verinfo, shares in list(versionmap.items()):
    249259            s = set()
    250260            for (shnum, server, timestamp) in shares:
     
    272282        versionmap = self.make_versionmap()
    273283        bits = []
    274         for (verinfo, shares) in versionmap.items():
     284        for (verinfo, shares) in list(versionmap.items()):
    275285            vstr = self.summarize_version(verinfo)
    276286            shnums = set([shnum for (shnum, server, timestamp) in shares])
     
    283293        versionmap = self.make_versionmap()
    284294        recoverable_versions = set()
    285         for (verinfo, shares) in versionmap.items():
     295        for (verinfo, shares) in list(versionmap.items()):
    286296            (seqnum, root_hash, IV, segsize, datalength, k, N, prefix,
    287297             offsets_tuple) = verinfo
     
    299309
    300310        unrecoverable_versions = set()
    301         for (verinfo, shares) in versionmap.items():
     311        for (verinfo, shares) in list(versionmap.items()):
    302312            (seqnum, root_hash, IV, segsize, datalength, k, N, prefix,
    303313             offsets_tuple) = verinfo
     
    333343        unrecoverable = set()
    334344        highest_recoverable_seqnum = -1
    335         for (verinfo, shares) in versionmap.items():
     345        for (verinfo, shares) in list(versionmap.items()):
    336346            (seqnum, root_hash, IV, segsize, datalength, k, N, prefix,
    337347             offsets_tuple) = verinfo
     
    668678        ds = []
    669679
    670         for shnum,datav in datavs.items():
     680        for shnum,datav in list(datavs.items()):
    671681            data = datav[0]
    672682            reader = MDMFSlotReadProxy(ss,
  • TabularUnified src/allmydata/node.py

    rda0fe23 ra0a39d3  
    2020import types
    2121import errno
    22 import tempfile
    2322from base64 import b32decode, b32encode
    2423
     
    2928from twisted.application import service
    3029from twisted.python.failure import Failure
    31 from twisted.python.compat import nativeString
    32 from foolscap.api import Tub, app_versions
     30from foolscap.api import Tub
     31
    3332import foolscap.logging.log
    34 from allmydata.version_checks import get_package_versions, get_package_versions_string
     33
    3534from allmydata.util import log
    3635from allmydata.util import fileutil, iputil
    37 from allmydata.util.assertutil import _assert
    3836from allmydata.util.fileutil import abspath_expanduser_unicode
    3937from allmydata.util.encodingutil import get_filesystem_encoding, quote_output
    4038from allmydata.util import configutil
     39
     40from . import (
     41    __full_version__,
     42)
    4143
    4244def _common_valid_config():
     
    8082    })
    8183
    82 # Add our application versions to the data that Foolscap's LogPublisher
    83 # reports.
    84 for thing, things_version in list(get_package_versions().items()):
    85     app_versions.add_version(thing, things_version)
    86 
    8784# group 1 will be addr (dotted quad string), group 3 if any will be portnum (string)
    8885ADDR_RE = re.compile("^([1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*)(:([1-9][0-9]*))?$")
     
    233230        """
    234231    return _Config(parser, portnumfile, basedir, fname, write_new_config)
    235 
    236 
    237 def get_app_versions():
    238     """
    239     :returns: dict of versions important to Foolscap
    240     """
    241     return dict(app_versions.versions)
    242232
    243233
     
    833823        self._tor_provider = tor_provider
    834824
    835         self.init_tempdir()
    836 
    837825        self.create_log_tub()
    838826        self.logSource = "Node"
     
    852840            self.control_tub.setServiceParent(self)
    853841
    854         self.log("Node constructed. " + get_package_versions_string())
     842        self.log("Node constructed. " + __full_version__)
    855843        iputil.increase_rlimits()
    856844
     
    860848        """
    861849        return len(self.tub.getListeners()) > 0
    862 
    863     def init_tempdir(self):
    864         """
    865         Initialize/create a directory for temporary files.
    866         """
    867         tempdir_config = self.config.get_config("node", "tempdir", "tmp")
    868         if isinstance(tempdir_config, bytes):
    869             tempdir_config = tempdir_config.decode('utf-8')
    870         tempdir = self.config.get_config_path(tempdir_config)
    871         if not os.path.exists(tempdir):
    872             fileutil.make_dirs(tempdir)
    873         tempfile.tempdir = nativeString(tempdir)
    874         # this should cause twisted.web.http (which uses
    875         # tempfile.TemporaryFile) to put large request bodies in the given
    876         # directory. Without this, the default temp dir is usually /tmp/,
    877         # which is frequently too small.
    878         temp_fd, test_name = tempfile.mkstemp()
    879         _assert(os.path.dirname(test_name) == tempdir, test_name, tempdir)
    880         os.close(temp_fd)  # avoid leak of unneeded fd
    881850
    882851    # pull this outside of Node's __init__ too, see:
  • TabularUnified src/allmydata/scripts/runner.py

    rda0fe23 ra0a39d3  
    88from twisted.internet import defer, task, threads
    99
    10 from allmydata.version_checks import get_package_versions_string
    1110from allmydata.scripts.common import get_default_nodedir
    1211from allmydata.scripts import debug, create_node, cli, \
     
    2019)
    2120
     21from .. import (
     22    __full_version__,
     23)
     24
    2225_default_nodedir = get_default_nodedir()
    2326
     
    7881
    7982    def opt_version(self):
    80         print(get_package_versions_string(debug=True), file=self.stdout)
     83        print(__full_version__, file=self.stdout)
    8184        self.no_command_needed = True
    8285
    83     def opt_version_and_path(self):
    84         print(get_package_versions_string(show_paths=True, debug=True), file=self.stdout)
    85         self.no_command_needed = True
     86    opt_version_and_path = opt_version
    8687
    8788    opt_eliot_destination = opt_eliot_destination
  • TabularUnified src/allmydata/test/cli/test_cli.py

    rda0fe23 ra0a39d3  
    12671267        stdout = StringIO()
    12681268        self.failUnlessRaises(SystemExit, self.parse, ["--version"], stdout)
    1269         self.failUnlessIn(allmydata.__appname__ + ":", stdout.getvalue())
     1269        self.failUnlessIn(allmydata.__full_version__, stdout.getvalue())
    12701270        # but "tahoe SUBCOMMAND --version" should be rejected
    12711271        self.failUnlessRaises(usage.UsageError, self.parse,
  • TabularUnified src/allmydata/test/common.py

    rda0fe23 ra0a39d3  
    111111    my_version = attr.ib()
    112112    oldest_supported = attr.ib()
    113     app_versions = attr.ib()
    114113    sequencer = attr.ib()
    115114    cache_filepath = attr.ib()
     
    11521151    * trial-compatible mktemp method
    11531152    * unittest2-compatible assertRaises helper
    1154     * Automatic cleanup of tempfile.tempdir mutation (pervasive through the
    1155       Tahoe-LAFS test suite).
     1153    * Automatic cleanup of tempfile.tempdir mutation (once pervasive through
     1154      the Tahoe-LAFS test suite, perhaps gone now but someone should verify
     1155      this).
    11561156    """
    11571157    def setUp(self):
  • TabularUnified src/allmydata/test/no_network.py

    rda0fe23 ra0a39d3  
    362362        """
    363363        if self._setup_errors:
    364             raise self._setup_errors[0].value
     364            self._setup_errors[0].raiseException()
    365365
    366366    @defer.inlineCallbacks
  • TabularUnified src/allmydata/test/test_client.py

    rda0fe23 ra0a39d3  
    4242from allmydata.node import OldConfigError, UnescapedHashError, create_node_dir
    4343from allmydata.frontends.auth import NeedRootcapLookupScheme
    44 from allmydata.version_checks import (
    45     get_package_versions_string,
    46 )
    4744from allmydata import client
    4845from allmydata.storage_client import (
     
    622619        self.failUnless("." in str(allmydata.__full_version__),
    623620                        "non-numeric version in '%s'" % allmydata.__version__)
    624         all_versions = get_package_versions_string()
    625         self.failUnless(allmydata.__appname__ in all_versions)
    626621        # also test stats
    627622        stats = c.get_stats()
  • TabularUnified src/allmydata/test/test_introducer.py

    rda0fe23 ra0a39d3  
    156156    def test_create(self):
    157157        ic = IntroducerClient(None, "introducer.furl", u"my_nickname",
    158                               "my_version", "oldest_version", {}, fakeseq,
     158                              "my_version", "oldest_version", fakeseq,
    159159                              FilePath(self.mktemp()))
    160160        self.failUnless(isinstance(ic, IntroducerClient))
     
    189189        ic1 = IntroducerClient(None,
    190190                               "introducer.furl", u"my_nickname",
    191                                "ver23", "oldest_version", {}, fakeseq,
     191                               "ver23", "oldest_version", fakeseq,
    192192                               FilePath(self.mktemp()))
    193193        # we use a second client just to create a different-looking
     
    195195        ic2 = IntroducerClient(None,
    196196                               "introducer.furl", u"my_nickname",
    197                                "ver24","oldest_version",{}, fakeseq,
     197                               "ver24","oldest_version",fakeseq,
    198198                               FilePath(self.mktemp()))
    199199        announcements = []
     
    299299        ic1 = IntroducerClient(None,
    300300                               "introducer.furl", u"my_nickname",
    301                                "ver23", "oldest_version", {}, realseq,
     301                               "ver23", "oldest_version", realseq,
    302302                               FilePath(self.mktemp()))
    303303        furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:36106/gydnp"
     
    397397        tub2.setServiceParent(self.parent)
    398398        c = IntroducerClient(tub2, ifurl,
    399                              u"nickname", "version", "oldest", {}, fakeseq,
     399                             u"nickname", "version", "oldest", fakeseq,
    400400                             FilePath(self.mktemp()))
    401401        furl1 = "pb://onug64tu@127.0.0.1:123/short" # base32("short")
     
    478478                                 NICKNAME % str(i),
    479479                                 "version", "oldest",
    480                                  {"component": "component-v1"}, fakeseq,
     480                                 fakeseq,
    481481                                 FilePath(self.mktemp()))
    482482            received_announcements[c] = {}
     
    738738        introducer = IntroducerService()
    739739        tub = introducer_furl = None
    740         app_versions = {"whizzy": "fizzy"}
    741740        client_v2 = IntroducerClient(tub, introducer_furl, NICKNAME % u"v2",
    742                                      "my_version", "oldest", app_versions,
     741                                     "my_version", "oldest",
    743742                                     fakeseq, FilePath(self.mktemp()))
    744743        #furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
     
    752751        s0 = subs[0]
    753752        self.failUnlessEqual(s0.service_name, "storage")
    754         self.failUnlessEqual(s0.app_versions, app_versions)
    755753        self.failUnlessEqual(s0.nickname, NICKNAME % u"v2")
    756754        self.failUnlessEqual(s0.version, "my_version")
     
    761759        introducer = IntroducerService()
    762760        tub = introducer_furl = None
    763         app_versions = {"whizzy": "fizzy"}
    764761        client_v2 = IntroducerClient(tub, introducer_furl, u"nick-v2",
    765                                      "my_version", "oldest", app_versions,
     762                                     "my_version", "oldest",
    766763                                     fakeseq, FilePath(self.mktemp()))
    767764        furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
     
    777774        self.assertThat(a[0].canary, Is(canary0))
    778775        self.failUnlessEqual(a[0].index, ("storage", public_key_str))
    779         self.failUnlessEqual(a[0].announcement["app-versions"], app_versions)
    780776        self.failUnlessEqual(a[0].nickname, u"nick-v2")
    781777        self.failUnlessEqual(a[0].service_name, "storage")
     
    855851        yield flushEventualQueue()
    856852        ic2 = IntroducerClient(None, "introducer.furl", u"my_nickname",
    857                                "my_version", "oldest_version", {}, fakeseq,
     853                               "my_version", "oldest_version", fakeseq,
    858854                               ic._cache_filepath)
    859855        announcements = {}
     
    955951        listenOnUnused(tub)
    956952        c = IntroducerClient(tub, self.introducer_furl,
    957                              u"nickname-client", "version", "oldest", {},
     953                             u"nickname-client", "version", "oldest",
    958954                             fakeseq, FilePath(self.mktemp()))
    959955        announcements = {}
     
    10281024            "0.0.0",
    10291025            "1.2.3",
    1030             {},
    10311026            (0, u"i am a nonce"),
    10321027            "invalid",
  • TabularUnified src/allmydata/test/test_log.py

    rda0fe23 ra0a39d3  
    1010from __future__ import print_function
    1111
    12 from future.utils import PY2
     12from future.utils import PY2, native_str
    1313if PY2:
    1414    from builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min  # noqa: F401
     
    155155        self.assertEqual([m[2] for m in self.messages],
    156156                         ["grand", "par1", "par2", "msg1", "msg1"])
     157
     158    def test_native_string_keys(self):
     159        """Keyword argument keys are all native strings."""
     160        class LoggingObject17(tahoe_log.PrefixingLogMixin):
     161            pass
     162
     163        obj = LoggingObject17()
     164        # Native string by default:
     165        obj.log(hello="world")
     166        # Will be Unicode on Python 2:
     167        obj.log(**{"my": "message"})
     168        for message in self.messages:
     169            for k in message[-1].keys():
     170                self.assertIsInstance(k, native_str)
  • TabularUnified src/allmydata/test/test_runner.py

    rda0fe23 ra0a39d3  
    1313from twisted.internet.defer import (
    1414    inlineCallbacks,
    15     returnValue,
    1615    DeferredList,
    1716)
     
    2120)
    2221from allmydata.util import fileutil, pollmixin
    23 from allmydata.util.encodingutil import unicode_to_argv, unicode_to_output, \
    24     get_filesystem_encoding
     22from allmydata.util.encodingutil import unicode_to_argv, unicode_to_output
    2523from allmydata.test import common_util
    26 from allmydata.version_checks import normalized_version
    2724import allmydata
    28 from allmydata import __appname__
    2925from .common_util import parse_cli, run_cli
    3026from .cli_node_api import (
     
    5955
    6056class RunBinTahoeMixin(object):
    61 
    62     @inlineCallbacks
    63     def find_import_location(self):
    64         res = yield self.run_bintahoe(["--version-and-path"])
    65         out, err, rc_or_sig = res
    66         self.assertEqual(rc_or_sig, 0, res)
    67         lines = out.splitlines()
    68         tahoe_pieces = lines[0].split()
    69         self.assertEqual(tahoe_pieces[0], "%s:" % (__appname__,), (tahoe_pieces, res))
    70         returnValue(tahoe_pieces[-1].strip("()"))
    71 
    7257    def run_bintahoe(self, args, stdin=None, python_options=[], env=None):
    7358        command = sys.executable
     
    8772
    8873class BinTahoe(common_util.SignalMixin, unittest.TestCase, RunBinTahoeMixin):
    89     @inlineCallbacks
    90     def test_the_right_code(self):
    91         # running "tahoe" in a subprocess should find the same code that
    92         # holds this test file, else something is weird
    93         test_path = os.path.dirname(os.path.dirname(os.path.normcase(os.path.realpath(srcfile))))
    94         bintahoe_import_path = yield self.find_import_location()
    95 
    96         same = (bintahoe_import_path == test_path)
    97         if not same:
    98             msg = ("My tests and my 'tahoe' executable are using different paths.\n"
    99                    "tahoe: %r\n"
    100                    "tests: %r\n"
    101                    "( according to the test source filename %r)\n" %
    102                    (bintahoe_import_path, test_path, srcfile))
    103 
    104             if (not isinstance(rootdir, unicode) and
    105                 rootdir.decode(get_filesystem_encoding(), 'replace') != rootdir):
    106                 msg += ("However, this may be a false alarm because the import path\n"
    107                         "is not representable in the filesystem encoding.")
    108                 raise unittest.SkipTest(msg)
    109             else:
    110                 msg += "Please run the tests in a virtualenv that includes both the Tahoe-LAFS library and the 'tahoe' executable."
    111                 self.fail(msg)
    112 
    113     def test_path(self):
    114         d = self.run_bintahoe(["--version-and-path"])
    115         def _cb(res):
    116             out, err, rc_or_sig = res
    117             self.failUnlessEqual(rc_or_sig, 0, str(res))
    118 
    119             # Fail unless the __appname__ package is *this* version *and*
    120             # was loaded from *this* source directory.
    121 
    122             required_verstr = str(allmydata.__version__)
    123 
    124             self.failIfEqual(required_verstr, "unknown",
    125                              "We don't know our version, because this distribution didn't come "
    126                              "with a _version.py and 'setup.py update_version' hasn't been run.")
    127 
    128             srcdir = os.path.dirname(os.path.dirname(os.path.normcase(os.path.realpath(srcfile))))
    129             info = repr((res, allmydata.__appname__, required_verstr, srcdir))
    130 
    131             appverpath = out.split(')')[0]
    132             (appverfull, path) = appverpath.split('] (')
    133             (appver, comment) = appverfull.split(' [')
    134             (branch, full_version) = comment.split(': ')
    135             (app, ver) = appver.split(': ')
    136 
    137             self.failUnlessEqual(app, allmydata.__appname__, info)
    138             norm_ver = normalized_version(ver)
    139             norm_required = normalized_version(required_verstr)
    140             self.failUnlessEqual(norm_ver, norm_required, info)
    141             self.failUnlessEqual(path, srcdir, info)
    142             self.failUnlessEqual(branch, allmydata.branch)
    143             self.failUnlessEqual(full_version, allmydata.full_version)
    144         d.addCallback(_cb)
    145         return d
    146 
    14774    def test_unicode_arguments_and_output(self):
    14875        tricky = u"\u2621"
     
    16693        def _cb(res):
    16794            out, err, rc_or_sig = res
    168             self.failUnlessEqual(rc_or_sig, 0, str(res))
    169             self.failUnless(out.startswith(allmydata.__appname__+':'), str(res))
     95            self.assertEqual(rc_or_sig, 0, str(res))
     96            self.assertTrue(out.startswith(allmydata.__appname__ + '/'), str(res))
    17097        d.addCallback(_cb)
    17198        return d
  • TabularUnified src/allmydata/test/web/test_introducer.py

    rda0fe23 ra0a39d3  
    128128            self,
    129129            soup,
    130             u"%s: %s" % (allmydata.__appname__, allmydata.__version__),
     130            allmydata.__full_version__,
    131131        )
    132132        assert_soup_has_text(self, soup, u"no peers!")
  • TabularUnified src/allmydata/test/web/test_web.py

    rda0fe23 ra0a39d3  
    77from bs4 import BeautifulSoup
    88
     9from twisted.python.filepath import (
     10    FilePath,
     11)
    912from twisted.application import service
    1013from twisted.internet import defer
     
    317320        self.clock = Clock()
    318321        self.fakeTime = 86460 # 1d 0h 1m 0s
    319         self.ws = webish.WebishServer(self.s, "0", staticdir=self.staticdir,
    320                                       clock=self.clock, now_fn=lambda:self.fakeTime)
     322        tempdir = FilePath(self.mktemp())
     323        tempdir.makedirs()
     324        self.ws = webish.WebishServer(
     325            self.s,
     326            "0",
     327            tempdir=tempdir.path,
     328            staticdir=self.staticdir,
     329            clock=self.clock,
     330            now_fn=lambda:self.fakeTime,
     331        )
    321332        self.ws.setServiceParent(self.s)
    322333        self.webish_port = self.ws.getPortnum()
  • TabularUnified src/allmydata/test/web/test_webish.py

    rda0fe23 ra0a39d3  
    55from uuid import (
    66    uuid4,
     7)
     8from errno import (
     9    EACCES,
     10)
     11from io import (
     12    BytesIO,
     13)
     14
     15from hypothesis import (
     16    given,
     17)
     18from hypothesis.strategies import (
     19    integers,
    720)
    821
     
    1326    MatchesAll,
    1427    Not,
    15 )
    16 
     28    IsInstance,
     29    HasLength,
     30)
     31
     32from twisted.python.runtime import (
     33    platform,
     34)
    1735from twisted.python.filepath import (
    1836    FilePath,
     
    3149from ...webish import (
    3250    TahoeLAFSRequest,
    33     tahoe_lafs_site,
     51    TahoeLAFSSite,
    3452)
    3553
     
    97115class TahoeLAFSSiteTests(SyncTestCase):
    98116    """
    99     Tests for the ``Site`` created by ``tahoe_lafs_site``.
     117    Tests for ``TahoeLAFSSite``.
    100118    """
    101119    def _test_censoring(self, path, censored):
     
    113131        logPath = self.mktemp()
    114132
    115         site = tahoe_lafs_site(Resource(), logPath=logPath)
     133        site = TahoeLAFSSite(self.mktemp(), Resource(), logPath=logPath)
    116134        site.startFactory()
    117135
     
    170188            b"/uri?uri=[CENSORED]",
    171189        )
     190
     191    def _create_request(self, tempdir):
     192        """
     193        Create and return a new ``TahoeLAFSRequest`` hooked up to a
     194        ``TahoeLAFSSite``.
     195
     196        :param bytes tempdir: The temporary directory to give to the site.
     197
     198        :return TahoeLAFSRequest: The new request instance.
     199        """
     200        site = TahoeLAFSSite(tempdir.path, Resource(), logPath=self.mktemp())
     201        site.startFactory()
     202
     203        channel = DummyChannel()
     204        channel.site = site
     205        request = TahoeLAFSRequest(channel)
     206        return request
     207
     208    @given(integers(min_value=0, max_value=1024 * 1024 - 1))
     209    def test_small_content(self, request_body_size):
     210        """
     211        A request body smaller than 1 MiB is kept in memory.
     212        """
     213        tempdir = FilePath(self.mktemp())
     214        request = self._create_request(tempdir)
     215        request.gotLength(request_body_size)
     216        self.assertThat(
     217            request.content,
     218            IsInstance(BytesIO),
     219        )
     220
     221    def _large_request_test(self, request_body_size):
     222        """
     223        Assert that when a request with a body of of the given size is received
     224        its content is written to the directory the ``TahoeLAFSSite`` is
     225        configured with.
     226        """
     227        tempdir = FilePath(self.mktemp())
     228        tempdir.makedirs()
     229        request = self._create_request(tempdir)
     230
     231        # So.  Bad news.  The temporary file for the uploaded content is
     232        # unnamed (and this isn't even necessarily a bad thing since it is how
     233        # you get automatic on-process-exit cleanup behavior on POSIX).  It's
     234        # not visible by inspecting the filesystem.  It has no name we can
     235        # discover.  Then how do we verify it is written to the right place?
     236        # The question itself is meaningless if we try to be too precise.  It
     237        # *has* no filesystem location.  However, it is still stored *on* some
     238        # filesystem.  We still want to make sure it is on the filesystem we
     239        # specified because otherwise it might be on a filesystem that's too
     240        # small or undesirable in some other way.
     241        #
     242        # I don't know of any way to ask a file descriptor which filesystem
     243        # it's on, either, though.  It might be the case that the [f]statvfs()
     244        # result could be compared somehow to infer the filesystem but
     245        # ... it's not clear what the failure modes might be there, across
     246        # different filesystems and runtime environments.
     247        #
     248        # Another approach is to make the temp directory unwriteable and
     249        # observe the failure when an attempt is made to create a file there.
     250        # This is hardly a lovely solution but at least it's kind of simple.
     251        #
     252        # It would be nice if it worked consistently cross-platform but on
     253        # Windows os.chmod is more or less broken.
     254        if platform.isWindows():
     255            request.gotLength(request_body_size)
     256            self.assertThat(
     257                tempdir.children(),
     258                HasLength(1),
     259            )
     260        else:
     261            tempdir.chmod(0o550)
     262            with self.assertRaises(OSError) as ctx:
     263                request.gotLength(request_body_size)
     264                raise Exception(
     265                    "OSError not raised, instead tempdir.children() = {}".format(
     266                        tempdir.children(),
     267                    ),
     268                )
     269
     270            self.assertThat(
     271                ctx.exception.errno,
     272                Equals(EACCES),
     273            )
     274
     275    def test_unknown_request_size(self):
     276        """
     277        A request body with an unknown size is written to a file in the temporary
     278        directory passed to ``TahoeLAFSSite``.
     279        """
     280        self._large_request_test(None)
     281
     282    @given(integers(min_value=1024 * 1024))
     283    def test_large_request(self, request_body_size):
     284        """
     285        A request body of 1 MiB or more is written to a file in the temporary
     286        directory passed to ``TahoeLAFSSite``.
     287        """
     288        self._large_request_test(request_body_size)
     289
    172290
    173291def param(name, value):
  • TabularUnified src/allmydata/util/_python3.py

    rda0fe23 ra0a39d3  
    5757    "allmydata.mutable.common",
    5858    "allmydata.mutable.filenode",
     59    "allmydata.mutable.layout",
    5960    "allmydata.mutable.publish",
     61    "allmydata.mutable.repairer",
     62    "allmydata.mutable.retrieve",
     63    "allmydata.mutable.servermap",
    6064    "allmydata.node",
    6165    "allmydata.storage_client",
     
    156160    "allmydata.test.test_uri",
    157161    "allmydata.test.test_util",
    158     "allmydata.test.test_version",
    159162]
  • TabularUnified src/allmydata/util/log.py

    rda0fe23 ra0a39d3  
    1212if PY2:
    1313    from builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min  # noqa: F401
     14from six import ensure_str
    1415
    1516from pyutil import nummedobj
     
    5657            if pmsgid is None:
    5758                pmsgid = self._grandparentmsgid
     59        kwargs = {ensure_str(k): v for (k, v) in kwargs.items()}
    5860        msgid = log.msg(msg, facility=facility, parent=pmsgid, *args, **kwargs)
    5961        if self._parentmsgid is None:
  • TabularUnified src/allmydata/web/introweb.py

    rda0fe23 ra0a39d3  
    77import allmydata
    88import json
    9 from allmydata.version_checks import get_package_versions_string
    109from allmydata.util import idlib
    1110from allmydata.web.common import (
     
    9089        self.node_data_dict = {
    9190            "my_nodeid": idlib.nodeid_b2a(self.introducer_node.nodeid),
    92             "version": get_package_versions_string(),
     91            "version": allmydata.__full_version__,
    9392            "import_path": str(allmydata).replace("/", "/ "),  # XXX kludge for wrapping
    9493            "rendered_at": render_time(time.time()),
  • TabularUnified src/allmydata/web/root.py

    rda0fe23 ra0a39d3  
    2222
    2323import allmydata # to display import path
    24 from allmydata.version_checks import get_package_versions_string
    2524from allmydata.util import log
    2625from allmydata.interfaces import IFileNode
     
    567566    @renderer
    568567    def version(self, req, tag):
    569         return tag(get_package_versions_string())
     568        return tag(allmydata.__full_version__)
    570569
    571570    @renderer
  • TabularUnified src/allmydata/webish.py

    rda0fe23 ra0a39d3  
    11from six import ensure_str
    22
    3 import re, time
    4 
    5 from functools import (
    6     partial,
    7 )
     3import re, time, tempfile
     4
    85from cgi import (
    96    FieldStorage,
     7)
     8from io import (
     9    BytesIO,
    1010)
    1111
     
    151151
    152152
    153 tahoe_lafs_site = partial(
    154     Site,
    155     requestFactory=TahoeLAFSRequest,
    156     logFormatter=_logFormatter,
    157 )
     153class TahoeLAFSSite(Site, object):
     154    """
     155    The HTTP protocol factory used by Tahoe-LAFS.
     156
     157    Among the behaviors provided:
     158
     159    * A configurable temporary directory where large request bodies can be
     160      written so they don't stay in memory.
     161
     162    * A log formatter that writes some access logs but omits capability
     163      strings to help keep them secret.
     164    """
     165    requestFactory = TahoeLAFSRequest
     166
     167    def __init__(self, tempdir, *args, **kwargs):
     168        Site.__init__(self, *args, logFormatter=_logFormatter, **kwargs)
     169        self._tempdir = tempdir
     170
     171    def getContentFile(self, length):
     172        if length is None or length >= 1024 * 1024:
     173            return tempfile.TemporaryFile(dir=self._tempdir)
     174        return BytesIO()
    158175
    159176
     
    161178    name = "webish"
    162179
    163     def __init__(self, client, webport, nodeurl_path=None, staticdir=None,
     180    def __init__(self, client, webport, tempdir, nodeurl_path=None, staticdir=None,
    164181                 clock=None, now_fn=time.time):
    165182        service.MultiService.__init__(self)
     
    171188
    172189        self.root = root.Root(client, clock, now_fn)
    173         self.buildServer(webport, nodeurl_path, staticdir)
     190        self.buildServer(webport, tempdir, nodeurl_path, staticdir)
    174191
    175192        # If set, clock is a twisted.internet.task.Clock that the tests
     
    181198        self.root.putChild(b"storage-plugins", StoragePlugins(client))
    182199
    183     def buildServer(self, webport, nodeurl_path, staticdir):
     200    def buildServer(self, webport, tempdir, nodeurl_path, staticdir):
    184201        self.webport = webport
    185         self.site = tahoe_lafs_site(self.root)
     202        self.site = TahoeLAFSSite(tempdir, self.root)
    186203        self.staticdir = staticdir # so tests can check
    187204        if staticdir:
     
    261278        service.MultiService.__init__(self)
    262279        self.root = introweb.IntroducerRoot(introducer)
    263         self.buildServer(webport, nodeurl_path, staticdir)
     280        self.buildServer(webport, tempfile.tempdir, nodeurl_path, staticdir)
Note: See TracChangeset for help on using the changeset viewer.