##// END OF EJS Templates
rust-cpython: binding for LazyAncestors...
Georges Racinet -
r41149:b31a41f2 default
parent child Browse files
Show More
@@ -13,8 +13,8 b' use cpython::{'
13 13 };
14 14 use exceptions::GraphError;
15 15 use hg;
16 use hg::AncestorsIterator as CoreIterator;
17 16 use hg::Revision;
17 use hg::{AncestorsIterator as CoreIterator, LazyAncestors as CoreLazy};
18 18 use std::cell::RefCell;
19 19
20 20 /// Utility function to convert a Python iterable into a Vec<Revision>
@@ -70,6 +70,37 b' impl AncestorsIterator {'
70 70 }
71 71 }
72 72
73 py_class!(class LazyAncestors |py| {
74 data inner: RefCell<Box<CoreLazy<Index>>>;
75
76 def __contains__(&self, rev: Revision) -> PyResult<bool> {
77 self.inner(py)
78 .borrow_mut()
79 .contains(rev)
80 .map_err(|e| GraphError::pynew(py, e))
81 }
82
83 def __iter__(&self) -> PyResult<AncestorsIterator> {
84 AncestorsIterator::from_inner(py, self.inner(py).borrow().iter())
85 }
86
87 def __bool__(&self) -> PyResult<bool> {
88 Ok(!self.inner(py).borrow().is_empty())
89 }
90
91 def __new__(_cls, index: PyObject, initrevs: PyObject, stoprev: Revision,
92 inclusive: bool) -> PyResult<Self> {
93 let initvec = reviter_to_revvec(py, initrevs)?;
94
95 let lazy =
96 CoreLazy::new(Index::new(py, index)?, initvec, stoprev, inclusive)
97 .map_err(|e| GraphError::pynew(py, e))?;
98
99 Self::create_instance(py, RefCell::new(Box::new(lazy)))
100 }
101
102 });
103
73 104 /// Create the module, with __package__ given from parent
74 105 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
75 106 let dotted_name = &format!("{}.ancestor", package);
@@ -81,6 +112,7 b' pub fn init_module(py: Python, package: '
81 112 "Generic DAG ancestor algorithms - Rust implementation",
82 113 )?;
83 114 m.add_class::<AncestorsIterator>(py)?;
115 m.add_class::<LazyAncestors>(py)?;
84 116
85 117 let sys = PyModule::import(py, "sys")?;
86 118 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
@@ -9,7 +9,10 b' except ImportError:'
9 9 rustext = None
10 10 else:
11 11 # this would fail already without appropriate ancestor.__package__
12 from mercurial.rustext.ancestor import AncestorsIterator
12 from mercurial.rustext.ancestor import (
13 AncestorsIterator,
14 LazyAncestors
15 )
13 16
14 17 try:
15 18 from mercurial.cext import parsers as cparsers
@@ -71,6 +74,37 b' class rustancestorstest(unittest.TestCas'
71 74 ait = AncestorsIterator(idx, [3], 0, False)
72 75 self.assertEqual([r for r in ait], [2, 1, 0])
73 76
77 def testlazyancestors(self):
78 idx = self.parseindex()
79 start_count = sys.getrefcount(idx) # should be 2 (see Python doc)
80 self.assertEqual({i: (r[5], r[6]) for i, r in enumerate(idx)},
81 {0: (-1, -1),
82 1: (0, -1),
83 2: (1, -1),
84 3: (2, -1)})
85 lazy = LazyAncestors(idx, [3], 0, True)
86 # we have two more references to the index:
87 # - in its inner iterator for __contains__ and __bool__
88 # - in the LazyAncestors instance itself (to spawn new iterators)
89 self.assertEqual(sys.getrefcount(idx), start_count + 2)
90
91 self.assertTrue(2 in lazy)
92 self.assertTrue(bool(lazy))
93 self.assertEqual(list(lazy), [3, 2, 1, 0])
94 # a second time to validate that we spawn new iterators
95 self.assertEqual(list(lazy), [3, 2, 1, 0])
96
97 # now let's watch the refcounts closer
98 ait = iter(lazy)
99 self.assertEqual(sys.getrefcount(idx), start_count + 3)
100 del ait
101 self.assertEqual(sys.getrefcount(idx), start_count + 2)
102 del lazy
103 self.assertEqual(sys.getrefcount(idx), start_count)
104
105 # let's check bool for an empty one
106 self.assertFalse(LazyAncestors(idx, [0], 0, False))
107
74 108 def testrefcount(self):
75 109 idx = self.parseindex()
76 110 start_count = sys.getrefcount(idx)
@@ -87,7 +121,7 b' class rustancestorstest(unittest.TestCas'
87 121 # and removing ref to the index after iterator init is no issue
88 122 ait = AncestorsIterator(idx, [3], 0, True)
89 123 del idx
90 self.assertEqual([r for r in ait], [3, 2, 1, 0])
124 self.assertEqual(list(ait), [3, 2, 1, 0])
91 125
92 126 def testgrapherror(self):
93 127 data = (data_non_inlined[:64 + 27] +
General Comments 0
You need to be logged in to leave comments. Login now