ONE-api 3.0b4__tar.gz → 3.0b5__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.
Files changed (44) hide show
  1. {one_api-3.0b4 → one_api-3.0b5/ONE_api.egg-info}/PKG-INFO +1 -1
  2. {one_api-3.0b4/ONE_api.egg-info → one_api-3.0b5}/PKG-INFO +1 -1
  3. {one_api-3.0b4 → one_api-3.0b5}/one/__init__.py +1 -1
  4. {one_api-3.0b4 → one_api-3.0b5}/one/api.py +36 -6
  5. {one_api-3.0b4 → one_api-3.0b5}/one/webclient.py +4 -2
  6. {one_api-3.0b4 → one_api-3.0b5}/LICENSE +0 -0
  7. {one_api-3.0b4 → one_api-3.0b5}/MANIFEST.in +0 -0
  8. {one_api-3.0b4 → one_api-3.0b5}/ONE_api.egg-info/SOURCES.txt +0 -0
  9. {one_api-3.0b4 → one_api-3.0b5}/ONE_api.egg-info/dependency_links.txt +0 -0
  10. {one_api-3.0b4 → one_api-3.0b5}/ONE_api.egg-info/requires.txt +0 -0
  11. {one_api-3.0b4 → one_api-3.0b5}/ONE_api.egg-info/top_level.txt +0 -0
  12. {one_api-3.0b4 → one_api-3.0b5}/README.md +0 -0
  13. {one_api-3.0b4 → one_api-3.0b5}/one/alf/__init__.py +0 -0
  14. {one_api-3.0b4 → one_api-3.0b5}/one/alf/cache.py +0 -0
  15. {one_api-3.0b4 → one_api-3.0b5}/one/alf/exceptions.py +0 -0
  16. {one_api-3.0b4 → one_api-3.0b5}/one/alf/io.py +0 -0
  17. {one_api-3.0b4 → one_api-3.0b5}/one/alf/path.py +0 -0
  18. {one_api-3.0b4 → one_api-3.0b5}/one/alf/spec.py +0 -0
  19. {one_api-3.0b4 → one_api-3.0b5}/one/converters.py +0 -0
  20. {one_api-3.0b4 → one_api-3.0b5}/one/params.py +0 -0
  21. {one_api-3.0b4 → one_api-3.0b5}/one/registration.py +0 -0
  22. {one_api-3.0b4 → one_api-3.0b5}/one/remote/__init__.py +0 -0
  23. {one_api-3.0b4 → one_api-3.0b5}/one/remote/aws.py +0 -0
  24. {one_api-3.0b4 → one_api-3.0b5}/one/remote/base.py +0 -0
  25. {one_api-3.0b4 → one_api-3.0b5}/one/remote/globus.py +0 -0
  26. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/datasets.pqt +0 -0
  27. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/params/.caches +0 -0
  28. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/params/.test.alyx.internationalbrainlab.org +0 -0
  29. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/rest_responses/1f187d80fd59677b395fcdb18e68e4401bfa1cc9 +0 -0
  30. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/rest_responses/3f51aa2e0baa42438467906f56a457c91a221898 +0 -0
  31. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/rest_responses/47893cf67c985e6361cdee009334963f49fb0746 +0 -0
  32. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/rest_responses/535d0e9a1e2c1efbdeba0d673b131e00361a2edb +0 -0
  33. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/rest_responses/5618bea3484a52cd893616f07903f0e49e023ba1 +0 -0
  34. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/rest_responses/6dc96f7e9bcc6ac2e7581489b9580a6cd3f28293 +0 -0
  35. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/rest_responses/db1731fb8df0208944ae85f76718430813a8bf50 +0 -0
  36. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/rest_responses/dcce48259bb929661f60a02a48563f70aa6185b3 +0 -0
  37. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/rest_responses/f530d6022f61cdc9e38cc66beb3cb71f3003c9a1 +0 -0
  38. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/sessions.pqt +0 -0
  39. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/test_dbs.json +0 -0
  40. {one_api-3.0b4 → one_api-3.0b5}/one/tests/fixtures/test_img.png +0 -0
  41. {one_api-3.0b4 → one_api-3.0b5}/one/util.py +0 -0
  42. {one_api-3.0b4 → one_api-3.0b5}/pyproject.toml +0 -0
  43. {one_api-3.0b4 → one_api-3.0b5}/requirements.txt +0 -0
  44. {one_api-3.0b4 → one_api-3.0b5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ONE-api
3
- Version: 3.0b4
3
+ Version: 3.0b5
4
4
  Summary: Open Neurophysiology Environment
5
5
  Author: IBL Staff
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ONE-api
3
- Version: 3.0b4
3
+ Version: 3.0b5
4
4
  Summary: Open Neurophysiology Environment
5
5
  Author: IBL Staff
6
6
  License: MIT
@@ -1,2 +1,2 @@
1
1
  """The Open Neurophysiology Environment (ONE) API."""
2
- __version__ = '3.0b4'
2
+ __version__ = '3.0b5'
@@ -39,8 +39,10 @@ from one import util
39
39
 
40
40
  _logger = logging.getLogger(__name__)
41
41
  __all__ = ['ONE', 'One', 'OneAlyx']
42
- N_THREADS = os.environ.get('ONE_HTTP_DL_THREADS', 4)
43
- """int: The number of download threads."""
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
- self.save_cache()
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):
@@ -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=n_threads) as executor:
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
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