datashare-python 0.12.7__tar.gz → 0.12.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {datashare_python-0.12.7 → datashare_python-0.12.9}/PKG-INFO +1 -1
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/config.py +4 -1
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/utils.py +38 -12
- datashare_python-0.12.9/datashare_python/worker-template.tar.gz +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/pyproject.toml +1 -1
- datashare_python-0.12.7/datashare_python/worker-template.tar.gz +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/.gitignore +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/README.md +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/.gitignore +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/__init__.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/__main__.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/cli/__init__.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/cli/project.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/cli/task.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/cli/utils.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/cli/worker.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/conftest.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/constants.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/dependencies.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/discovery.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/exceptions.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/interceptors.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/logging_.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/mimetypes_.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/objects.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/task_client.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/template.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/types_.py +0 -0
- {datashare_python-0.12.7 → datashare_python-0.12.9}/datashare_python/worker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: datashare-python
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.9
|
|
4
4
|
Summary: Manage Python tasks and local resources in Datashare
|
|
5
5
|
Project-URL: Homepage, https://icij.github.io/datashare-python/
|
|
6
6
|
Project-URL: Documentation, https://icij.github.io/datashare-python/
|
|
@@ -114,6 +114,7 @@ class LoggingConfig(BaseModel):
|
|
|
114
114
|
|
|
115
115
|
class ResourceCacheConfig(BaseModel):
|
|
116
116
|
size: int = 1
|
|
117
|
+
refresh_interval: int | None = None
|
|
117
118
|
exit_context_managers: bool = True
|
|
118
119
|
|
|
119
120
|
def to_resource_cache(self) -> "SharedResources":
|
|
@@ -123,7 +124,9 @@ class ResourceCacheConfig(BaseModel):
|
|
|
123
124
|
if self.exit_context_managers:
|
|
124
125
|
eviction_callback = close_cm_callback
|
|
125
126
|
return SharedResources(
|
|
126
|
-
cache_size=self.size,
|
|
127
|
+
cache_size=self.size,
|
|
128
|
+
eviction_callback=eviction_callback,
|
|
129
|
+
refresh_interval=self.refresh_interval,
|
|
127
130
|
)
|
|
128
131
|
|
|
129
132
|
|
|
@@ -822,9 +822,11 @@ class SharedResources:
|
|
|
822
822
|
self,
|
|
823
823
|
cache_size: int = 1,
|
|
824
824
|
eviction_callback: Callable[[Any, Any], None] | None = None,
|
|
825
|
+
refresh_interval: int | None = None,
|
|
825
826
|
) -> None:
|
|
826
827
|
self._eviction_callback = eviction_callback
|
|
827
828
|
self._cache = LRU(cache_size, self._on_evict)
|
|
829
|
+
self._refresh_interval = refresh_interval
|
|
828
830
|
self._sentinel = object()
|
|
829
831
|
# Leased resources are tracked by id, evicting a leased resource defers the
|
|
830
832
|
# eviction callback until its last lease is released
|
|
@@ -854,6 +856,14 @@ class SharedResources:
|
|
|
854
856
|
"""
|
|
855
857
|
value = self._get_and_acquire(key)
|
|
856
858
|
if value is self._sentinel:
|
|
859
|
+
# The factory can be long to complete (that's one of the reason we want to
|
|
860
|
+
# cache its results). Because we don't lock the factory call, together with
|
|
861
|
+
# the cache update, in case of concurrent access, quicker factories will
|
|
862
|
+
# complete first and will stay longer in the cache. This is fine, the
|
|
863
|
+
# alternative is to lock factory + cache update to avoid concurrent access
|
|
864
|
+
# but this will mean waiting for the first factory call to complete, this
|
|
865
|
+
# can potentially imply longer waits than no getting the value from the
|
|
866
|
+
# cache
|
|
857
867
|
value = default_factory()
|
|
858
868
|
self._cache_and_acquire(key, value)
|
|
859
869
|
try:
|
|
@@ -873,6 +883,14 @@ class SharedResources:
|
|
|
873
883
|
"""
|
|
874
884
|
value = self._get_and_acquire(key)
|
|
875
885
|
if value is self._sentinel:
|
|
886
|
+
# The factory can be long to complete (that's one of the reason we want to
|
|
887
|
+
# cache its results). Because we don't lock the factory call, together with
|
|
888
|
+
# the cache update, in case of concurrent access, quicker factories will
|
|
889
|
+
# complete first and will stay longer in the cache. This is fine, the
|
|
890
|
+
# alternative is to lock factory + cache update to avoid concurrent access
|
|
891
|
+
# but this will mean waiting for the first factory call to complete, this
|
|
892
|
+
# can potentially imply longer waits than no getting the value from the
|
|
893
|
+
# cache
|
|
876
894
|
value = await default_factory()
|
|
877
895
|
self._cache_and_acquire(key, value)
|
|
878
896
|
try:
|
|
@@ -884,28 +902,33 @@ class SharedResources:
|
|
|
884
902
|
with self._lock:
|
|
885
903
|
value = self._cache.get(key, self._sentinel)
|
|
886
904
|
if value is not self._sentinel:
|
|
887
|
-
|
|
905
|
+
# If refresh needs to happen, we set the value to the sentinel.
|
|
906
|
+
# The old value will be release with the last user call to _release.
|
|
907
|
+
# Returning the sentinel will trigger the call to the factory
|
|
908
|
+
refresh = (
|
|
909
|
+
self._refresh_interval is not None
|
|
910
|
+
and self._n_leases.get(self._vkey(value), 0)
|
|
911
|
+
>= self._refresh_interval
|
|
912
|
+
)
|
|
913
|
+
if refresh:
|
|
914
|
+
self._pending_evictions[self._vkey(value)] = (key, value)
|
|
915
|
+
value = self._sentinel
|
|
916
|
+
else:
|
|
917
|
+
self._acquire(value)
|
|
888
918
|
return value
|
|
889
919
|
|
|
890
920
|
def _cache_and_acquire(self, key: str, value: Any) -> None:
|
|
891
|
-
# The factory can be long to complete (that's one of the reason we want to
|
|
892
|
-
# cache its results). Because we don't lock the factory call, together with
|
|
893
|
-
# the cache update, in case of concurrent access, quicker factories will
|
|
894
|
-
# complete first and will stay longer in the cache. This is fine, the
|
|
895
|
-
# alternative is to lock factory + cache update to avoid concurrent access but
|
|
896
|
-
# this will mean waiting for the first factory call to complete, this can
|
|
897
|
-
# potentially imply longer waits than no getting the value from the cache
|
|
898
921
|
with self._lock:
|
|
899
922
|
self._acquire(value)
|
|
900
923
|
# Can evict other resources, must be called without holding the lock
|
|
901
924
|
self._cache[key] = value
|
|
902
925
|
|
|
903
926
|
def _acquire(self, value: Any) -> None:
|
|
904
|
-
value_id =
|
|
927
|
+
value_id = self._vkey(value)
|
|
905
928
|
self._n_leases[value_id] = self._n_leases.get(value_id, 0) + 1
|
|
906
929
|
|
|
907
930
|
def _release(self, value: Any) -> None:
|
|
908
|
-
value_id =
|
|
931
|
+
value_id = self._vkey(value)
|
|
909
932
|
with self._lock:
|
|
910
933
|
self._n_leases[value_id] -= 1
|
|
911
934
|
if self._n_leases[value_id]:
|
|
@@ -917,8 +940,8 @@ class SharedResources:
|
|
|
917
940
|
|
|
918
941
|
def _on_evict(self, key: Any, value: Any) -> None:
|
|
919
942
|
with self._lock:
|
|
920
|
-
if
|
|
921
|
-
self._pending_evictions[
|
|
943
|
+
if self._vkey(value) in self._n_leases:
|
|
944
|
+
self._pending_evictions[self._vkey(value)] = (key, value)
|
|
922
945
|
return
|
|
923
946
|
self._evict(key, value)
|
|
924
947
|
|
|
@@ -926,6 +949,9 @@ class SharedResources:
|
|
|
926
949
|
if self._eviction_callback is not None:
|
|
927
950
|
self._eviction_callback(key, value)
|
|
928
951
|
|
|
952
|
+
def _vkey(self, value: Any) -> int:
|
|
953
|
+
return id(value)
|
|
954
|
+
|
|
929
955
|
|
|
930
956
|
def close_cm_callback(key: str, value: Any) -> None: # noqa: ARG001
|
|
931
957
|
if hasattr(value, "__exit__"):
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|