Mercurial > public > mercurial-scm > hg
comparison contrib/phabricator.py @ 39650:d8f07b16abfc
phabricator: add support for using the vcr library to mock interactions
I'll use this in an upcoming test. The decorator dancing in this is
more complicated than I'd like, but it beats repeating all this code
everywhere.
Differential Revision: https://phab.mercurial-scm.org/D4600
author | Augie Fackler <raf@durin42.com> |
---|---|
date | Sat, 15 Sep 2018 00:20:03 -0400 |
parents | 0dce1297dd01 |
children |
comparison
equal
deleted
inserted
replaced
39649:d6d094259d9c | 39650:d8f07b16abfc |
---|---|
103 b'phabricator.action.updated': b'magenta', | 103 b'phabricator.action.updated': b'magenta', |
104 b'phabricator.desc': b'', | 104 b'phabricator.desc': b'', |
105 b'phabricator.drev': b'bold', | 105 b'phabricator.drev': b'bold', |
106 b'phabricator.node': b'', | 106 b'phabricator.node': b'', |
107 } | 107 } |
108 | |
109 _VCR_FLAGS = [ | |
110 (b'', b'test-vcr', b'', | |
111 _(b'Path to a vcr file. If nonexistent, will record a new vcr transcript' | |
112 b', otherwise will mock all http requests using the specified vcr file.' | |
113 b' (ADVANCED)' | |
114 )), | |
115 ] | |
116 | |
117 def vcrcommand(name, flags, spec): | |
118 fullflags = flags + _VCR_FLAGS | |
119 def decorate(fn): | |
120 def inner(*args, **kwargs): | |
121 cassette = kwargs.pop(r'test_vcr', None) | |
122 if cassette: | |
123 import hgdemandimport | |
124 with hgdemandimport.deactivated(): | |
125 import vcr as vcrmod | |
126 import vcr.stubs as stubs | |
127 vcr = vcrmod.VCR( | |
128 serializer=r'json', | |
129 custom_patches=[ | |
130 (urlmod, 'httpconnection', stubs.VCRHTTPConnection), | |
131 (urlmod, 'httpsconnection', stubs.VCRHTTPSConnection), | |
132 ]) | |
133 with vcr.use_cassette(cassette): | |
134 return fn(*args, **kwargs) | |
135 return fn(*args, **kwargs) | |
136 inner.__name__ = fn.__name__ | |
137 return command(name, fullflags, spec)(inner) | |
138 return decorate | |
108 | 139 |
109 def urlencodenested(params): | 140 def urlencodenested(params): |
110 """like urlencode, but works with nested parameters. | 141 """like urlencode, but works with nested parameters. |
111 | 142 |
112 For example, if params is {'a': ['b', 'c'], 'd': {'e': 'f'}}, it will be | 143 For example, if params is {'a': ['b', 'c'], 'd': {'e': 'f'}}, it will be |
213 msg = (_(b'Conduit Error (%s): %s') | 244 msg = (_(b'Conduit Error (%s): %s') |
214 % (parsed[r'error_code'], parsed[r'error_info'])) | 245 % (parsed[r'error_code'], parsed[r'error_info'])) |
215 raise error.Abort(msg) | 246 raise error.Abort(msg) |
216 return parsed[r'result'] | 247 return parsed[r'result'] |
217 | 248 |
218 @command(b'debugcallconduit', [], _(b'METHOD')) | 249 @vcrcommand(b'debugcallconduit', [], _(b'METHOD')) |
219 def debugcallconduit(ui, repo, name): | 250 def debugcallconduit(ui, repo, name): |
220 """call Conduit API | 251 """call Conduit API |
221 | 252 |
222 Call parameters are read from stdin as a JSON blob. Result will be written | 253 Call parameters are read from stdin as a JSON blob. Result will be written |
223 to stdout as a JSON blob. | 254 to stdout as a JSON blob. |
450 if unresolved: | 481 if unresolved: |
451 raise error.Abort(_(b'unknown username: %s') | 482 raise error.Abort(_(b'unknown username: %s') |
452 % b' '.join(sorted(unresolved))) | 483 % b' '.join(sorted(unresolved))) |
453 return [entry[r'phid'] for entry in data] | 484 return [entry[r'phid'] for entry in data] |
454 | 485 |
455 @command(b'phabsend', | 486 @vcrcommand(b'phabsend', |
456 [(b'r', b'rev', [], _(b'revisions to send'), _(b'REV')), | 487 [(b'r', b'rev', [], _(b'revisions to send'), _(b'REV')), |
457 (b'', b'amend', True, _(b'update commit messages')), | 488 (b'', b'amend', True, _(b'update commit messages')), |
458 (b'', b'reviewer', [], _(b'specify reviewers')), | 489 (b'', b'reviewer', [], _(b'specify reviewers')), |
459 (b'', b'confirm', None, _(b'ask for confirmation before sending'))], | 490 (b'', b'confirm', None, _(b'ask for confirmation before sending'))], |
460 _(b'REV [OPTIONS]')) | 491 _(b'REV [OPTIONS]')) |
907 header += b'# %s %s\n' % (_metanamemap[k], meta[k]) | 938 header += b'# %s %s\n' % (_metanamemap[k], meta[k]) |
908 | 939 |
909 content = b'%s%s\n%s' % (header, desc, body) | 940 content = b'%s%s\n%s' % (header, desc, body) |
910 write(encoding.unitolocal(content)) | 941 write(encoding.unitolocal(content)) |
911 | 942 |
912 @command(b'phabread', | 943 @vcrcommand(b'phabread', |
913 [(b'', b'stack', False, _(b'read dependencies'))], | 944 [(b'', b'stack', False, _(b'read dependencies'))], |
914 _(b'DREVSPEC [OPTIONS]')) | 945 _(b'DREVSPEC [OPTIONS]')) |
915 def phabread(ui, repo, spec, **opts): | 946 def phabread(ui, repo, spec, **opts): |
916 """print patches from Phabricator suitable for importing | 947 """print patches from Phabricator suitable for importing |
917 | 948 |
934 if opts.get(b'stack'): | 965 if opts.get(b'stack'): |
935 spec = b':(%s)' % spec | 966 spec = b':(%s)' % spec |
936 drevs = querydrev(repo, spec) | 967 drevs = querydrev(repo, spec) |
937 readpatch(repo, drevs, ui.write) | 968 readpatch(repo, drevs, ui.write) |
938 | 969 |
939 @command(b'phabupdate', | 970 @vcrcommand(b'phabupdate', |
940 [(b'', b'accept', False, _(b'accept revisions')), | 971 [(b'', b'accept', False, _(b'accept revisions')), |
941 (b'', b'reject', False, _(b'reject revisions')), | 972 (b'', b'reject', False, _(b'reject revisions')), |
942 (b'', b'abandon', False, _(b'abandon revisions')), | 973 (b'', b'abandon', False, _(b'abandon revisions')), |
943 (b'', b'reclaim', False, _(b'reclaim revisions')), | 974 (b'', b'reclaim', False, _(b'reclaim revisions')), |
944 (b'm', b'comment', b'', _(b'comment on the last revision')), | 975 (b'm', b'comment', b'', _(b'comment on the last revision')), |