fix: add sync.make_selector() convenience function

wraps `fabsync.ItemSelector.new()`
This commit is contained in:
Lance Edgar 2024-09-10 20:10:15 -05:00
parent 2a83142d95
commit e3b593d628
2 changed files with 45 additions and 5 deletions

View file

@ -44,20 +44,41 @@ def make_root(path, dest='/'):
return fabsync.load(path, dest) return fabsync.load(path, dest)
def isync(c, root, selector=None, echo=True, **kwargs): def make_selector(subpath=None, **kwargs):
"""
Make and return an "item selector" for use with a sync call.
This is a convenience wrapper around
:meth:`fabsync:fabsync.ItemSelector.new()`.
:param subpath: (Optional) Relative subpath of the file tree to
sync, e.g. ``'etc/postfix'``.
:param tags: Optional iterable of tags to include; excluding any
files which are not so tagged. E.g. ``{'foo'}``
"""
return fabsync.ItemSelector.new(subpath, **kwargs)
def isync(c, root, selector=None, tags=None, echo=True, **kwargs):
""" """
Sync files, yielding the result for each as it goes. Sync files, yielding the result for each as it goes.
This is a convenience wrapper around This is a convenience wrapper around
:func:`fabsync:fabsync.isync()`. :func:`fabsync:fabsync.isync()`.
:param c: Connection object. :param c: Fabric connection.
:param root: File tree "root" object as obtained from :param root: File tree "root" object as obtained from
:func:`make_root()`. :func:`make_root()`.
:param selector: This can be a simple "subpath" string, indicating :param selector: This can be a simple "subpath" string, indicating
a section of the file tree. For instance: ``'etc/postfix'`` a section of the file tree (e.g. ``'etc/postfix'``). Or can be
a :class:`fabsync.ItemSelector` instance.
:param tags: Optional iterable of tags to select. If ``selector``
is a subpath string, and you specify ``tags`` then they will be
included when creating the actual selector.
:param echo: Flag indicating whether the path for each file synced :param echo: Flag indicating whether the path for each file synced
should be echoed to stdout. Generally thought to be useful but should be echoed to stdout. Generally thought to be useful but
@ -68,7 +89,10 @@ def isync(c, root, selector=None, echo=True, **kwargs):
""" """
if selector: if selector:
if not isinstance(selector, fabsync.ItemSelector): if not isinstance(selector, fabsync.ItemSelector):
selector = fabsync.ItemSelector.new(selector) kw = {}
if tags:
kw['tags'] = tags
selector = make_selector(selector, **kw)
kwargs['selector'] = selector kwargs['selector'] = selector
for result in fabsync.isync(c, root, **kwargs): for result in fabsync.isync(c, root, **kwargs):

View file

@ -18,6 +18,14 @@ class TestMakeRoot(TestCase):
self.assertEqual(root.dest, Path('/')) self.assertEqual(root.dest, Path('/'))
class TestMakeSelector(TestCase):
def test_basic(self):
selector = mod.make_selector('etc/postfix')
self.assertIsInstance(selector, ItemSelector)
self.assertEqual(selector.subpath, Path('etc/postfix'))
class TestIsync(TestCase): class TestIsync(TestCase):
def test_basic(self): def test_basic(self):
@ -40,7 +48,7 @@ class TestIsync(TestCase):
self.assertEqual(results, [result]) self.assertEqual(results, [result])
fabsync.isync.assert_called_once_with(c, root) fabsync.isync.assert_called_once_with(c, root)
# sync with selector # sync with selector (subpath)
fabsync.isync.reset_mock() fabsync.isync.reset_mock()
result = MagicMock(path='/foo', modified=True) result = MagicMock(path='/foo', modified=True)
fabsync.isync.return_value = [result] fabsync.isync.return_value = [result]
@ -48,6 +56,14 @@ class TestIsync(TestCase):
self.assertEqual(results, [result]) self.assertEqual(results, [result])
fabsync.isync.assert_called_once_with(c, root, selector=fabsync.ItemSelector.new('foo')) fabsync.isync.assert_called_once_with(c, root, selector=fabsync.ItemSelector.new('foo'))
# sync with selector (subpath + tags)
fabsync.isync.reset_mock()
result = MagicMock(path='/foo', modified=True)
fabsync.isync.return_value = [result]
results = list(mod.isync(c, root, 'foo', tags={'bar'}))
self.assertEqual(results, [result])
fabsync.isync.assert_called_once_with(c, root, selector=fabsync.ItemSelector.new('foo', tags={'bar'}))
class TestCheckIsync(TestCase): class TestCheckIsync(TestCase):