lamindb_setup 1.18.2__py3-none-any.whl → 1.19.1__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.
Files changed (50) hide show
  1. lamindb_setup/__init__.py +4 -19
  2. lamindb_setup/_cache.py +87 -87
  3. lamindb_setup/_check.py +7 -7
  4. lamindb_setup/_check_setup.py +131 -131
  5. lamindb_setup/_connect_instance.py +443 -438
  6. lamindb_setup/_delete.py +155 -151
  7. lamindb_setup/_disconnect.py +38 -38
  8. lamindb_setup/_django.py +39 -39
  9. lamindb_setup/_entry_points.py +19 -19
  10. lamindb_setup/_init_instance.py +423 -429
  11. lamindb_setup/_migrate.py +331 -327
  12. lamindb_setup/_register_instance.py +32 -32
  13. lamindb_setup/_schema.py +27 -27
  14. lamindb_setup/_schema_metadata.py +451 -451
  15. lamindb_setup/_set_managed_storage.py +81 -80
  16. lamindb_setup/_setup_user.py +198 -198
  17. lamindb_setup/_silence_loggers.py +46 -46
  18. lamindb_setup/core/__init__.py +25 -34
  19. lamindb_setup/core/_aws_options.py +276 -266
  20. lamindb_setup/core/_aws_storage.py +57 -55
  21. lamindb_setup/core/_clone.py +50 -50
  22. lamindb_setup/core/_deprecated.py +62 -62
  23. lamindb_setup/core/_docs.py +14 -14
  24. lamindb_setup/core/_hub_client.py +288 -294
  25. lamindb_setup/core/_hub_core.py +0 -2
  26. lamindb_setup/core/_hub_crud.py +247 -247
  27. lamindb_setup/core/_hub_utils.py +100 -100
  28. lamindb_setup/core/_private_django_api.py +80 -80
  29. lamindb_setup/core/_settings.py +440 -434
  30. lamindb_setup/core/_settings_instance.py +32 -7
  31. lamindb_setup/core/_settings_load.py +162 -159
  32. lamindb_setup/core/_settings_save.py +108 -96
  33. lamindb_setup/core/_settings_storage.py +433 -433
  34. lamindb_setup/core/_settings_store.py +162 -92
  35. lamindb_setup/core/_settings_user.py +55 -55
  36. lamindb_setup/core/_setup_bionty_sources.py +44 -44
  37. lamindb_setup/core/cloud_sqlite_locker.py +240 -240
  38. lamindb_setup/core/django.py +414 -413
  39. lamindb_setup/core/exceptions.py +1 -1
  40. lamindb_setup/core/hashing.py +134 -134
  41. lamindb_setup/core/types.py +1 -1
  42. lamindb_setup/core/upath.py +1031 -1028
  43. lamindb_setup/errors.py +72 -70
  44. lamindb_setup/io.py +423 -416
  45. lamindb_setup/types.py +17 -17
  46. {lamindb_setup-1.18.2.dist-info → lamindb_setup-1.19.1.dist-info}/METADATA +4 -2
  47. lamindb_setup-1.19.1.dist-info/RECORD +51 -0
  48. {lamindb_setup-1.18.2.dist-info → lamindb_setup-1.19.1.dist-info}/WHEEL +1 -1
  49. {lamindb_setup-1.18.2.dist-info → lamindb_setup-1.19.1.dist-info/licenses}/LICENSE +201 -201
  50. lamindb_setup-1.18.2.dist-info/RECORD +0 -51
@@ -1,55 +1,57 @@
1
- from __future__ import annotations
2
-
3
- import httpx
4
- from lamin_utils import logger
5
-
6
-
7
- def get_location(ip="ipinfo.io"):
8
- response = httpx.get(f"http://{ip}/json").json()
9
- loc = response["loc"].split(",")
10
- return {"latitude": float(loc[0]), "longitude": float(loc[1])}
11
-
12
-
13
- def haversine(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
14
- import math
15
-
16
- R = 6371 # Radius of the Earth in kilometers
17
- dLat = math.radians(lat2 - lat1)
18
- dLon = math.radians(lon2 - lon1)
19
- a = math.sin(dLat / 2) * math.sin(dLat / 2) + math.cos(
20
- math.radians(lat1)
21
- ) * math.cos(math.radians(lat2)) * math.sin(dLon / 2) * math.sin(dLon / 2)
22
- c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
23
- distance = R * c
24
- return distance
25
-
26
-
27
- def find_closest_aws_region() -> str:
28
- aws_region_locations = {
29
- "us-east-1": {"latitude": 39.0, "longitude": -77.0}, # Northern Virginia
30
- "us-east-2": {"latitude": 40.0, "longitude": -83.0}, # Ohio
31
- "us-west-1": {"latitude": 37.77, "longitude": -122.41}, # Northern California
32
- "us-west-2": {"latitude": 45.52, "longitude": -122.68}, # Oregon
33
- "eu-central-1": {"latitude": 50.11, "longitude": 8.68}, # Frankfurt
34
- "eu-west-2": {"latitude": 51.51, "longitude": -0.13}, # London, UK
35
- }
36
- # sometimes get_location fails to obtain coordinates
37
- try:
38
- your_location = get_location()
39
- except Exception as e:
40
- logger.warning(f"failed to infer location, using us-east-1: {e}")
41
- return "us-east-1"
42
-
43
- closest_region = ""
44
- min_distance = float("inf")
45
- for region in aws_region_locations:
46
- region_location = aws_region_locations[region]
47
- distance = haversine(
48
- your_location["latitude"],
49
- your_location["longitude"],
50
- region_location["latitude"],
51
- region_location["longitude"],
52
- )
53
- if distance < min_distance:
54
- closest_region, min_distance = region, distance
55
- return closest_region
1
+ from __future__ import annotations
2
+
3
+ from lamin_utils import logger
4
+
5
+
6
+ def get_location(ip="ipinfo.io"):
7
+ # dynamic import to avoid importing the heavy httpx at root
8
+ import httpx
9
+
10
+ response = httpx.get(f"http://{ip}/json").json()
11
+ loc = response["loc"].split(",")
12
+ return {"latitude": float(loc[0]), "longitude": float(loc[1])}
13
+
14
+
15
+ def haversine(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
16
+ import math
17
+
18
+ R = 6371 # Radius of the Earth in kilometers
19
+ dLat = math.radians(lat2 - lat1)
20
+ dLon = math.radians(lon2 - lon1)
21
+ a = math.sin(dLat / 2) * math.sin(dLat / 2) + math.cos(
22
+ math.radians(lat1)
23
+ ) * math.cos(math.radians(lat2)) * math.sin(dLon / 2) * math.sin(dLon / 2)
24
+ c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
25
+ distance = R * c
26
+ return distance
27
+
28
+
29
+ def find_closest_aws_region() -> str:
30
+ aws_region_locations = {
31
+ "us-east-1": {"latitude": 39.0, "longitude": -77.0}, # Northern Virginia
32
+ "us-east-2": {"latitude": 40.0, "longitude": -83.0}, # Ohio
33
+ "us-west-1": {"latitude": 37.77, "longitude": -122.41}, # Northern California
34
+ "us-west-2": {"latitude": 45.52, "longitude": -122.68}, # Oregon
35
+ "eu-central-1": {"latitude": 50.11, "longitude": 8.68}, # Frankfurt
36
+ "eu-west-2": {"latitude": 51.51, "longitude": -0.13}, # London, UK
37
+ }
38
+ # sometimes get_location fails to obtain coordinates
39
+ try:
40
+ your_location = get_location()
41
+ except Exception as e:
42
+ logger.warning(f"failed to infer location, using us-east-1: {e}")
43
+ return "us-east-1"
44
+
45
+ closest_region = ""
46
+ min_distance = float("inf")
47
+ for region in aws_region_locations:
48
+ region_location = aws_region_locations[region]
49
+ distance = haversine(
50
+ your_location["latitude"],
51
+ your_location["longitude"],
52
+ region_location["latitude"],
53
+ region_location["longitude"],
54
+ )
55
+ if distance < min_distance:
56
+ closest_region, min_distance = region, distance
57
+ return closest_region
@@ -1,50 +1,50 @@
1
- """Utilities to work with Postgres Snapshots.
2
-
3
- .. autosummary::
4
- :toctree:
5
-
6
- upload_sqlite_clone
7
- """
8
-
9
- import gzip
10
- import shutil
11
- from pathlib import Path
12
-
13
- from lamindb_setup.core.upath import create_path
14
-
15
-
16
- def upload_sqlite_clone(
17
- local_sqlite_path: Path | str | None = None, compress: bool = True
18
- ) -> None:
19
- """Uploads the SQLite clone to the default storage.
20
-
21
- Args:
22
- local_sqlite_path: Path to the SQLite file.
23
- Defaults to the local storage path if not specified.
24
- compress: Whether to compress the database with gzip before uploading.
25
- """
26
- import lamindb_setup as ln_setup
27
-
28
- if local_sqlite_path is None:
29
- local_sqlite_path = ln_setup.settings.instance._sqlite_file_local
30
- else:
31
- local_sqlite_path = Path(local_sqlite_path)
32
-
33
- if not local_sqlite_path.exists():
34
- raise FileNotFoundError(f"Database not found at {local_sqlite_path}")
35
-
36
- cloud_db_path = ln_setup.settings.instance._sqlite_file
37
-
38
- if compress:
39
- temp_gz_path = local_sqlite_path.with_suffix(".db.gz")
40
- with (
41
- open(local_sqlite_path, "rb") as f_in,
42
- gzip.open(temp_gz_path, "wb") as f_out,
43
- ):
44
- shutil.copyfileobj(f_in, f_out)
45
- cloud_destination = create_path(f"{cloud_db_path}.gz")
46
- cloud_destination.upload_from(temp_gz_path, print_progress=True)
47
- temp_gz_path.unlink()
48
- else:
49
- cloud_destination = create_path(cloud_db_path)
50
- cloud_destination.upload_from(local_sqlite_path, print_progress=True)
1
+ """Utilities to work with Postgres Snapshots.
2
+
3
+ .. autosummary::
4
+ :toctree:
5
+
6
+ upload_sqlite_clone
7
+ """
8
+
9
+ import gzip
10
+ import shutil
11
+ from pathlib import Path
12
+
13
+ from lamindb_setup.core.upath import create_path
14
+
15
+
16
+ def upload_sqlite_clone(
17
+ local_sqlite_path: Path | str | None = None, compress: bool = True
18
+ ) -> None:
19
+ """Uploads the SQLite clone to the default storage.
20
+
21
+ Args:
22
+ local_sqlite_path: Path to the SQLite file.
23
+ Defaults to the local storage path if not specified.
24
+ compress: Whether to compress the database with gzip before uploading.
25
+ """
26
+ import lamindb_setup as ln_setup
27
+
28
+ if local_sqlite_path is None:
29
+ local_sqlite_path = ln_setup.settings.instance._sqlite_file_local
30
+ else:
31
+ local_sqlite_path = Path(local_sqlite_path)
32
+
33
+ if not local_sqlite_path.exists():
34
+ raise FileNotFoundError(f"Database not found at {local_sqlite_path}")
35
+
36
+ cloud_db_path = ln_setup.settings.instance._sqlite_file
37
+
38
+ if compress:
39
+ temp_gz_path = local_sqlite_path.with_suffix(".db.gz")
40
+ with (
41
+ open(local_sqlite_path, "rb") as f_in,
42
+ gzip.open(temp_gz_path, "wb") as f_out,
43
+ ):
44
+ shutil.copyfileobj(f_in, f_out)
45
+ cloud_destination = create_path(f"{cloud_db_path}.gz")
46
+ cloud_destination.upload_from(temp_gz_path, print_progress=True)
47
+ temp_gz_path.unlink()
48
+ else:
49
+ cloud_destination = create_path(cloud_db_path)
50
+ cloud_destination.upload_from(local_sqlite_path, print_progress=True)
@@ -1,62 +1,62 @@
1
- from __future__ import annotations
2
-
3
- # BSD 3-Clause License
4
- # Copyright (c) 2017-2018 P. Angerer, F. Alexander Wolf, Theis Lab
5
- # All rights reserved.
6
- # Redistribution and use in source and binary forms, with or without
7
- # modification, are permitted provided that the following conditions are met:
8
- # * Redistributions of source code must retain the above copyright notice, this
9
- # list of conditions and the following disclaimer.
10
- # * Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- # * Neither the name of the copyright holder nor the names of its
14
- # contributors may be used to endorse or promote products derived from
15
- # this software without specific prior written permission.
16
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
- # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
- import warnings
27
- from functools import wraps
28
-
29
-
30
- def deprecated(new_name: str):
31
- """Deprecated.
32
-
33
- This is a decorator which can be used to mark functions, methods and properties
34
- as deprecated. It will result in a warning being emitted
35
- when the function is used.
36
-
37
- It will also hide the function from the docs.
38
-
39
- Example::
40
-
41
- @property
42
- @deprecated("n_files")
43
- def n_objects(self) -> int:
44
- return self.n_files
45
-
46
- """
47
-
48
- def decorator(func):
49
- @wraps(func)
50
- def new_func(*args, **kwargs):
51
- warnings.warn(
52
- f"Use {new_name} instead of {func.__name__}, "
53
- f"{func.__name__} will be removed in the future.",
54
- category=DeprecationWarning,
55
- stacklevel=2,
56
- )
57
- return func(*args, **kwargs)
58
-
59
- setattr(new_func, "__deprecated", True)
60
- return new_func
61
-
62
- return decorator
1
+ from __future__ import annotations
2
+
3
+ # BSD 3-Clause License
4
+ # Copyright (c) 2017-2018 P. Angerer, F. Alexander Wolf, Theis Lab
5
+ # All rights reserved.
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ # * Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of the copyright holder nor the names of its
14
+ # contributors may be used to endorse or promote products derived from
15
+ # this software without specific prior written permission.
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ import warnings
27
+ from functools import wraps
28
+
29
+
30
+ def deprecated(new_name: str):
31
+ """Deprecated.
32
+
33
+ This is a decorator which can be used to mark functions, methods and properties
34
+ as deprecated. It will result in a warning being emitted
35
+ when the function is used.
36
+
37
+ It will also hide the function from the docs.
38
+
39
+ Example::
40
+
41
+ @property
42
+ @deprecated("n_files")
43
+ def n_objects(self) -> int:
44
+ return self.n_files
45
+
46
+ """
47
+
48
+ def decorator(func):
49
+ @wraps(func)
50
+ def new_func(*args, **kwargs):
51
+ warnings.warn(
52
+ f"Use {new_name} instead of {func.__name__}, "
53
+ f"{func.__name__} will be removed in the future.",
54
+ category=DeprecationWarning,
55
+ stacklevel=2,
56
+ )
57
+ return func(*args, **kwargs)
58
+
59
+ setattr(new_func, "__deprecated", True)
60
+ return new_func
61
+
62
+ return decorator
@@ -1,14 +1,14 @@
1
- from __future__ import annotations
2
-
3
- from textwrap import dedent
4
-
5
-
6
- def doc_args(*args):
7
- """Pass arguments to docstrings."""
8
-
9
- def dec(obj):
10
- obj.__orig_doc__ = obj.__doc__
11
- obj.__doc__ = dedent(obj.__doc__).format(*args)
12
- return obj
13
-
14
- return dec
1
+ from __future__ import annotations
2
+
3
+ from textwrap import dedent
4
+
5
+
6
+ def doc_args(*args):
7
+ """Pass arguments to docstrings."""
8
+
9
+ def dec(obj):
10
+ obj.__orig_doc__ = obj.__doc__
11
+ obj.__doc__ = dedent(obj.__doc__).format(*args)
12
+ return obj
13
+
14
+ return dec