revset: add extra data to filteredset for better inspection
A filteredset is heavily used, but it cannot provide a printable information
how given set is filtered because a condition is an arbitrary callable object.
This patch adds an optional "condrepr" object that is used only by repr(). To
minimize the maintaining/runtime overhead of "condrepr", its type is overloaded
as follows:
type example
-------- ---------------------------------
tuple ('<not %r>', other)
str '<branch closed>'
callable lambda: '<branch %r>' % sorted(b)
object other
--- a/mercurial/revset.py Tue Mar 01 10:18:47 2016 +0000
+++ b/mercurial/revset.py Sat Feb 13 19:25:11 2016 +0900
@@ -2730,6 +2730,29 @@
funcs.add(tree[1][1])
return funcs
+def _formatsetrepr(r):
+ """Format an optional printable representation of a set
+
+ ======== =================================
+ type(r) example
+ ======== =================================
+ tuple ('<not %r>', other)
+ str '<branch closed>'
+ callable lambda: '<branch %r>' % sorted(b)
+ object other
+ ======== =================================
+ """
+ if r is None:
+ return ''
+ elif isinstance(r, tuple):
+ return r[0] % r[1:]
+ elif isinstance(r, str):
+ return r
+ elif callable(r):
+ return r()
+ else:
+ return repr(r)
+
class abstractsmartset(object):
def __nonzero__(self):
@@ -2810,7 +2833,7 @@
This is part of the mandatory API for smartset."""
if isinstance(other, fullreposet):
return self
- return self.filter(other.__contains__, cache=False)
+ return self.filter(other.__contains__, condrepr=other, cache=False)
def __add__(self, other):
"""Returns a new object with the union of the two collections.
@@ -2823,19 +2846,21 @@
This is part of the mandatory API for smartset."""
c = other.__contains__
- return self.filter(lambda r: not c(r), cache=False)
-
- def filter(self, condition, cache=True):
+ return self.filter(lambda r: not c(r), condrepr=('<not %r>', other),
+ cache=False)
+
+ def filter(self, condition, condrepr=None, cache=True):
"""Returns this smartset filtered by condition as a new smartset.
`condition` is a callable which takes a revision number and returns a
- boolean.
+ boolean. Optional `condrepr` provides a printable representation of
+ the given `condition`.
This is part of the mandatory API for smartset."""
# builtin cannot be cached. but do not needs to
if cache and util.safehasattr(condition, 'func_code'):
condition = util.cachefunc(condition)
- return filteredset(self, condition)
+ return filteredset(self, condition, condrepr)
class baseset(abstractsmartset):
"""Basic data structure that represents a revset and contains the basic
@@ -2939,13 +2964,16 @@
the subset and contains a function which tests for membership in the
revset
"""
- def __init__(self, subset, condition=lambda x: True):
+ def __init__(self, subset, condition=lambda x: True, condrepr=None):
"""
condition: a function that decide whether a revision in the subset
belongs to the revset or not.
+ condrepr: a tuple of (format, obj, ...), a function or an object that
+ provides a printable representation of the given condition.
"""
self._subset = subset
self._condition = condition
+ self._condrepr = condrepr
def __contains__(self, x):
return x in self._subset and self._condition(x)
@@ -3025,7 +3053,11 @@
return x
def __repr__(self):
- return '<%s %r>' % (type(self).__name__, self._subset)
+ xs = [repr(self._subset)]
+ s = _formatsetrepr(self._condrepr)
+ if s:
+ xs.append(s)
+ return '<%s %s>' % (type(self).__name__, ', '.join(xs))
def _iterordered(ascending, iter1, iter2):
"""produce an ordered iteration from two iterators with the same order
--- a/tests/test-revset.t Tue Mar 01 10:18:47 2016 +0000
+++ b/tests/test-revset.t Sat Feb 13 19:25:11 2016 +0900
@@ -169,7 +169,9 @@
('symbol', 'a'))
* set:
<filteredset
- <baseset [1]>>
+ <baseset [1]>,
+ <not
+ <baseset [0]>>>
1
$ try _a_b_c_
('symbol', '_a_b_c_')
@@ -182,7 +184,9 @@
('symbol', 'a'))
* set:
<filteredset
- <baseset [6]>>
+ <baseset [6]>,
+ <not
+ <baseset [0]>>>
6
$ try .a.b.c.
('symbol', '.a.b.c.')
@@ -195,7 +199,9 @@
('symbol', 'a'))
* set:
<filteredset
- <baseset [7]>>
+ <baseset [7]>,
+ <not
+ <baseset [0]>>>
7
names that should be caught by fallback mechanism
@@ -278,7 +284,9 @@
('symbol', 'a'))
* set:
<filteredset
- <baseset [4]>>
+ <baseset [4]>,
+ <not
+ <baseset [0]>>>
4
$ log '1 or 2'