MCPcopy
hub / github.com/pimutils/vdirsyncer / sync

Function sync

vdirsyncer/sync/__init__.py:90–158  ·  view source on GitHub ↗

Synchronizes two storages. :param storage_a: The first storage :type storage_a: :class:`vdirsyncer.storage.base.Storage` :param storage_b: The second storage :type storage_b: :class:`vdirsyncer.storage.base.Storage` :param status: {ident: (href_a, etag_a, href_b, etag_b)}

(storage_a, storage_b, status, conflict_resolution=None,
         force_delete=False, error_callback=None, partial_sync='revert')

Source from the content-addressed store, hash-verified

88
89
90def sync(storage_a, storage_b, status, conflict_resolution=None,
91 force_delete=False, error_callback=None, partial_sync='revert'):
92 '''Synchronizes two storages.
93
94 :param storage_a: The first storage
95 :type storage_a: :class:`vdirsyncer.storage.base.Storage`
96 :param storage_b: The second storage
97 :type storage_b: :class:`vdirsyncer.storage.base.Storage`
98 :param status: {ident: (href_a, etag_a, href_b, etag_b)}
99 metadata about the two storages for detection of changes. Will be
100 modified by the function and should be passed to it at the next sync.
101 If this is the first sync, an empty dictionary should be provided.
102 :param conflict_resolution: A function that, given two conflicting item
103 versions A and B, returns a new item with conflicts resolved. The UID
104 must be the same. The strings `"a wins"` and `"b wins"` are also
105 accepted to mean that side's version will always be taken. If none
106 is provided, the sync function will raise :py:exc:`SyncConflict`.
107 :param force_delete: When one storage got completely emptied between two
108 syncs, :py:exc:`StorageEmpty` is raised for
109 safety. Setting this parameter to ``True`` disables this safety
110 measure.
111 :param error_callback: Instead of raising errors when executing actions,
112 call the given function with an `Exception` as the only argument.
113 :param partial_sync: What to do when doing sync actions on read-only
114 storages.
115
116 - ``error``: Raise an error.
117 - ``ignore``: Those actions are simply skipped.
118 - ``revert`` (default): Revert changes on other side.
119 '''
120 if storage_a.read_only and storage_b.read_only:
121 raise BothReadOnly()
122
123 if conflict_resolution == 'a wins':
124 conflict_resolution = lambda a, b: a
125 elif conflict_resolution == 'b wins':
126 conflict_resolution = lambda a, b: b
127
128 status_nonempty = bool(next(status.iter_old(), None))
129
130 with status.transaction():
131 a_info = _StorageInfo(storage_a, SubStatus(status, 'a'))
132 b_info = _StorageInfo(storage_b, SubStatus(status, 'b'))
133
134 a_nonempty = a_info.prepare_new_status()
135 b_nonempty = b_info.prepare_new_status()
136
137 if status_nonempty and not force_delete:
138 if a_nonempty and not b_nonempty:
139 raise StorageEmpty(empty_storage=storage_b)
140 elif not a_nonempty and b_nonempty:
141 raise StorageEmpty(empty_storage=storage_a)
142
143 actions = list(_get_actions(a_info, b_info))
144
145 with storage_a.at_once(), storage_b.at_once():
146 for action in actions:
147 try:

Callers

nothing calls this directly

Calls 11

BothReadOnlyClass · 0.85
_StorageInfoClass · 0.85
SubStatusClass · 0.85
StorageEmptyClass · 0.85
_get_actionsFunction · 0.85
error_callbackFunction · 0.85
prepare_new_statusMethod · 0.80
iter_oldMethod · 0.45
transactionMethod · 0.45
at_onceMethod · 0.45
runMethod · 0.45

Tested by

no test coverage detected