Submitter | Pierre-Yves David |
---|---|
Date | April 3, 2014, 10:57 p.m. |
Message ID | <44096fd181296f228c1f.1396565870@marginatus.alto.octopoid.net> |
Download | mbox | patch |
Permalink | /patch/4213/ |
State | Accepted |
Headers | show |
Comments
On 4/3/14 3:57 PM, pierre-yves.david@ens-lyon.org wrote: > # HG changeset patch > # User Pierre-Yves David <pierre-yves.david@fb.com> > # Date 1396503470 25200 > # Wed Apr 02 22:37:50 2014 -0700 > # Node ID 44096fd181296f228c1f2d869b53034b55d2bac9 > # Parent d47181150c1edace8a5e5da51e99dffe17d52407 > bundle2: records processing results in the bundleoperation object > > Part handlers can now add records to the `bundleoperation` object This can be > used to help other part or to let the caller of the unbundling process to react > to the results. > > diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py > --- a/mercurial/bundle2.py > +++ b/mercurial/bundle2.py > @@ -181,10 +181,50 @@ def parthandler(parttype): > assert lparttype not in parthandlermapping > parthandlermapping[lparttype] = func > return func > return _decorator > > +class unbundlerecords(object): > + """keep record of what happen during and unbundle > + > + New record are added using `records.add('cat', obj)`. Where 'cat' is a > + category of record and obj is an arbitraty object. > + > + `records['cat']` will return all entries of this category 'cat'. > + > + Iterating on the object itself will yield `('category', obj)` tuple for all > + entries. > + > + All iterations happens in chronological order. > + """ > + > + def __init__(self): > + self._categories = {} > + self._sequences = [] > + > + def add(self, category, entry): > + """add a new record of a given category. > + > + The entry can then be retrieved in the list returned by > + self['category'].""" > + category = str(category) > + self._categories.setdefault(category, []).append(entry) > + self._sequences.append((category, entry)) > + > + def __getitem__(self, cat): > + return tuple(self._categories.get(cat, ())) > + add() converts category to a str() before using it, but __getitem__() does not. Seems inconsistent. Why bother doing the str() at all?
On 04/03/2014 07:01 PM, Durham Goode wrote: > > On 4/3/14 3:57 PM, pierre-yves.david@ens-lyon.org wrote: >> # HG changeset patch >> # User Pierre-Yves David <pierre-yves.david@fb.com> >> # Date 1396503470 25200 >> # Wed Apr 02 22:37:50 2014 -0700 >> # Node ID 44096fd181296f228c1f2d869b53034b55d2bac9 >> # Parent d47181150c1edace8a5e5da51e99dffe17d52407 >> bundle2: records processing results in the bundleoperation object >> >> Part handlers can now add records to the `bundleoperation` object This >> can be >> used to help other part or to let the caller of the unbundling process >> to react >> to the results. >> >> diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py >> --- a/mercurial/bundle2.py >> +++ b/mercurial/bundle2.py >> @@ -181,10 +181,50 @@ def parthandler(parttype): >> assert lparttype not in parthandlermapping >> parthandlermapping[lparttype] = func >> return func >> return _decorator >> +class unbundlerecords(object): >> + """keep record of what happen during and unbundle >> + >> + New record are added using `records.add('cat', obj)`. Where 'cat' >> is a >> + category of record and obj is an arbitraty object. >> + >> + `records['cat']` will return all entries of this category 'cat'. >> + >> + Iterating on the object itself will yield `('category', obj)` >> tuple for all >> + entries. >> + >> + All iterations happens in chronological order. >> + """ >> + >> + def __init__(self): >> + self._categories = {} >> + self._sequences = [] >> + >> + def add(self, category, entry): >> + """add a new record of a given category. >> + >> + The entry can then be retrieved in the list returned by >> + self['category'].""" >> + category = str(category) >> + self._categories.setdefault(category, []).append(entry) >> + self._sequences.append((category, entry)) >> + >> + def __getitem__(self, cat): >> + return tuple(self._categories.get(cat, ())) >> + > add() converts category to a str() before using it, but __getitem__() > does not. Seems inconsistent. Why bother doing the str() at all? We can drop it.
Patch
diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py --- a/mercurial/bundle2.py +++ b/mercurial/bundle2.py @@ -181,10 +181,50 @@ def parthandler(parttype): assert lparttype not in parthandlermapping parthandlermapping[lparttype] = func return func return _decorator +class unbundlerecords(object): + """keep record of what happen during and unbundle + + New record are added using `records.add('cat', obj)`. Where 'cat' is a + category of record and obj is an arbitraty object. + + `records['cat']` will return all entries of this category 'cat'. + + Iterating on the object itself will yield `('category', obj)` tuple for all + entries. + + All iterations happens in chronological order. + """ + + def __init__(self): + self._categories = {} + self._sequences = [] + + def add(self, category, entry): + """add a new record of a given category. + + The entry can then be retrieved in the list returned by + self['category'].""" + category = str(category) + self._categories.setdefault(category, []).append(entry) + self._sequences.append((category, entry)) + + def __getitem__(self, cat): + return tuple(self._categories.get(cat, ())) + + def __iter__(self): + return iter(self._sequences) + + def __len__(self): + return len(self._sequences) + + def __nonzero__(self): + return bool(self._sequences) + + class bundleoperation(object): """an object that represent a single bundle processing It purpose is to carry unbundle related objects and states. @@ -200,10 +240,11 @@ class bundleoperation(object): """ def __init__(self, repo): self.repo = repo self.ui = repo.ui + self.records = unbundlerecords() def processbundle(repo, unbundler): """This function process a bundle, apply effect to/from a repo @@ -241,10 +282,11 @@ def processbundle(repo, unbundler): handler(op, part) except Exception: for part in iterparts: pass # consume the bundle content raise + return op class bundle20(object): """represent an outgoing bundle2 container Use the `addparam` method to add stream level parameter. and `addpart` to diff --git a/tests/test-bundle2.t b/tests/test-bundle2.t --- a/tests/test-bundle2.t +++ b/tests/test-bundle2.t @@ -22,12 +22,15 @@ Create an extension to test bundle2 API > > @bundle2.parthandler('test:song') > def songhandler(op, part): > """handle a "test:song" bundle2 part, printing the lyrics on stdin""" > op.ui.write('The choir start singing:\n') + > verses = 0 > for line in part.data.split('\n'): > op.ui.write(' %s\n' % line) + > verses += 1 + > op.records.add('song', {'verses': verses}) > > @command('bundle2', > [('', 'param', [], 'stream level parameter'), > ('', 'unknown', False, 'include an unknown mandatory part in the bundle'), > ('', 'parts', False, 'include some arbitrary parts to the bundle'),], @@ -72,16 +75,19 @@ Create an extension to test bundle2 API > def cmdunbundle2(ui, repo): > """process a bundle2 stream from stdin on the current repo""" > try: > try: > unbundler = bundle2.unbundle20(ui, sys.stdin) - > bundle2.processbundle(repo, unbundler) + > op = bundle2.processbundle(repo, unbundler) > except KeyError, exc: > raise util.Abort('missing support for %s' % exc) > finally: > remains = sys.stdin.read() > ui.write('%i unread bytes\n' % len(remains)) + > if op.records['song']: + > totalverses = sum(r['verses'] for r in op.records['song']) + > ui.write('%i total verses sung\n' % totalverses) > > @command('statbundle2', [], '') > def cmdstatbundle2(ui, repo): > """print statistic on the bundle2 container read from stdin""" > unbundler = bundle2.unbundle20(ui, sys.stdin) @@ -389,10 +395,11 @@ Process the bundle payload chunk size: 0 ignoring unknown advisory part 'test:math' part header size: 0 end of bundle2 stream 0 unread bytes + 3 total verses sung $ hg bundle2 --parts --unknown ../unknown.hg2 $ hg unbundle2 < ../unknown.hg2