mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-06-05 09:10:53 +00:00
load-yaml-cache cleanups
* use yaml.safe_load and yaml.safe_dump * configure SafeLoader to return unicode consistently, not str * log+ignore bad cache, instead of throwing error, since we're already in the log+ignore chain from connect_failed() * use a local exception type, instead of one from storage_client.py * delegate delivery to self._deliver_announcements Using yaml.safe_dump gives us: - ann: my-version: tahoe-lafs/1.11.0.post96.dev0 nickname: node-4 instead of: - ann: !!python/unicode 'my-version': !!python/unicode 'tahoe-lafs/1.11.0.post96.dev0' !!python/unicode 'nickname': !!python/unicode 'node-4' We want SafeLoader to consistently return unicode instead of sometimes plain strings (for ASCII-safe values) and sometimes unicode (for everything else). The data we write into the cache was all unicode to start with (it came from a JSON parser), so it seems better to get back unicode too.
This commit is contained in:
parent
5508f751b6
commit
5bedca43e3
@ -13,6 +13,9 @@ from allmydata.util import log
|
|||||||
from allmydata.util.rrefutil import add_version_to_remote_reference
|
from allmydata.util.rrefutil import add_version_to_remote_reference
|
||||||
from allmydata.util.keyutil import BadSignatureError
|
from allmydata.util.keyutil import BadSignatureError
|
||||||
|
|
||||||
|
class InvalidCacheError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
class WrapV2ClientInV1Interface(Referenceable): # for_v1
|
class WrapV2ClientInV1Interface(Referenceable): # for_v1
|
||||||
"""I wrap a v2 IntroducerClient to make it look like a v1 client, so it
|
"""I wrap a v2 IntroducerClient to make it look like a v1 client, so it
|
||||||
can be attached to an old server."""
|
can be attached to an old server."""
|
||||||
@ -116,23 +119,28 @@ class IntroducerClient(service.Service, Referenceable):
|
|||||||
d.addErrback(connect_failed)
|
d.addErrback(connect_failed)
|
||||||
|
|
||||||
def _load_announcements(self):
|
def _load_announcements(self):
|
||||||
if self._cache_filepath.exists():
|
# Announcements contain unicode, because they come from JSON. We tell
|
||||||
|
# PyYAML to give us unicode instead of str/bytes.
|
||||||
|
def construct_unicode(loader, node):
|
||||||
|
return node.value
|
||||||
|
yaml.SafeLoader.add_constructor("tag:yaml.org,2002:str",
|
||||||
|
construct_unicode)
|
||||||
|
try:
|
||||||
with self._cache_filepath.open() as f:
|
with self._cache_filepath.open() as f:
|
||||||
servers = yaml.load(f)
|
servers = yaml.safe_load(f)
|
||||||
f.close()
|
except EnvironmentError:
|
||||||
if not isinstance(servers, list):
|
return # no cache file
|
||||||
msg = "Invalid cached storage server announcements. No list encountered."
|
if not isinstance(servers, list):
|
||||||
self.log(msg,
|
log.err(InvalidCacheError("not a list"), level=log.WEIRD)
|
||||||
level=log.WEIRD)
|
return
|
||||||
raise storage_client.UnknownServerTypeError(msg)
|
self.log("Using server data from cache", level=log.UNUSUAL)
|
||||||
for server_params in servers:
|
for server_params in servers:
|
||||||
if not isinstance(server_params, dict):
|
if not isinstance(server_params, dict):
|
||||||
msg = "Invalid cached storage server announcement encountered. No key/values found in %s" % server_params
|
log.err(InvalidCacheError("not a dict: %r" % (server_params,)),
|
||||||
self.log(msg,
|
level=log.WEIRD)
|
||||||
level=log.WEIRD)
|
continue
|
||||||
raise storage_client.UnknownServerTypeError(msg)
|
self._deliver_announcements(server_params['key_s'],
|
||||||
for _, cb, _, _ in self._local_subscribers:
|
server_params['ann'])
|
||||||
eventually(cb, server_params['key_s'], server_params['ann'])
|
|
||||||
|
|
||||||
def _save_announcements(self):
|
def _save_announcements(self):
|
||||||
announcements = []
|
announcements = []
|
||||||
@ -143,7 +151,7 @@ class IntroducerClient(service.Service, Referenceable):
|
|||||||
"key_s" : key_s,
|
"key_s" : key_s,
|
||||||
}
|
}
|
||||||
announcements.append(server_params)
|
announcements.append(server_params)
|
||||||
announcement_cache_yaml = yaml.dump(announcements)
|
announcement_cache_yaml = yaml.safe_dump(announcements)
|
||||||
self._cache_filepath.setContent(announcement_cache_yaml)
|
self._cache_filepath.setContent(announcement_cache_yaml)
|
||||||
|
|
||||||
def _got_introducer(self, publisher):
|
def _got_introducer(self, publisher):
|
||||||
|
@ -1009,10 +1009,11 @@ class Announcements(unittest.TestCase):
|
|||||||
self.failUnlessEqual(a[0].announcement["anonymous-storage-FURL"], furl1)
|
self.failUnlessEqual(a[0].announcement["anonymous-storage-FURL"], furl1)
|
||||||
|
|
||||||
def _load_cache(self, cache_filepath):
|
def _load_cache(self, cache_filepath):
|
||||||
|
def construct_unicode(loader, node):
|
||||||
|
return node.value
|
||||||
|
yaml.SafeLoader.add_constructor("tag:yaml.org,2002:str",
|
||||||
|
construct_unicode)
|
||||||
with cache_filepath.open() as f:
|
with cache_filepath.open() as f:
|
||||||
def constructor(loader, node):
|
|
||||||
return node.value
|
|
||||||
yaml.SafeLoader.add_constructor("tag:yaml.org,2002:python/unicode", constructor)
|
|
||||||
return yaml.safe_load(f)
|
return yaml.safe_load(f)
|
||||||
|
|
||||||
def test_client_cache(self):
|
def test_client_cache(self):
|
||||||
@ -1080,6 +1081,18 @@ class Announcements(unittest.TestCase):
|
|||||||
for a in announcements]))
|
for a in announcements]))
|
||||||
|
|
||||||
|
|
||||||
|
class YAMLUnicode(unittest.TestCase):
|
||||||
|
def test_convert(self):
|
||||||
|
data = yaml.safe_dump(["str", u"unicode", u"\u1234nicode"])
|
||||||
|
def construct_unicode(loader, node):
|
||||||
|
return node.value
|
||||||
|
yaml.SafeLoader.add_constructor("tag:yaml.org,2002:str",
|
||||||
|
construct_unicode)
|
||||||
|
back = yaml.safe_load(data)
|
||||||
|
self.failUnlessEqual(type(back[0]), unicode)
|
||||||
|
self.failUnlessEqual(type(back[1]), unicode)
|
||||||
|
self.failUnlessEqual(type(back[2]), unicode)
|
||||||
|
|
||||||
class ClientSeqnums(unittest.TestCase):
|
class ClientSeqnums(unittest.TestCase):
|
||||||
def test_client(self):
|
def test_client(self):
|
||||||
basedir = "introducer/ClientSeqnums/test_client"
|
basedir = "introducer/ClientSeqnums/test_client"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user