mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-08 19:34:18 +00:00
Merge remote-tracking branch 'origin/master' into 3855-immutable-http-apis-part-1
This commit is contained in:
commit
609bd819bb
@ -49,8 +49,8 @@ workflows:
|
||||
- "pypy27-buster":
|
||||
{}
|
||||
|
||||
# Just one Python 3.6 configuration while the port is in-progress.
|
||||
- "python36":
|
||||
# Test against Python 3:
|
||||
- "python37":
|
||||
{}
|
||||
|
||||
# Other assorted tasks and configurations
|
||||
@ -118,7 +118,7 @@ workflows:
|
||||
<<: *DOCKERHUB_CONTEXT
|
||||
- "build-image-pypy27-buster":
|
||||
<<: *DOCKERHUB_CONTEXT
|
||||
- "build-image-python36-ubuntu":
|
||||
- "build-image-python37-ubuntu":
|
||||
<<: *DOCKERHUB_CONTEXT
|
||||
|
||||
|
||||
@ -379,11 +379,11 @@ jobs:
|
||||
user: "nobody"
|
||||
|
||||
|
||||
python36:
|
||||
python37:
|
||||
<<: *UBUNTU_18_04
|
||||
docker:
|
||||
- <<: *DOCKERHUB_AUTH
|
||||
image: "tahoelafsci/ubuntu:18.04-py3"
|
||||
image: "tahoelafsci/ubuntu:18.04-py3.7"
|
||||
user: "nobody"
|
||||
|
||||
environment:
|
||||
@ -392,7 +392,7 @@ jobs:
|
||||
# this reporter on Python 3. So drop that and just specify the
|
||||
# reporter.
|
||||
TAHOE_LAFS_TRIAL_ARGS: "--reporter=subunitv2-file"
|
||||
TAHOE_LAFS_TOX_ENVIRONMENT: "py36"
|
||||
TAHOE_LAFS_TOX_ENVIRONMENT: "py37"
|
||||
|
||||
|
||||
ubuntu-20-04:
|
||||
@ -511,7 +511,9 @@ jobs:
|
||||
# https://circleci.com/blog/how-to-build-a-docker-image-on-circleci-2-0/
|
||||
docker:
|
||||
- <<: *DOCKERHUB_AUTH
|
||||
image: "docker:17.05.0-ce-git"
|
||||
# CircleCI build images; https://github.com/CircleCI-Public/cimg-base
|
||||
# for details.
|
||||
image: "cimg/base:2022.01"
|
||||
|
||||
environment:
|
||||
DISTRO: "tahoelafsci/<DISTRO>:foo-py2"
|
||||
@ -577,13 +579,13 @@ jobs:
|
||||
PYTHON_VERSION: "2.7"
|
||||
|
||||
|
||||
build-image-python36-ubuntu:
|
||||
build-image-python37-ubuntu:
|
||||
<<: *BUILD_IMAGE
|
||||
|
||||
environment:
|
||||
DISTRO: "ubuntu"
|
||||
TAG: "18.04"
|
||||
PYTHON_VERSION: "3"
|
||||
PYTHON_VERSION: "3.7"
|
||||
|
||||
|
||||
build-image-ubuntu-20-04:
|
||||
|
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@ -39,12 +39,11 @@ jobs:
|
||||
- ubuntu-latest
|
||||
python-version:
|
||||
- 2.7
|
||||
- 3.6
|
||||
- 3.7
|
||||
- 3.8
|
||||
- 3.9
|
||||
include:
|
||||
# On macOS don't bother with 3.6-3.8, just to get faster builds.
|
||||
# On macOS don't bother with 3.7-3.8, just to get faster builds.
|
||||
- os: macos-10.15
|
||||
python-version: 2.7
|
||||
- os: macos-latest
|
||||
@ -181,10 +180,10 @@ jobs:
|
||||
- ubuntu-latest
|
||||
python-version:
|
||||
- 2.7
|
||||
- 3.6
|
||||
- 3.7
|
||||
- 3.9
|
||||
include:
|
||||
# On macOS don't bother with 3.6, just to get faster builds.
|
||||
# On macOS don't bother with 3.7, just to get faster builds.
|
||||
- os: macos-10.15
|
||||
python-version: 2.7
|
||||
- os: macos-latest
|
||||
|
4
Makefile
4
Makefile
@ -35,7 +35,7 @@ test: .tox/create-venvs.log
|
||||
# Run codechecks first since it takes the least time to report issues early.
|
||||
tox --develop -e codechecks
|
||||
# Run all the test environments in parallel to reduce run-time
|
||||
tox --develop -p auto -e 'py27,py36,pypy27'
|
||||
tox --develop -p auto -e 'py27,py37,pypy27'
|
||||
.PHONY: test-venv-coverage
|
||||
## Run all tests with coverage collection and reporting.
|
||||
test-venv-coverage:
|
||||
@ -51,7 +51,7 @@ test-venv-coverage:
|
||||
.PHONY: test-py3-all
|
||||
## Run all tests under Python 3
|
||||
test-py3-all: .tox/create-venvs.log
|
||||
tox --develop -e py36 allmydata
|
||||
tox --develop -e py37 allmydata
|
||||
|
||||
# This is necessary only if you want to automatically produce a new
|
||||
# _version.py file from the current git history (without doing a build).
|
||||
|
14
NEWS.rst
14
NEWS.rst
@ -5,6 +5,20 @@ User-Visible Changes in Tahoe-LAFS
|
||||
==================================
|
||||
|
||||
.. towncrier start line
|
||||
Release 1.17.1 (2022-01-07)
|
||||
'''''''''''''''''''''''''''
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- Fixed regression on Python 3 causing the JSON version of the Welcome page to sometimes produce a 500 error (`#3852 <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3852>`_)
|
||||
- Fixed regression on Python 3 where JSON HTTP POSTs failed to be processed. (`#3854 <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3854>`_)
|
||||
|
||||
|
||||
Misc/Other
|
||||
----------
|
||||
|
||||
- `#3848 <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3848>`_, `#3849 <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3849>`_, `#3850 <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3850>`_, `#3856 <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3856>`_
|
||||
|
||||
|
||||
Release 1.17.0 (2021-12-06)
|
||||
|
@ -28,15 +28,15 @@ To install Tahoe-LAFS on Windows:
|
||||
3. Open the installer by double-clicking it. Select the **Add Python to PATH** check-box, then click **Install Now**.
|
||||
|
||||
4. Start PowerShell and enter the following command to verify python installation::
|
||||
|
||||
|
||||
python --version
|
||||
|
||||
5. Enter the following command to install Tahoe-LAFS::
|
||||
|
||||
|
||||
pip install tahoe-lafs
|
||||
|
||||
6. Verify installation by checking for the version::
|
||||
|
||||
|
||||
tahoe --version
|
||||
|
||||
If you want to hack on Tahoe's source code, you can install Tahoe in a ``virtualenv`` on your Windows Machine. To learn more, see :doc:`install-on-windows`.
|
||||
@ -56,13 +56,13 @@ If you are working on MacOS or a Linux distribution which does not have Tahoe-LA
|
||||
* **pip**: Most python installations already include `pip`. However, if your installation does not, see `pip installation <https://pip.pypa.io/en/stable/installing/>`_.
|
||||
|
||||
2. Install Tahoe-LAFS using pip::
|
||||
|
||||
|
||||
pip install tahoe-lafs
|
||||
|
||||
3. Verify installation by checking for the version::
|
||||
|
||||
|
||||
tahoe --version
|
||||
|
||||
If you are looking to hack on the source code or run pre-release code, we recommend you install Tahoe-LAFS on a `virtualenv` instance. To learn more, see :doc:`install-on-linux`.
|
||||
If you are looking to hack on the source code or run pre-release code, we recommend you install Tahoe-LAFS on a `virtualenv` instance. To learn more, see :doc:`install-on-linux`.
|
||||
|
||||
You can always write to the `tahoe-dev mailing list <https://lists.tahoe-lafs.org/mailman/listinfo/tahoe-dev>`_ or chat on the `Libera.chat IRC <irc://irc.libera.chat/%23tahoe-lafs>`_ if you are not able to get Tahoe-LAFS up and running on your deployment.
|
||||
|
@ -70,7 +70,6 @@ Create Branch and Apply Updates
|
||||
- commit it
|
||||
|
||||
- update "docs/known_issues.rst" if appropriate
|
||||
- update "docs/Installation/install-tahoe.rst" references to the new release
|
||||
- Push the branch to github
|
||||
- Create a (draft) PR; this should trigger CI (note that github
|
||||
doesn't let you create a PR without some changes on the branch so
|
||||
@ -107,6 +106,11 @@ they will need to evaluate which contributors' signatures they trust.
|
||||
|
||||
- tox -e deprecations,upcoming-deprecations
|
||||
|
||||
- clone to a clean, local checkout (to avoid extra files being included in the release)
|
||||
|
||||
- cd /tmp
|
||||
- git clone /home/meejah/src/tahoe-lafs
|
||||
|
||||
- build tarballs
|
||||
|
||||
- tox -e tarballs
|
||||
@ -153,14 +157,20 @@ need to be uploaded to https://tahoe-lafs.org in `~source/downloads`
|
||||
|
||||
- secure-copy all release artifacts to the download area on the
|
||||
tahoe-lafs.org host machine. `~source/downloads` on there maps to
|
||||
https://tahoe-lafs.org/downloads/ on the Web.
|
||||
- scp dist/*1.15.0* username@tahoe-lafs.org:/home/source/downloads
|
||||
https://tahoe-lafs.org/downloads/ on the Web:
|
||||
|
||||
- scp dist/*1.15.0* username@tahoe-lafs.org:/home/source/downloads
|
||||
|
||||
- the following developers have access to do this:
|
||||
|
||||
- exarkun
|
||||
- meejah
|
||||
- warner
|
||||
|
||||
Push the signed tag to the main repository:
|
||||
|
||||
- git push origin tahoe-lafs-1.17.1
|
||||
|
||||
For the actual release, the tarball and signature files need to be
|
||||
uploaded to PyPI as well.
|
||||
|
||||
|
1
newsfragments/3865.incompat
Normal file
1
newsfragments/3865.incompat
Normal file
@ -0,0 +1 @@
|
||||
Python 3.6 is no longer supported, as it has reached end-of-life and is no longer receiving security updates.
|
@ -7,7 +7,7 @@
|
||||
, html5lib, pyutil, distro, configparser, klein, werkzeug, cbor2
|
||||
}:
|
||||
python.pkgs.buildPythonPackage rec {
|
||||
# Most of the time this is not exactly the release version (eg 1.17.0).
|
||||
# Most of the time this is not exactly the release version (eg 1.17.1).
|
||||
# Give it a `post` component to make it look newer than the release version
|
||||
# and we'll bump this up at the time of each release.
|
||||
#
|
||||
@ -20,7 +20,7 @@ python.pkgs.buildPythonPackage rec {
|
||||
# is not a reproducable artifact (in the sense of "reproducable builds") so
|
||||
# it is excluded from the source tree by default. When it is included, the
|
||||
# package tends to be frequently spuriously rebuilt.
|
||||
version = "1.17.0.post1";
|
||||
version = "1.17.1.post1";
|
||||
name = "tahoe-lafs-${version}";
|
||||
src = lib.cleanSourceWith {
|
||||
src = ../.;
|
||||
|
45
relnotes.txt
45
relnotes.txt
@ -1,6 +1,6 @@
|
||||
ANNOUNCING Tahoe, the Least-Authority File Store, v1.17.0
|
||||
ANNOUNCING Tahoe, the Least-Authority File Store, v1.17.1
|
||||
|
||||
The Tahoe-LAFS team is pleased to announce version 1.17.0 of
|
||||
The Tahoe-LAFS team is pleased to announce version 1.17.1 of
|
||||
Tahoe-LAFS, an extremely reliable decentralized storage
|
||||
system. Get it with "pip install tahoe-lafs", or download a
|
||||
tarball here:
|
||||
@ -15,19 +15,12 @@ unique security and fault-tolerance properties:
|
||||
|
||||
https://tahoe-lafs.readthedocs.org/en/latest/about.html
|
||||
|
||||
The previous stable release of Tahoe-LAFS was v1.16.0, released on
|
||||
October 19, 2021.
|
||||
The previous stable release of Tahoe-LAFS was v1.17.0, released on
|
||||
December 6, 2021.
|
||||
|
||||
This release fixes several security issues raised as part of an audit
|
||||
by Cure53. We developed fixes for these issues in a private
|
||||
repository. Shortly after this release, public tickets will be updated
|
||||
with further information (along with, of course, all the code).
|
||||
This release fixes two Python3-releated regressions and 4 minor bugs.
|
||||
|
||||
There is also OpenMetrics support now and several bug fixes.
|
||||
|
||||
In all, 46 issues have been fixed since the last release.
|
||||
|
||||
Please see ``NEWS.rst`` for a more complete list of changes.
|
||||
Please see ``NEWS.rst`` [1] for a complete list of changes.
|
||||
|
||||
|
||||
WHAT IS IT GOOD FOR?
|
||||
@ -66,12 +59,12 @@ to v1.0 (which was released March 25, 2008). Clients from this
|
||||
release can read files and directories produced by clients of
|
||||
all versions since v1.0.
|
||||
|
||||
Network connections are limited by the Introducer protocol in
|
||||
use. If the Introducer is running v1.10 or v1.11, then servers
|
||||
from this release (v1.12) can serve clients of all versions
|
||||
back to v1.0 . If it is running v1.12, then they can only
|
||||
serve clients back to v1.10. Clients from this release can use
|
||||
servers back to v1.10, but not older servers.
|
||||
Network connections are limited by the Introducer protocol in use. If
|
||||
the Introducer is running v1.10 or v1.11, then servers from this
|
||||
release can serve clients of all versions back to v1.0 . If it is
|
||||
running v1.12 or higher, then they can only serve clients back to
|
||||
v1.10. Clients from this release can use servers back to v1.10, but
|
||||
not older servers.
|
||||
|
||||
Except for the new optional MDMF format, we have not made any
|
||||
intentional compatibility changes. However we do not yet have
|
||||
@ -79,7 +72,7 @@ the test infrastructure to continuously verify that all new
|
||||
versions are interoperable with previous versions. We intend
|
||||
to build such an infrastructure in the future.
|
||||
|
||||
This is the twenty-first release in the version 1 series. This
|
||||
This is the twenty-second release in the version 1 series. This
|
||||
series of Tahoe-LAFS will be actively supported and maintained
|
||||
for the foreseeable future, and future versions of Tahoe-LAFS
|
||||
will retain the ability to read and write files compatible
|
||||
@ -139,7 +132,7 @@ Of Fame" [13].
|
||||
|
||||
ACKNOWLEDGEMENTS
|
||||
|
||||
This is the eighteenth release of Tahoe-LAFS to be created
|
||||
This is the nineteenth release of Tahoe-LAFS to be created
|
||||
solely as a labor of love by volunteers. Thank you very much
|
||||
to the team of "hackers in the public interest" who make
|
||||
Tahoe-LAFS possible.
|
||||
@ -147,16 +140,16 @@ Tahoe-LAFS possible.
|
||||
meejah
|
||||
on behalf of the Tahoe-LAFS team
|
||||
|
||||
December 6, 2021
|
||||
January 7, 2022
|
||||
Planet Earth
|
||||
|
||||
|
||||
[1] https://github.com/tahoe-lafs/tahoe-lafs/blob/tahoe-lafs-1.17.0/NEWS.rst
|
||||
[1] https://github.com/tahoe-lafs/tahoe-lafs/blob/tahoe-lafs-1.17.1/NEWS.rst
|
||||
[2] https://github.com/tahoe-lafs/tahoe-lafs/blob/master/docs/known_issues.rst
|
||||
[3] https://tahoe-lafs.org/trac/tahoe-lafs/wiki/RelatedProjects
|
||||
[4] https://github.com/tahoe-lafs/tahoe-lafs/blob/tahoe-lafs-1.17.0/COPYING.GPL
|
||||
[5] https://github.com/tahoe-lafs/tahoe-lafs/blob/tahoe-lafs-1.17.0/COPYING.TGPPL.rst
|
||||
[6] https://tahoe-lafs.readthedocs.org/en/tahoe-lafs-1.17.0/INSTALL.html
|
||||
[4] https://github.com/tahoe-lafs/tahoe-lafs/blob/tahoe-lafs-1.17.1/COPYING.GPL
|
||||
[5] https://github.com/tahoe-lafs/tahoe-lafs/blob/tahoe-lafs-1.17.1/COPYING.TGPPL.rst
|
||||
[6] https://tahoe-lafs.readthedocs.org/en/tahoe-lafs-1.17.1/INSTALL.html
|
||||
[7] https://lists.tahoe-lafs.org/mailman/listinfo/tahoe-dev
|
||||
[8] https://tahoe-lafs.org/trac/tahoe-lafs/roadmap
|
||||
[9] https://github.com/tahoe-lafs/tahoe-lafs/blob/master/CREDITS
|
||||
|
9
setup.py
9
setup.py
@ -380,9 +380,8 @@ setup(name="tahoe-lafs", # also set in __init__.py
|
||||
package_dir = {'':'src'},
|
||||
packages=find_packages('src') + ['allmydata.test.plugins'],
|
||||
classifiers=trove_classifiers,
|
||||
# We support Python 2.7, and we're working on support for 3.6 (the
|
||||
# highest version that PyPy currently supports).
|
||||
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*",
|
||||
# We support Python 2.7, and Python 3.7 or later.
|
||||
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*",
|
||||
install_requires=install_requires,
|
||||
extras_require={
|
||||
# Duplicate the Twisted pywin32 dependency here. See
|
||||
@ -413,7 +412,9 @@ setup(name="tahoe-lafs", # also set in __init__.py
|
||||
"html5lib",
|
||||
"junitxml",
|
||||
"tenacity",
|
||||
"paramiko",
|
||||
# Pin old version until
|
||||
# https://github.com/paramiko/paramiko/issues/1961 is fixed.
|
||||
"paramiko < 2.9",
|
||||
"pytest-timeout",
|
||||
# Does our OpenMetrics endpoint adhere to the spec:
|
||||
"prometheus-client == 0.11.0",
|
||||
|
@ -11,6 +11,7 @@ if PY2:
|
||||
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
|
||||
|
||||
import time
|
||||
import json
|
||||
|
||||
from urllib.parse import (
|
||||
quote,
|
||||
@ -24,14 +25,23 @@ from twisted.web.template import Tag
|
||||
from twisted.web.test.requesthelper import DummyRequest
|
||||
from twisted.application import service
|
||||
from testtools.twistedsupport import succeeded
|
||||
from twisted.internet.defer import inlineCallbacks
|
||||
from twisted.internet.defer import (
|
||||
inlineCallbacks,
|
||||
succeed,
|
||||
)
|
||||
|
||||
from ...storage_client import (
|
||||
NativeStorageServer,
|
||||
StorageFarmBroker,
|
||||
)
|
||||
from ...web.root import RootElement
|
||||
from ...web.root import (
|
||||
RootElement,
|
||||
Root,
|
||||
)
|
||||
from ...util.connection_status import ConnectionStatus
|
||||
from ...crypto.ed25519 import (
|
||||
create_signing_keypair,
|
||||
)
|
||||
from allmydata.web.root import URIHandler
|
||||
from allmydata.client import _Client
|
||||
|
||||
@ -47,6 +57,7 @@ from ..common import (
|
||||
|
||||
from ..common import (
|
||||
SyncTestCase,
|
||||
AsyncTestCase,
|
||||
)
|
||||
|
||||
from testtools.matchers import (
|
||||
@ -138,3 +149,94 @@ class RenderServiceRow(SyncTestCase):
|
||||
|
||||
self.assertThat(item.slotData.get("version"), Equals(""))
|
||||
self.assertThat(item.slotData.get("nickname"), Equals(""))
|
||||
|
||||
|
||||
class RenderRoot(AsyncTestCase):
|
||||
|
||||
@inlineCallbacks
|
||||
def test_root_json(self):
|
||||
"""
|
||||
The 'welcome' / root page renders properly with ?t=json when some
|
||||
servers show None for available_space while others show a
|
||||
valid int
|
||||
|
||||
See also https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3852
|
||||
"""
|
||||
ann = {
|
||||
"anonymous-storage-FURL": "pb://w2hqnbaa25yw4qgcvghl5psa3srpfgw3@tcp:127.0.0.1:51309/vucto2z4fxment3vfxbqecblbf6zyp6x",
|
||||
"permutation-seed-base32": "w2hqnbaa25yw4qgcvghl5psa3srpfgw3",
|
||||
}
|
||||
srv0 = NativeStorageServer(b"server_id0", ann, None, {}, EMPTY_CLIENT_CONFIG)
|
||||
srv0.get_connection_status = lambda: ConnectionStatus(False, "summary0", {}, 0, 0)
|
||||
|
||||
srv1 = NativeStorageServer(b"server_id1", ann, None, {}, EMPTY_CLIENT_CONFIG)
|
||||
srv1.get_connection_status = lambda: ConnectionStatus(False, "summary1", {}, 0, 0)
|
||||
# arrange for this server to have some valid available space
|
||||
srv1.get_available_space = lambda: 12345
|
||||
|
||||
class FakeClient(_Client):
|
||||
history = []
|
||||
stats_provider = object()
|
||||
nickname = ""
|
||||
nodeid = b"asdf"
|
||||
_node_public_key = create_signing_keypair()[1]
|
||||
introducer_clients = []
|
||||
helper = None
|
||||
|
||||
def __init__(self):
|
||||
service.MultiService.__init__(self)
|
||||
self.storage_broker = StorageFarmBroker(
|
||||
permute_peers=True,
|
||||
tub_maker=None,
|
||||
node_config=EMPTY_CLIENT_CONFIG,
|
||||
)
|
||||
self.storage_broker.test_add_server(b"test-srv0", srv0)
|
||||
self.storage_broker.test_add_server(b"test-srv1", srv1)
|
||||
|
||||
root = Root(FakeClient(), now_fn=time.time)
|
||||
|
||||
lines = []
|
||||
|
||||
req = DummyRequest(b"")
|
||||
req.fields = {}
|
||||
req.args = {
|
||||
b"t": [b"json"],
|
||||
}
|
||||
|
||||
# for some reason, DummyRequest is already finished when we
|
||||
# try to add a notifyFinish handler, so override that
|
||||
# behavior.
|
||||
|
||||
def nop():
|
||||
return succeed(None)
|
||||
req.notifyFinish = nop
|
||||
req.write = lines.append
|
||||
|
||||
yield root.render(req)
|
||||
|
||||
raw_js = b"".join(lines).decode("utf8")
|
||||
js = json.loads(raw_js)
|
||||
servers = js["servers"]
|
||||
self.assertEquals(len(servers), 2)
|
||||
self.assertIn(
|
||||
{
|
||||
"connection_status": "summary0",
|
||||
"nodeid": "server_id0",
|
||||
"last_received_data": 0,
|
||||
"version": None,
|
||||
"available_space": None,
|
||||
"nickname": ""
|
||||
},
|
||||
servers
|
||||
)
|
||||
self.assertIn(
|
||||
{
|
||||
"connection_status": "summary1",
|
||||
"nodeid": "server_id1",
|
||||
"last_received_data": 0,
|
||||
"version": None,
|
||||
"available_space": 12345,
|
||||
"nickname": ""
|
||||
},
|
||||
servers
|
||||
)
|
||||
|
@ -820,29 +820,37 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
|
||||
"""
|
||||
d = self.GET("/?t=json")
|
||||
def _check(res):
|
||||
"""
|
||||
Check that the results are correct.
|
||||
We can't depend on the order of servers in the output
|
||||
"""
|
||||
decoded = json.loads(res)
|
||||
expected = {
|
||||
u'introducers': {
|
||||
u'statuses': [],
|
||||
self.assertEqual(decoded['introducers'], {u'statuses': []})
|
||||
actual_servers = decoded[u"servers"]
|
||||
self.assertEquals(len(actual_servers), 2)
|
||||
self.assertIn(
|
||||
{
|
||||
u"nodeid": u'other_nodeid',
|
||||
u'available_space': 123456,
|
||||
u'connection_status': u'summary',
|
||||
u'last_received_data': 30,
|
||||
u'nickname': u'other_nickname \u263b',
|
||||
u'version': u'1.0',
|
||||
},
|
||||
u'servers': sorted([
|
||||
{u"nodeid": u'other_nodeid',
|
||||
u'available_space': 123456,
|
||||
u'connection_status': u'summary',
|
||||
u'last_received_data': 30,
|
||||
u'nickname': u'other_nickname \u263b',
|
||||
u'version': u'1.0',
|
||||
},
|
||||
{u"nodeid": u'disconnected_nodeid',
|
||||
u'available_space': 123456,
|
||||
u'connection_status': u'summary',
|
||||
u'last_received_data': 35,
|
||||
u'nickname': u'disconnected_nickname \u263b',
|
||||
u'version': u'1.0',
|
||||
},
|
||||
], key=lambda o: sorted(o.items())),
|
||||
}
|
||||
self.assertEqual(expected, decoded)
|
||||
actual_servers
|
||||
)
|
||||
self.assertIn(
|
||||
{
|
||||
u"nodeid": u'disconnected_nodeid',
|
||||
u'available_space': 123456,
|
||||
u'connection_status': u'summary',
|
||||
u'last_received_data': 35,
|
||||
u'nickname': u'disconnected_nickname \u263b',
|
||||
u'version': u'1.0',
|
||||
},
|
||||
actual_servers
|
||||
)
|
||||
|
||||
d.addCallback(_check)
|
||||
return d
|
||||
|
||||
|
@ -90,10 +90,11 @@ class TahoeLAFSRequestTests(SyncTestCase):
|
||||
"""
|
||||
self._fields_test(b"GET", {}, b"", Equals(None))
|
||||
|
||||
def test_form_fields(self):
|
||||
def test_form_fields_if_filename_set(self):
|
||||
"""
|
||||
When a ``POST`` request is received, form fields are parsed into
|
||||
``TahoeLAFSRequest.fields``.
|
||||
``TahoeLAFSRequest.fields`` and the body is bytes (presuming ``filename``
|
||||
is set).
|
||||
"""
|
||||
form_data, boundary = multipart_formdata([
|
||||
[param(u"name", u"foo"),
|
||||
@ -121,6 +122,49 @@ class TahoeLAFSRequestTests(SyncTestCase):
|
||||
),
|
||||
)
|
||||
|
||||
def test_form_fields_if_name_is_file(self):
|
||||
"""
|
||||
When a ``POST`` request is received, form fields are parsed into
|
||||
``TahoeLAFSRequest.fields`` and the body is bytes when ``name``
|
||||
is set to ``"file"``.
|
||||
"""
|
||||
form_data, boundary = multipart_formdata([
|
||||
[param(u"name", u"foo"),
|
||||
body(u"bar"),
|
||||
],
|
||||
[param(u"name", u"file"),
|
||||
body(u"some file contents"),
|
||||
],
|
||||
])
|
||||
self._fields_test(
|
||||
b"POST",
|
||||
{b"content-type": b"multipart/form-data; boundary=" + bytes(boundary, 'ascii')},
|
||||
form_data.encode("ascii"),
|
||||
AfterPreprocessing(
|
||||
lambda fs: {
|
||||
k: fs.getvalue(k)
|
||||
for k
|
||||
in fs.keys()
|
||||
},
|
||||
Equals({
|
||||
"foo": "bar",
|
||||
"file": b"some file contents",
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
def test_form_fields_require_correct_mime_type(self):
|
||||
"""
|
||||
The body of a ``POST`` is not parsed into fields if its mime type is
|
||||
not ``multipart/form-data``.
|
||||
|
||||
Reproducer for https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3854
|
||||
"""
|
||||
data = u'{"lalala": "lolo"}'
|
||||
data = data.encode("utf-8")
|
||||
self._fields_test(b"POST", {"content-type": "application/json"},
|
||||
data, Equals(None))
|
||||
|
||||
|
||||
class TahoeLAFSSiteTests(SyncTestCase):
|
||||
"""
|
||||
|
@ -297,14 +297,12 @@ class Root(MultiFormatResource):
|
||||
}
|
||||
return json.dumps(result, indent=1) + "\n"
|
||||
|
||||
|
||||
def _describe_known_servers(self, broker):
|
||||
return sorted(list(
|
||||
return list(
|
||||
self._describe_server(server)
|
||||
for server
|
||||
in broker.get_known_servers()
|
||||
), key=lambda o: sorted(o.items()))
|
||||
|
||||
)
|
||||
|
||||
def _describe_server(self, server):
|
||||
status = server.get_connection_status()
|
||||
|
@ -114,7 +114,8 @@ class TahoeLAFSRequest(Request, object):
|
||||
self.path, argstring = x
|
||||
self.args = parse_qs(argstring, 1)
|
||||
|
||||
if self.method == b'POST':
|
||||
content_type = (self.requestHeaders.getRawHeaders("content-type") or [""])[0]
|
||||
if self.method == b'POST' and content_type.split(";")[0] in ("multipart/form-data", "application/x-www-form-urlencoded"):
|
||||
# We use FieldStorage here because it performs better than
|
||||
# cgi.parse_multipart(self.content, pdict) which is what
|
||||
# twisted.web.http.Request uses.
|
||||
|
5
tox.ini
5
tox.ini
@ -8,7 +8,6 @@
|
||||
[gh-actions]
|
||||
python =
|
||||
2.7: py27-coverage,codechecks
|
||||
3.6: py36-coverage
|
||||
3.7: py37-coverage,typechecks,codechecks3
|
||||
3.8: py38-coverage
|
||||
3.9: py39-coverage
|
||||
@ -18,7 +17,7 @@ python =
|
||||
twisted = 1
|
||||
|
||||
[tox]
|
||||
envlist = typechecks,codechecks,codechecks3,py{27,36,37,38,39}-{coverage},pypy27,pypy3,integration,integration3
|
||||
envlist = typechecks,codechecks,codechecks3,py{27,37,38,39}-{coverage},pypy27,pypy3,integration,integration3
|
||||
minversion = 2.4
|
||||
|
||||
[testenv]
|
||||
@ -51,7 +50,7 @@ deps =
|
||||
# suffering we're trying to avoid with the above pins.
|
||||
certifi
|
||||
# VCS hooks support
|
||||
py36,!coverage: pre-commit
|
||||
py37,!coverage: pre-commit
|
||||
|
||||
# We add usedevelop=False because testing against a true installation gives
|
||||
# more useful results.
|
||||
|
Loading…
x
Reference in New Issue
Block a user