Merge pull request #645 from tahoe-lafs/3239.python2-new-style-regression-test

Fix the new-style class regression test

Fixes: ticket:3239
This commit is contained in:
Jean-Paul Calderone 2019-08-14 09:08:35 -04:00 committed by GitHub
commit 0723a2f4d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 76 additions and 39 deletions

0
newsfragments/3239.minor Normal file
View File

View File

@ -114,7 +114,7 @@ def check(options):
class FakeTransport(object):
disconnecting = False
class DeepCheckOutput(LineOnlyReceiver):
class DeepCheckOutput(LineOnlyReceiver, object):
delimiter = "\n"
def __init__(self, streamer, options):
self.streamer = streamer
@ -173,7 +173,7 @@ class DeepCheckOutput(LineOnlyReceiver):
print("done: %d objects checked, %d healthy, %d unhealthy" \
% (self.num_objects, self.files_healthy, self.files_unhealthy), file=stdout)
class DeepCheckAndRepairOutput(LineOnlyReceiver):
class DeepCheckAndRepairOutput(LineOnlyReceiver, object):
delimiter = "\n"
def __init__(self, streamer, options):
self.streamer = streamer
@ -271,7 +271,7 @@ class DeepCheckAndRepairOutput(LineOnlyReceiver):
% (self.post_repair_files_healthy,
self.post_repair_files_unhealthy), file=stdout)
class DeepCheckStreamer(LineOnlyReceiver):
class DeepCheckStreamer(LineOnlyReceiver, object):
def deepcheck_location(self, options, where):
stdout = options.stdout

View File

@ -12,7 +12,7 @@ from allmydata.util.encodingutil import quote_output, quote_path
class FakeTransport(object):
disconnecting = False
class ManifestStreamer(LineOnlyReceiver):
class ManifestStreamer(LineOnlyReceiver, object):
delimiter = "\n"
def __init__(self):

View File

@ -1,6 +1,6 @@
from foolscap.logging.incident import IncidentQualifier
class NonQualifier(IncidentQualifier):
class NonQualifier(IncidentQualifier, object):
def check_event(self, ev):
return False

View File

@ -15,7 +15,7 @@ from io import BytesIO
from twisted.internet import protocol, defer
class _EverythingGetter(protocol.ProcessProtocol):
class _EverythingGetter(protocol.ProcessProtocol, object):
def __init__(self, deferred, stdinBytes=None):
self.deferred = deferred

View File

@ -270,4 +270,3 @@ while True:
f.write("directories-written: %d\n" % directories_written)
f.close()
os.rename(stats_out+".tmp", stats_out)

View File

@ -14,7 +14,7 @@ from allmydata.util.encodingutil import get_filesystem_encoding
from foolscap.api import Tub, fireEventually, flushEventualQueue
from twisted.python import log, procutils
class StallableHTTPGetterDiscarder(tw_client.HTTPPageGetter):
class StallableHTTPGetterDiscarder(tw_client.HTTPPageGetter, object):
full_speed_ahead = False
_bytes_so_far = 0
stalled = None
@ -41,7 +41,7 @@ class StallableHTTPGetterDiscarder(tw_client.HTTPPageGetter):
self.stalled = None
return tw_client.HTTPPageGetter.handleResponseEnd(self)
class StallableDiscardingHTTPClientFactory(tw_client.HTTPClientFactory):
class StallableDiscardingHTTPClientFactory(tw_client.HTTPClientFactory, object):
protocol = StallableHTTPGetterDiscarder
def discardPage(url, stall=False, *args, **kwargs):
@ -477,7 +477,7 @@ this file are ignored.
return d
class ClientWatcher(protocol.ProcessProtocol):
class ClientWatcher(protocol.ProcessProtocol, object):
ended = False
def outReceived(self, data):
print("OUT:", data)
@ -504,4 +504,3 @@ if __name__ == '__main__':
# removed each time we run.
sf = SystemFramework("_test_memory", mode)
sf.run()

View File

@ -49,7 +49,7 @@ from ..util.eliotutil import (
inline_callbacks,
)
class Expect(Protocol):
class Expect(Protocol, object):
def __init__(self):
self._expectations = []
@ -79,7 +79,7 @@ class Expect(Protocol):
d.errback(reason)
class _ProcessProtocolAdapter(ProcessProtocol):
class _ProcessProtocolAdapter(ProcessProtocol, object):
def __init__(self, fds):
self._fds = fds
@ -218,7 +218,7 @@ class CLINodeAPI(object):
return stopping
class _WaitForEnd(ProcessProtocol):
class _WaitForEnd(ProcessProtocol, object):
def __init__(self, ended):
self._ended = ended

View File

@ -1,32 +1,71 @@
"""
Tests to check for Python2 regressions
"""
from twisted.trial import unittest
from inspect import isclass
from twisted.python.modules import getModule
class PythonTwoRegressions(unittest.TestCase):
"""
A test class to hold Python2 regression tests.
"""
skip = "https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3239"
from testtools import (
TestCase,
)
from testtools.matchers import (
Equals,
)
def is_new_style(self, cls):
"""check for being a new-style class"""
# another test could be: issubclass(value, type)
has_class_attr = hasattr(cls, '__class__')
dict_or_slots = '__dict__' in dir(cls) or hasattr(cls, '__slots__')
return has_class_attr and dict_or_slots
BLACKLIST = {
"allmydata.test.check_load",
"allmydata.watchdog._watchdog_541",
"allmydata.watchdog.inotify",
"allmydata.windows.inotify",
"allmydata.windows.registry",
"allmydata.windows.tahoesvc",
}
def test_old_style_class(self):
def is_new_style(cls):
"""
:return bool: ``True`` if and only if the given class is "new style".
"""
# All new-style classes are instances of type. By definition.
return isinstance(cls, type)
def defined_here(cls, where):
"""
:return bool: ``True`` if and only if the given class was defined in a
module with the given name.
:note: Classes can lie about where they are defined. Try not to do that.
"""
return cls.__module__ == where
class PythonTwoRegressions(TestCase):
"""
Regression tests for Python 2 behaviors related to Python 3 porting.
"""
def test_new_style_classes(self):
"""
Check if all classes are new-style classes
All classes in Tahoe-LAFS are new-style.
"""
newstyle = set()
classic = set()
for mod in getModule("allmydata").walkModules():
if mod.name in BLACKLIST:
continue
# iterAttributes will only work on loaded modules. So, load it.
mod.load()
for attr in mod.iterAttributes():
value = attr.load()
if isinstance(value, str):
# apparently strings are note a new-style class (in Python 2.7)
# so we skip testing them
return
self.assertTrue(self.is_new_style(value),
"{} does not seem to be a new-style class".format(attr.name))
if isclass(value) and defined_here(value, mod.name):
if is_new_style(value):
newstyle.add(value)
else:
classic.add(value)
self.assertThat(
classic,
Equals(set()),
"Expected to find no classic classes.",
)

View File

@ -1,7 +1,7 @@
import exceptions, os
from repr import Repr
class BetterRepr(Repr):
class BetterRepr(Repr, object):
def __init__(self):
Repr.__init__(self)

View File

@ -19,7 +19,7 @@ class SingleFileError(Exception):
"""You are not permitted to add a job to a full pipeline."""
class ExpandableDeferredList(defer.Deferred):
class ExpandableDeferredList(defer.Deferred, object):
# like DeferredList(fireOnOneErrback=True) with a built-in
# gatherResults(), but you can add new Deferreds until you close it. This
# gives you a chance to add don't-complain-about-unhandled-error errbacks

View File

@ -322,7 +322,7 @@ def humanize_failure(f):
return (f.getTraceback(), http.REQUEST_ENTITY_TOO_LARGE)
return (str(f), None)
class MyExceptionHandler(appserver.DefaultExceptionHandler):
class MyExceptionHandler(appserver.DefaultExceptionHandler, object):
def simple(self, ctx, text, code=http.BAD_REQUEST):
req = IRequest(ctx)
req.setResponseCode(code)
@ -461,7 +461,7 @@ class MultiFormatPage(Page):
class TokenOnlyWebApi(resource.Resource):
class TokenOnlyWebApi(resource.Resource, object):
"""
I provide a rend.Page implementation that only accepts POST calls,
and only if they have a 'token=' arg with the correct

View File

@ -20,7 +20,7 @@ from allmydata.web.common import IOpHandleTable, MyExceptionHandler
# surgery may induce a dependency upon a particular version of twisted.web
parse_qs = http.parse_qs
class MyRequest(appserver.NevowRequest):
class MyRequest(appserver.NevowRequest, object):
fields = None
_tahoe_request_had_error = None