Mercurial > public > mercurial-scm > hg
view tests/test-check-interfaces.py @ 37006:8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Previously, we passed a bunch of arguments to httppeer.__init__,
validated them, then possibly constructed a valid instance.
A short while ago, we refactored sshpeer so all the validation and
setup work occurs before the constructor. We introduced a makepeer()
to hold most of this logic.
This commit gives httppeer the same treatment.
As a sign that the previous design was poor, __del__ no longer
conditionally checks for the presence of an attribute that may
not be defined (it is always defined in the new code).
.. api::
httppeer.httppeer.__init__ now takes additional arguments.
Instances should be obtained by calling httppeer.instance()
or httppeer.makepeer() instead.
Differential Revision: https://phab.mercurial-scm.org/D2725
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 07 Mar 2018 20:41:59 -0800 |
parents | 11ba1a96f946 |
children | 0dfb5672f015 |
line wrap: on
line source
# Test that certain objects conform to well-defined interfaces. from __future__ import absolute_import, print_function from mercurial import ( bundlerepo, httppeer, localrepo, sshpeer, statichttprepo, ui as uimod, unionrepo, ) def checkobject(o): """Verify a constructed object conforms to interface rules. An object must have __abstractmethods__ defined. All "public" attributes of the object (attributes not prefixed with an underscore) must be in __abstractmethods__ or appear on a base class with __abstractmethods__. """ name = o.__class__.__name__ allowed = set() for cls in o.__class__.__mro__: if not getattr(cls, '__abstractmethods__', set()): continue allowed |= cls.__abstractmethods__ allowed |= {a for a in dir(cls) if not a.startswith('_')} if not allowed: print('%s does not have abstract methods' % name) return public = {a for a in dir(o) if not a.startswith('_')} for attr in sorted(public - allowed): print('public attributes not in abstract interface: %s.%s' % ( name, attr)) # Facilitates testing localpeer. class dummyrepo(object): def __init__(self): self.ui = uimod.ui() def filtered(self, name): pass def _restrictcapabilities(self, caps): pass class dummyopener(object): handlers = [] # Facilitates testing sshpeer without requiring an SSH server. class badpeer(httppeer.httppeer): def __init__(self): super(badpeer, self).__init__(None, None, None, dummyopener()) self.badattribute = True def badmethod(self): pass class dummypipe(object): def close(self): pass def main(): ui = uimod.ui() checkobject(badpeer()) checkobject(httppeer.httppeer(None, None, None, dummyopener())) checkobject(localrepo.localpeer(dummyrepo())) checkobject(sshpeer.sshv1peer(ui, 'ssh://localhost/foo', None, dummypipe(), dummypipe(), None, None)) checkobject(sshpeer.sshv2peer(ui, 'ssh://localhost/foo', None, dummypipe(), dummypipe(), None, None)) checkobject(bundlerepo.bundlepeer(dummyrepo())) checkobject(statichttprepo.statichttppeer(dummyrepo())) checkobject(unionrepo.unionpeer(dummyrepo())) main()