ONE-api 3.0b4__py3-none-any.whl → 3.0b5__py3-none-any.whl
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.
- {ONE_api-3.0b4.dist-info → ONE_api-3.0b5.dist-info}/METADATA +1 -1
- {ONE_api-3.0b4.dist-info → ONE_api-3.0b5.dist-info}/RECORD +8 -8
- one/__init__.py +1 -1
- one/api.py +36 -6
- one/webclient.py +4 -2
- {ONE_api-3.0b4.dist-info → ONE_api-3.0b5.dist-info}/LICENSE +0 -0
- {ONE_api-3.0b4.dist-info → ONE_api-3.0b5.dist-info}/WHEEL +0 -0
- {ONE_api-3.0b4.dist-info → ONE_api-3.0b5.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
one/__init__.py,sha256=
|
|
2
|
-
one/api.py,sha256=
|
|
1
|
+
one/__init__.py,sha256=nInf_OtC7ZRulDTsGaWoCYJCQdioyk1iYSfMN-_fbMU,76
|
|
2
|
+
one/api.py,sha256=IWAjCBhw4DCLmfxcwVkOl0bgRlu2RXIV6Nyfey8HNas,131576
|
|
3
3
|
one/converters.py,sha256=icKlwPyxf3tJtyOFBj_SG06QDLIZLdTGalCSk1-cAvk,30733
|
|
4
4
|
one/params.py,sha256=zwR0Yq09ztROfH3fJsCUc-IDs_PBixT3WU3dm1vX728,15050
|
|
5
5
|
one/registration.py,sha256=cWvQFAzCF04wMZJjdOzBPJkYOJ3BO2KEgqtVG7qOlmA,36177
|
|
6
6
|
one/util.py,sha256=NUG_dTz3_4GXYG49qSql6mFCBkaVaq7_XdecRPRszJQ,20173
|
|
7
|
-
one/webclient.py,sha256=
|
|
7
|
+
one/webclient.py,sha256=CfHKn6eZu-woed_VEeY8DV6WTzb49u41-lBTRe-EYnM,50132
|
|
8
8
|
one/alf/__init__.py,sha256=DaFIi7PKlurp5HnyNOpJuIlY3pyhiottFpJfxR59VsY,70
|
|
9
9
|
one/alf/cache.py,sha256=NDN-Ii8E19C6IH1C7EQEIIgPFah3AtM9jhjLeHuBIjM,22735
|
|
10
10
|
one/alf/exceptions.py,sha256=6Gw8_ZObLnuYUpY4i0UyU4IA0kBZMBnJBGQyzIcDlUM,3427
|
|
@@ -30,8 +30,8 @@ one/tests/fixtures/rest_responses/6dc96f7e9bcc6ac2e7581489b9580a6cd3f28293,sha25
|
|
|
30
30
|
one/tests/fixtures/rest_responses/db1731fb8df0208944ae85f76718430813a8bf50,sha256=Dki7cTDg1bhbtPkuiv9NPRsuhM7TuicxoLcGtRD4D8g,209
|
|
31
31
|
one/tests/fixtures/rest_responses/dcce48259bb929661f60a02a48563f70aa6185b3,sha256=skaKl6sPgTyrufCIGNVNJfccXM-jSjYvAdyqNS3HXuA,416
|
|
32
32
|
one/tests/fixtures/rest_responses/f530d6022f61cdc9e38cc66beb3cb71f3003c9a1,sha256=EOqhNIVcmZ7j7aF09g5StFY434f2xbxwZLHwfeM4tug,22530
|
|
33
|
-
ONE_api-3.
|
|
34
|
-
ONE_api-3.
|
|
35
|
-
ONE_api-3.
|
|
36
|
-
ONE_api-3.
|
|
37
|
-
ONE_api-3.
|
|
33
|
+
ONE_api-3.0b5.dist-info/LICENSE,sha256=W6iRQJcr-tslNfY4gL98IWvPtpe0E3tcWCFOD3IFUqg,1087
|
|
34
|
+
ONE_api-3.0b5.dist-info/METADATA,sha256=V71vo5_2W9rsjtyhah07thKb0zXKS0VkM53Zw3eYRu8,4148
|
|
35
|
+
ONE_api-3.0b5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
36
|
+
ONE_api-3.0b5.dist-info/top_level.txt,sha256=LIsI2lzmA5jh8Zrw5dzMdE3ydLgmq-WF6rpoxSVDSAY,4
|
|
37
|
+
ONE_api-3.0b5.dist-info/RECORD,,
|
one/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""The Open Neurophysiology Environment (ONE) API."""
|
|
2
|
-
__version__ = '3.
|
|
2
|
+
__version__ = '3.0b5'
|
one/api.py
CHANGED
|
@@ -39,8 +39,10 @@ from one import util
|
|
|
39
39
|
|
|
40
40
|
_logger = logging.getLogger(__name__)
|
|
41
41
|
__all__ = ['ONE', 'One', 'OneAlyx']
|
|
42
|
-
|
|
43
|
-
"""
|
|
42
|
+
SAVE_ON_DELETE = (os.environ.get('ONE_SAVE_ON_DELETE') or '1').casefold() in ('true', '1')
|
|
43
|
+
"""bool: Whether to save modified cache tables on delete."""
|
|
44
|
+
|
|
45
|
+
_logger.debug('ONE_SAVE_ON_DELETE: %s', SAVE_ON_DELETE)
|
|
44
46
|
|
|
45
47
|
|
|
46
48
|
class One(ConversionMixin):
|
|
@@ -97,7 +99,8 @@ class One(ConversionMixin):
|
|
|
97
99
|
|
|
98
100
|
def __del__(self):
|
|
99
101
|
"""Save cache tables to disk before deleting the object."""
|
|
100
|
-
|
|
102
|
+
if SAVE_ON_DELETE:
|
|
103
|
+
self.save_cache()
|
|
101
104
|
|
|
102
105
|
@property
|
|
103
106
|
def offline(self):
|
|
@@ -162,6 +165,25 @@ class One(ConversionMixin):
|
|
|
162
165
|
if self.offline: # In online mode, the cache tables should be downloaded later
|
|
163
166
|
warnings.warn(f'No cache tables found in {self._tables_dir}')
|
|
164
167
|
|
|
168
|
+
# If in remote mode and loading old tables generated on Alyx,
|
|
169
|
+
# prompt the user to delete them to improve load times
|
|
170
|
+
raw_meta = self._cache['_meta'].get('raw', {}).values() or [{}]
|
|
171
|
+
tagged = any(filter(None, flatten(x.get('database_tags') for x in raw_meta)))
|
|
172
|
+
origin = set(x['origin'] for x in raw_meta if 'origin' in x)
|
|
173
|
+
older = (self._cache['_meta']['created_time'] or datetime.now()) < datetime(2025, 2, 13)
|
|
174
|
+
remote = not self.offline and self.mode == 'remote'
|
|
175
|
+
if remote and origin == {'alyx'} and older and not self._web_client.silent and not tagged:
|
|
176
|
+
message = ('Old Alyx cache tables detected on disk. '
|
|
177
|
+
'It\'s recomended to remove these tables as they '
|
|
178
|
+
'negatively affect performance.\nDelete these tables? [Y/n]: ')
|
|
179
|
+
if (input(message).casefold().strip() or 'y')[0] == 'y':
|
|
180
|
+
self._remove_table_files()
|
|
181
|
+
self._reset_cache()
|
|
182
|
+
elif len(self._cache.datasets) > 1e6:
|
|
183
|
+
warnings.warn(
|
|
184
|
+
'Large cache tables affect performance. '
|
|
185
|
+
'Consider removing them by calling the `_remove_table_files` method.')
|
|
186
|
+
|
|
165
187
|
return self._cache['_meta']['loaded_time']
|
|
166
188
|
|
|
167
189
|
def save_cache(self, save_dir=None, clobber=False):
|
|
@@ -1643,6 +1665,11 @@ class OneAlyx(One):
|
|
|
1643
1665
|
tag : str
|
|
1644
1666
|
An optional Alyx dataset tag for loading cache tables containing a subset of datasets.
|
|
1645
1667
|
|
|
1668
|
+
Returns
|
|
1669
|
+
-------
|
|
1670
|
+
datetime.datetime
|
|
1671
|
+
A timestamp of when the cache was loaded.
|
|
1672
|
+
|
|
1646
1673
|
Examples
|
|
1647
1674
|
--------
|
|
1648
1675
|
To load the cache tables for a given release tag
|
|
@@ -1666,6 +1693,8 @@ class OneAlyx(One):
|
|
|
1666
1693
|
different_tag = any(x != tag for x in current_tags)
|
|
1667
1694
|
if not (clobber or different_tag):
|
|
1668
1695
|
super(OneAlyx, self).load_cache(tables_dir) # Load any present cache
|
|
1696
|
+
cache_meta = self._cache.get('_meta', {})
|
|
1697
|
+
raw_meta = cache_meta.get('raw', {}).values() or [{}]
|
|
1669
1698
|
|
|
1670
1699
|
try:
|
|
1671
1700
|
# Determine whether a newer cache is available
|
|
@@ -1676,7 +1705,7 @@ class OneAlyx(One):
|
|
|
1676
1705
|
min_version = packaging.version.parse(cache_info.get('min_api_version', '0.0.0'))
|
|
1677
1706
|
if packaging.version.parse(one.__version__) < min_version:
|
|
1678
1707
|
warnings.warn(f'Newer cache tables require ONE version {min_version} or greater')
|
|
1679
|
-
return
|
|
1708
|
+
return cache_meta['loaded_time']
|
|
1680
1709
|
|
|
1681
1710
|
# Check whether remote cache more recent
|
|
1682
1711
|
remote_created = datetime.fromisoformat(cache_info['date_created'])
|
|
@@ -1684,7 +1713,7 @@ class OneAlyx(One):
|
|
|
1684
1713
|
fresh = local_created and (remote_created - local_created) < timedelta(minutes=1)
|
|
1685
1714
|
if fresh and not different_tag:
|
|
1686
1715
|
_logger.info('No newer cache available')
|
|
1687
|
-
return
|
|
1716
|
+
return cache_meta['loaded_time']
|
|
1688
1717
|
|
|
1689
1718
|
# Set the cache table directory location
|
|
1690
1719
|
if tables_dir: # If tables directory specified, use that
|
|
@@ -1708,7 +1737,7 @@ class OneAlyx(One):
|
|
|
1708
1737
|
_logger.info('Downloading remote caches...')
|
|
1709
1738
|
files = self.alyx.download_cache_tables(cache_info.get('location'), self._tables_dir)
|
|
1710
1739
|
assert any(files)
|
|
1711
|
-
super(OneAlyx, self).load_cache(self._tables_dir) # Reload cache after download
|
|
1740
|
+
return super(OneAlyx, self).load_cache(self._tables_dir) # Reload cache after download
|
|
1712
1741
|
except (requests.exceptions.HTTPError, wc.HTTPError, requests.exceptions.SSLError) as ex:
|
|
1713
1742
|
_logger.debug(ex)
|
|
1714
1743
|
_logger.error(f'{type(ex).__name__}: Failed to load the remote cache file')
|
|
@@ -1725,6 +1754,7 @@ class OneAlyx(One):
|
|
|
1725
1754
|
'Please provide valid tables_dir / cache_dir kwargs '
|
|
1726
1755
|
'or run ONE.setup to update the default directory.'
|
|
1727
1756
|
)
|
|
1757
|
+
return cache_meta['loaded_time']
|
|
1728
1758
|
|
|
1729
1759
|
@property
|
|
1730
1760
|
def alyx(self):
|
one/webclient.py
CHANGED
|
@@ -34,6 +34,7 @@ from uuid import UUID
|
|
|
34
34
|
import json
|
|
35
35
|
import logging
|
|
36
36
|
import math
|
|
37
|
+
import os
|
|
37
38
|
import re
|
|
38
39
|
import functools
|
|
39
40
|
import urllib.request
|
|
@@ -61,6 +62,8 @@ from iblutil.io.params import set_hidden
|
|
|
61
62
|
from iblutil.util import ensure_list
|
|
62
63
|
import concurrent.futures
|
|
63
64
|
_logger = logging.getLogger(__name__)
|
|
65
|
+
N_THREADS = int(os.environ.get('ONE_HTTP_DL_THREADS', 4))
|
|
66
|
+
"""int: The number of download threads."""
|
|
64
67
|
|
|
65
68
|
|
|
66
69
|
class _JSONEncoder(json.JSONEncoder):
|
|
@@ -355,7 +358,6 @@ def http_download_file_list(links_to_file_list, **kwargs):
|
|
|
355
358
|
|
|
356
359
|
"""
|
|
357
360
|
links_to_file_list = list(links_to_file_list) # In case generator was passed
|
|
358
|
-
n_threads = 4 # Max number of threads
|
|
359
361
|
outputs = []
|
|
360
362
|
target_dir = kwargs.pop('target_dir', None)
|
|
361
363
|
# Ensure target dir the length of url list
|
|
@@ -364,7 +366,7 @@ def http_download_file_list(links_to_file_list, **kwargs):
|
|
|
364
366
|
assert len(target_dir) == len(links_to_file_list)
|
|
365
367
|
# using with statement to ensure threads are cleaned up promptly
|
|
366
368
|
zipped = zip(links_to_file_list, target_dir)
|
|
367
|
-
with concurrent.futures.ThreadPoolExecutor(max_workers=
|
|
369
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=N_THREADS) as executor:
|
|
368
370
|
# Multithreading load operations
|
|
369
371
|
futures = [executor.submit(
|
|
370
372
|
http_download_file, link, target_dir=target, **kwargs) for link, target in zipped]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|