lamindb_setup 1.0a1__py3-none-any.whl → 1.0.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.
lamindb_setup/__init__.py CHANGED
@@ -33,10 +33,9 @@ Modules & settings:
33
33
 
34
34
  """
35
35
 
36
- __version__ = "1.0a1" # denote a release candidate for 0.1.0 with 0.1rc1
36
+ __version__ = "1.0.1" # denote a release candidate for 0.1.0 with 0.1rc1
37
37
 
38
- import os as _os
39
- import sys as _sys
38
+ import os
40
39
 
41
40
  from . import core
42
41
  from ._check_setup import _check_instance_setup
@@ -76,27 +75,11 @@ def _is_CI_environment() -> bool:
76
75
  "SEMAPHORE", # Semaphore CI
77
76
  "BUILD_ID", # Generic build environments
78
77
  ]
79
- return any(env_var in _os.environ for env_var in ci_env_vars)
78
+ return any(env_var in os.environ for env_var in ci_env_vars)
80
79
 
81
80
 
82
81
  _TESTING = _is_CI_environment()
83
82
 
84
-
85
- # hide the supabase error in a thread on windows
86
- if _os.name == "nt":
87
- if _sys.version_info.minor > 7:
88
- import threading
89
-
90
- _original_excepthook = threading.excepthook
91
-
92
- def _except_hook(args):
93
- is_overflow = args.exc_type is OverflowError
94
- for_timeout = str(args.exc_value) == "timeout value is too large"
95
- if not (is_overflow and for_timeout):
96
- _original_excepthook(args)
97
-
98
- threading.excepthook = _except_hook
99
-
100
83
  # provide a way for other packages to run custom code on import
101
84
  _call_registered_entry_points("lamindb_setup.on_import")
102
85
 
lamindb_setup/_cache.py CHANGED
@@ -10,11 +10,15 @@ from .core._settings_save import save_system_storage_settings
10
10
  def clear_cache_dir():
11
11
  from lamindb_setup import close, settings
12
12
 
13
- if settings.instance._is_cloud_sqlite:
14
- logger.warning(
15
- "Closing the current instance to update the cloud sqlite database."
16
- )
17
- close()
13
+ try:
14
+ if settings.instance._is_cloud_sqlite:
15
+ logger.warning(
16
+ "Closing the current instance to update the cloud sqlite database."
17
+ )
18
+ close()
19
+ except SystemExit as e:
20
+ if str(e) != "No instance is loaded! Call `lamin init` or `lamin connect`":
21
+ raise e
18
22
 
19
23
  cache_dir = settings.cache_dir
20
24
  shutil.rmtree(cache_dir)
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import functools
3
4
  import importlib as il
4
5
  import os
5
6
  from typing import TYPE_CHECKING
@@ -13,6 +14,8 @@ from .core._settings_store import current_instance_settings_file
13
14
  from .core.exceptions import DefaultMessageException
14
15
 
15
16
  if TYPE_CHECKING:
17
+ from collections.abc import Callable
18
+
16
19
  from .core._settings_instance import InstanceSettings
17
20
 
18
21
 
@@ -30,6 +33,20 @@ CURRENT_ISETTINGS: InstanceSettings | None = None
30
33
  IS_LOADING: bool = False
31
34
 
32
35
 
36
+ # decorator to disable auto-connect when importing a module such as lamindb
37
+ def _loading(func: Callable):
38
+ @functools.wraps(func)
39
+ def wrapper(*args, **kwargs):
40
+ global IS_LOADING
41
+ IS_LOADING = True
42
+ try:
43
+ return func(*args, **kwargs)
44
+ finally:
45
+ IS_LOADING = False
46
+
47
+ return wrapper
48
+
49
+
33
50
  def _get_current_instance_settings() -> InstanceSettings | None:
34
51
  global CURRENT_ISETTINGS
35
52
 
lamindb_setup/_close.py CHANGED
@@ -24,7 +24,7 @@ def close(mute: bool = False) -> None:
24
24
  logger.warning("did not upload cache file - not enough permissions")
25
25
  else:
26
26
  raise e
27
- if "bionty" in settings.instance.schema:
27
+ if "bionty" in settings.instance.modules:
28
28
  delete_bionty_sources_yaml()
29
29
  current_instance_settings_file().unlink()
30
30
  clear_locker()
@@ -7,7 +7,7 @@ from uuid import UUID
7
7
 
8
8
  from lamin_utils import logger
9
9
 
10
- from ._check_setup import _check_instance_setup
10
+ from ._check_setup import _check_instance_setup, _get_current_instance_settings
11
11
  from ._close import close as close_instance
12
12
  from ._init_instance import (
13
13
  MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE,
@@ -160,7 +160,7 @@ def _connect_instance(
160
160
  name=name,
161
161
  storage=ssettings,
162
162
  db=db_updated,
163
- schema=instance_result["schema_str"],
163
+ modules=instance_result["schema_str"],
164
164
  git_repo=instance_result["git_repo"],
165
165
  keep_artifacts_local=bool(instance_result["keep_artifacts_local"]),
166
166
  is_on_hub=True,
@@ -186,12 +186,12 @@ def _connect_instance(
186
186
 
187
187
 
188
188
  @unlock_cloud_sqlite_upon_exception(ignore_prev_locker=True)
189
- def connect(slug: str, **kwargs) -> str | tuple | None:
190
- """Connect to instance.
189
+ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
190
+ """Connect to an instance.
191
191
 
192
192
  Args:
193
- slug: The instance slug `account_handle/instance_name` or URL.
194
- If the instance is owned by you, it suffices to pass the instance name.
193
+ instance: `None` or an instance identifier (URL, slug `account/name`, or `name` if the instance is local or in your account).
194
+ If `None`, it will connect to the instance that was connected via the CLI.
195
195
  """
196
196
  # validate kwargs
197
197
  valid_kwargs = {
@@ -220,39 +220,46 @@ def connect(slug: str, **kwargs) -> str | tuple | None:
220
220
  access_token = _user.access_token
221
221
 
222
222
  try:
223
- owner, name = get_owner_name_from_identifier(slug)
224
-
225
- if _check_instance_setup() and not _test:
226
- if (
227
- settings._instance_exists
228
- and f"{owner}/{name}" == settings.instance.slug
223
+ if instance is None:
224
+ isettings_or_none = _get_current_instance_settings()
225
+ if isettings_or_none is None:
226
+ raise SystemExit(
227
+ "No instance was connected through the CLI, pass a value to `instance` or connect via the CLI."
228
+ )
229
+ isettings = isettings_or_none
230
+ else:
231
+ owner, name = get_owner_name_from_identifier(instance)
232
+ if _check_instance_setup() and not _test:
233
+ if (
234
+ settings._instance_exists
235
+ and f"{owner}/{name}" == settings.instance.slug
236
+ ):
237
+ logger.important(f"connected lamindb: {settings.instance.slug}")
238
+ return None
239
+ else:
240
+ raise CannotSwitchDefaultInstance(
241
+ MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE
242
+ )
243
+ elif (
244
+ _write_settings
245
+ and settings._instance_exists
246
+ and f"{owner}/{name}" != settings.instance.slug
229
247
  ):
230
- logger.info(f"connected lamindb: {settings.instance.slug}")
231
- return None
232
- else:
233
- raise CannotSwitchDefaultInstance(
234
- MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE
248
+ close_instance(mute=True)
249
+
250
+ try:
251
+ isettings = _connect_instance(
252
+ owner, name, db=_db, access_token=access_token
235
253
  )
236
- elif (
237
- _write_settings
238
- and settings._instance_exists
239
- and f"{owner}/{name}" != settings.instance.slug
240
- ):
241
- close_instance(mute=True)
242
-
243
- try:
244
- isettings = _connect_instance(
245
- owner, name, db=_db, access_token=access_token
246
- )
247
- except InstanceNotFoundError as e:
248
- if _raise_not_found_error:
249
- raise e
250
- else:
251
- return "instance-not-found"
252
- if isinstance(isettings, str):
253
- return isettings
254
+ except InstanceNotFoundError as e:
255
+ if _raise_not_found_error:
256
+ raise e
257
+ else:
258
+ return "instance-not-found"
259
+ if isinstance(isettings, str):
260
+ return isettings
254
261
  # at this point we have checked already that isettings is not a string
255
- # _user is passed to lock cloud sqite for this user in isettings._load_db()
262
+ # _user is passed to lock cloud sqlite for this user in isettings._load_db()
256
263
  # has no effect if _user is None or if not cloud sqlite instance
257
264
  isettings._locker_user = _user
258
265
  isettings._persist(write_to_disk=_write_settings)
@@ -304,6 +311,7 @@ def connect(slug: str, **kwargs) -> str | tuple | None:
304
311
  load_from_isettings(isettings, user=_user, write_settings=_write_settings)
305
312
  if _reload_lamindb:
306
313
  importlib.reload(importlib.import_module("lamindb"))
314
+ logger.important(f"connected lamindb: {isettings.slug}")
307
315
  except Exception as e:
308
316
  if isettings is not None:
309
317
  if _write_settings:
@@ -381,7 +389,7 @@ def migrate_lnschema_core(
381
389
  else:
382
390
  try:
383
391
  response = input(
384
- f"Do you want to migrate to lamindb 0.78 (integrate lnschema_core into lamindb)? (y/n) -- Will rename {tables_to_rename}"
392
+ f"Do you want to migrate to lamindb 1.0 (integrate lnschema_core into lamindb)? (y/n) -- Will rename {tables_to_rename}"
385
393
  )
386
394
  if response != "y":
387
395
  print("Aborted.")
@@ -5,10 +5,7 @@ from importlib.metadata import entry_points
5
5
 
6
6
  def call_registered_entry_points(group, **kwargs):
7
7
  """load and call entry points registered under group."""
8
- if sys.version_info >= (3, 10):
9
- eps = entry_points(group=group)
10
- else:
11
- eps = entry_points().get(group, [])
8
+ eps = entry_points(group=group)
12
9
 
13
10
  for ep in eps:
14
11
  func = ep.load()
@@ -12,7 +12,7 @@ MODELS = {
12
12
  "User": False,
13
13
  "Storage": False,
14
14
  "Feature": False,
15
- "FeatureSet": False,
15
+ "Schema": False,
16
16
  "ULabel": False,
17
17
  },
18
18
  # "bionty": {
@@ -57,9 +57,9 @@ def exportdb() -> None:
57
57
 
58
58
  # export data to parquet files
59
59
  print(f"\nexporting data to parquet files in: {directory}\n")
60
- for schema_name, models in MODELS.items():
60
+ for module_name, models in MODELS.items():
61
61
  for model_name in models.keys():
62
- schema_module = import_module(f"lnschema_{schema_name}")
62
+ schema_module = import_module(f"lnschema_{module_name}")
63
63
  registry = getattr(schema_module, model_name)
64
64
  export_registry(registry, directory)
65
65
  many_to_many_names = [field.name for field in registry._meta.many_to_many]
@@ -36,10 +36,10 @@ def importdb() -> None:
36
36
  with engine.begin() as connection:
37
37
  if ln_setup.settings.instance.dialect == "postgresql":
38
38
  connection.execute(text("SET CONSTRAINTS ALL DEFERRED;"))
39
- for schema_name, models in MODELS.items():
39
+ for module_name, models in MODELS.items():
40
40
  for model_name in models.keys():
41
41
  print(model_name)
42
- schema_module = import_module(f"lnschema_{schema_name}")
42
+ schema_module = import_module(f"lnschema_{module_name}")
43
43
  registry = getattr(schema_module, model_name)
44
44
  import_registry(registry, directory, connection)
45
45
  many_to_many_names = [
@@ -25,17 +25,17 @@ if TYPE_CHECKING:
25
25
  from .core.types import UPathStr
26
26
 
27
27
 
28
- def get_schema_module_name(schema_name, raise_import_error: bool = True) -> str | None:
28
+ def get_schema_module_name(module_name, raise_import_error: bool = True) -> str | None:
29
29
  import importlib.util
30
30
 
31
- if schema_name == "core":
31
+ if module_name == "core":
32
32
  return "lamindb"
33
- name_attempts = [f"lnschema_{schema_name.replace('-', '_')}", schema_name]
33
+ name_attempts = [f"lnschema_{module_name.replace('-', '_')}", module_name]
34
34
  for name in name_attempts:
35
35
  module_spec = importlib.util.find_spec(name)
36
36
  if module_spec is not None:
37
37
  return name
38
- message = f"Schema module '{schema_name}' is not installed → no access to its labels & registries (resolve via `pip install {schema_name}`)"
38
+ message = f"schema module '{module_name}' is not installed → no access to its labels & registries (resolve via `pip install {module_name}`)"
39
39
  if raise_import_error:
40
40
  raise ImportError(message)
41
41
  logger.warning(message.lower())
@@ -129,12 +129,21 @@ def process_connect_response(
129
129
  return instance_id, instance_state
130
130
 
131
131
 
132
+ def process_modules_arg(modules: str | None = None) -> str:
133
+ if modules is None or modules == "":
134
+ return ""
135
+ # currently no actual validation, can add back if we see a need
136
+ # the following just strips white spaces
137
+ to_be_validated = [s.strip() for s in modules.split(",")]
138
+ return ",".join(to_be_validated)
139
+
140
+
132
141
  def validate_init_args(
133
142
  *,
134
143
  storage: UPathStr,
135
144
  name: str | None = None,
136
145
  db: PostgresDsn | None = None,
137
- schema: str | None = None,
146
+ modules: str | None = None,
138
147
  _test: bool = False,
139
148
  _write_settings: bool = True,
140
149
  _user: UserSettings | None = None,
@@ -150,9 +159,6 @@ def validate_init_args(
150
159
  str,
151
160
  ]:
152
161
  from ._connect_instance import connect
153
- from .core._hub_utils import (
154
- validate_schema_arg,
155
- )
156
162
 
157
163
  if storage is None:
158
164
  raise SystemExit("✗ `storage` argument can't be `None`")
@@ -178,7 +184,7 @@ def validate_init_args(
178
184
  instance_id = None
179
185
  if response is not None:
180
186
  instance_id, instance_state = process_connect_response(response, instance_slug)
181
- schema = validate_schema_arg(schema)
187
+ modules = process_modules_arg(modules)
182
188
  return name_str, instance_id, instance_state, instance_slug
183
189
 
184
190
 
@@ -202,22 +208,23 @@ def init(
202
208
  storage: UPathStr,
203
209
  name: str | None = None,
204
210
  db: PostgresDsn | None = None,
205
- schema: str | None = None,
211
+ modules: str | None = None,
206
212
  **kwargs,
207
213
  ) -> None:
208
214
  """Create and load a LaminDB instance.
209
215
 
210
216
  Args:
211
- storage: Either ``"create-s3"``, local or
212
- remote folder (``"s3://..."`` or ``"gs://..."``).
217
+ storage: Either local or remote folder (`"s3://..."` or `"gs://..."`).
213
218
  name: Instance name.
214
219
  db: Database connection url, do not pass for SQLite.
215
- schema: Comma-separated string of schema modules. None if not set.
220
+ modules: Comma-separated string of modules. None if the lamindb registries are enough.
216
221
  """
217
222
  isettings = None
218
223
  ssettings = None
219
224
 
220
225
  _write_settings: bool = kwargs.get("_write_settings", True)
226
+ if modules is None:
227
+ modules = kwargs.get("schema", None)
221
228
  _test: bool = kwargs.get("_test", False)
222
229
 
223
230
  # use this user instead of settings.user
@@ -241,7 +248,7 @@ def init(
241
248
  storage=storage,
242
249
  name=name,
243
250
  db=db,
244
- schema=schema,
251
+ modules=modules,
245
252
  _test=_test,
246
253
  _write_settings=_write_settings,
247
254
  _user=_user, # will get from settings.user if _user is None
@@ -268,7 +275,7 @@ def init(
268
275
  name=name_str,
269
276
  storage=ssettings,
270
277
  db=db,
271
- schema=schema,
278
+ modules=modules,
272
279
  uid=ssettings.uid,
273
280
  # to lock passed user in isettings._cloud_sqlite_locker.lock()
274
281
  _locker_user=_user, # only has effect if cloud sqlite
lamindb_setup/_migrate.py CHANGED
@@ -5,7 +5,7 @@ from django.db.migrations.loader import MigrationLoader
5
5
  from lamin_utils import logger
6
6
  from packaging import version
7
7
 
8
- from . import _check_setup
8
+ from ._check_setup import _check_instance_setup, _loading
9
9
  from .core._settings import settings
10
10
  from .core.django import setup_django
11
11
 
@@ -23,9 +23,9 @@ def check_whether_migrations_in_sync(db_version_str: str):
23
23
  return None
24
24
  installed_version = version.parse(installed_version_str)
25
25
  db_version = version.parse(db_version_str)
26
- if (
27
- installed_version.major < db_version.major
28
- or installed_version.minor < db_version.minor
26
+ if installed_version.major < db_version.major or (
27
+ installed_version.major == db_version.major
28
+ and installed_version.minor < db_version.minor
29
29
  ):
30
30
  db_version_lower = f"{db_version.major}.{db_version.minor}"
31
31
  db_version_upper = f"{db_version.major}.{db_version.minor + 1}"
@@ -37,9 +37,9 @@ def check_whether_migrations_in_sync(db_version_str: str):
37
37
  "please update lamindb: pip install"
38
38
  f' "lamindb>={db_version_lower},<{db_version_upper}"'
39
39
  )
40
- elif (
41
- installed_version.major > db_version.major
42
- or installed_version.minor > db_version.minor
40
+ elif installed_version.major > db_version.major or (
41
+ installed_version.major == db_version.major
42
+ and installed_version.minor > db_version.minor
43
43
  ):
44
44
  logger.warning(
45
45
  f"the database ({db_version_str}) is behind your installed lamindb package"
@@ -62,20 +62,20 @@ class migrate:
62
62
  """
63
63
 
64
64
  @classmethod
65
+ @_loading
65
66
  def create(cls) -> None:
66
67
  """Create a migration."""
67
- if _check_setup._check_instance_setup():
68
+ if _check_instance_setup():
68
69
  raise RuntimeError("Restart Python session to create migration or use CLI!")
69
- _check_setup.IS_LOADING = True
70
70
  setup_django(settings.instance, create_migrations=True)
71
- _check_setup.IS_LOADING = False
72
71
 
73
72
  @classmethod
73
+ @_loading
74
74
  def deploy(cls) -> None:
75
75
  """Deploy a migration."""
76
76
  from ._schema_metadata import update_schema_in_hub
77
77
 
78
- if _check_setup._check_instance_setup():
78
+ if _check_instance_setup():
79
79
  raise RuntimeError("Restart Python session to migrate or use CLI!")
80
80
  from lamindb_setup.core._hub_client import call_with_fallback_auth
81
81
  from lamindb_setup.core._hub_crud import (
@@ -115,6 +115,7 @@ class migrate:
115
115
  )
116
116
 
117
117
  @classmethod
118
+ @_loading
118
119
  def check(cls) -> bool:
119
120
  """Check whether Registry definitions are in sync with migrations."""
120
121
  from django.core.management import call_command
@@ -131,6 +132,7 @@ class migrate:
131
132
  return True
132
133
 
133
134
  @classmethod
135
+ @_loading
134
136
  def squash(
135
137
  cls, package_name, migration_nr, start_migration_nr: str | None = None
136
138
  ) -> None:
@@ -146,6 +148,7 @@ class migrate:
146
148
  call_command("squashmigrations", package_name, migration_nr)
147
149
 
148
150
  @classmethod
151
+ @_loading
149
152
  def show(cls) -> None:
150
153
  """Show migrations."""
151
154
  from django.core.management import call_command
@@ -238,15 +238,15 @@ class _ModelHandler:
238
238
  model_name = field.model._meta.model_name
239
239
  relation_type = self._get_relation_type(model, field)
240
240
  if field.related_model is None:
241
- schema_name = field.model.__get_schema_name__()
241
+ schema_name = field.model.__get_module_name__()
242
242
  related_model_name = None
243
243
  related_schema_name = None
244
244
  related_field_name = None
245
245
  field_name = field.name
246
246
  else:
247
247
  related_model_name = field.related_model._meta.model_name
248
- related_schema_name = field.related_model.__get_schema_name__()
249
- schema_name = field.model.__get_schema_name__()
248
+ related_schema_name = field.related_model.__get_module_name__()
249
+ schema_name = field.model.__get_module_name__()
250
250
  related_field_name = field.remote_field.name
251
251
  field_name = field.name
252
252
 
@@ -362,7 +362,7 @@ class _ModelHandler:
362
362
 
363
363
  class _SchemaHandler:
364
364
  def __init__(self) -> None:
365
- self.included_modules = ["core"] + list(settings.instance.schema)
365
+ self.included_modules = ["core"] + list(settings.instance.modules)
366
366
  self.modules = self._get_modules_metadata()
367
367
 
368
368
  def to_dict(self, include_django_objects: bool = True):
@@ -391,7 +391,7 @@ class _SchemaHandler:
391
391
  if model.__class__ is Registry
392
392
  and model is not Record
393
393
  and not model._meta.abstract
394
- and model.__get_schema_name__() == module_name
394
+ and model.__get_module_name__() == module_name
395
395
  }
396
396
  for module_name in self.included_modules
397
397
  }
@@ -30,23 +30,30 @@ from functools import wraps
30
30
  def deprecated(new_name: str):
31
31
  """Deprecated.
32
32
 
33
- This is a decorator which can be used to mark functions
33
+ This is a decorator which can be used to mark functions, methods and properties
34
34
  as deprecated. It will result in a warning being emitted
35
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
+
36
46
  """
37
47
 
38
48
  def decorator(func):
39
49
  @wraps(func)
40
50
  def new_func(*args, **kwargs):
41
- # turn off filter
42
- warnings.simplefilter("always", DeprecationWarning)
43
51
  warnings.warn(
44
52
  f"Use {new_name} instead of {func.__name__}, "
45
53
  f"{func.__name__} will be removed in the future.",
46
- category=DeprecationWarning,
54
+ category=FutureWarning,
47
55
  stacklevel=2,
48
56
  )
49
- warnings.simplefilter("default", DeprecationWarning) # reset filter
50
57
  return func(*args, **kwargs)
51
58
 
52
59
  setattr(new_func, "__deprecated", True)
@@ -7,15 +7,6 @@ from pydantic import BaseModel, Field, GetCoreSchemaHandler
7
7
  from pydantic_core import CoreSchema, core_schema
8
8
 
9
9
 
10
- def validate_schema_arg(schema: str | None = None) -> str:
11
- if schema is None or schema == "":
12
- return ""
13
- # currently no actual validation, can add back if we see a need
14
- # the following just strips white spaces
15
- to_be_validated = [s.strip() for s in schema.split(",")]
16
- return ",".join(to_be_validated)
17
-
18
-
19
10
  def validate_db_arg(db: str | None) -> None:
20
11
  if db is not None:
21
12
  LaminDsnModel(db=db)
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING, Literal
8
8
  from django.db.utils import ProgrammingError
9
9
  from lamin_utils import logger
10
10
 
11
+ from ._deprecated import deprecated
11
12
  from ._hub_client import call_with_fallback
12
13
  from ._hub_crud import select_account_handle_name_by_lnid
13
14
  from ._hub_utils import LaminDsn, LaminDsnModel
@@ -53,7 +54,7 @@ class InstanceSettings:
53
54
  keep_artifacts_local: bool = False, # default to local storage
54
55
  uid: str | None = None, # instance uid/lnid
55
56
  db: str | None = None, # DB URI
56
- schema: str | None = None, # comma-separated string of schema names
57
+ modules: str | None = None, # comma-separated string of module names
57
58
  git_repo: str | None = None, # a git repo URL
58
59
  is_on_hub: bool | None = None, # initialized from hub
59
60
  api_url: str | None = None,
@@ -69,7 +70,7 @@ class InstanceSettings:
69
70
  self._storage: StorageSettings = storage
70
71
  validate_db_arg(db)
71
72
  self._db: str | None = db
72
- self._schema_str: str | None = schema
73
+ self._schema_str: str | None = modules
73
74
  self._git_repo = None if git_repo is None else sanitize_git_repo_url(git_repo)
74
75
  # local storage
75
76
  self._keep_artifacts_local = keep_artifacts_local
@@ -84,7 +85,7 @@ class InstanceSettings:
84
85
  def __repr__(self):
85
86
  """Rich string representation."""
86
87
  representation = f"Current instance: {self.slug}"
87
- attrs = ["owner", "name", "storage", "db", "schema", "git_repo"]
88
+ attrs = ["owner", "name", "storage", "db", "modules", "git_repo"]
88
89
  for attr in attrs:
89
90
  value = getattr(self, attr)
90
91
  if attr == "storage":
@@ -271,12 +272,20 @@ class InstanceSettings:
271
272
  return hash_and_encode_as_b62(self._id.hex)[:12]
272
273
 
273
274
  @property
274
- def schema(self) -> set[str]:
275
- """Schema modules in addition to core schema."""
275
+ def modules(self) -> set[str]:
276
+ """The set of modules that defines the database schema.
277
+
278
+ The core schema contained in lamindb is not included in this set.
279
+ """
276
280
  if self._schema_str is None:
277
281
  return {} # type: ignore
278
282
  else:
279
- return {schema for schema in self._schema_str.split(",") if schema != ""}
283
+ return {module for module in self._schema_str.split(",") if module != ""}
284
+
285
+ @property
286
+ @deprecated("modules")
287
+ def schema(self) -> set[str]:
288
+ return self.modules
280
289
 
281
290
  @property
282
291
  def _sqlite_file(self) -> UPath:
@@ -98,7 +98,7 @@ def setup_instance_from_store(store: InstanceSettingsStore) -> InstanceSettings:
98
98
  name=store.name,
99
99
  storage=ssettings,
100
100
  db=_null_to_value(store.db),
101
- schema=_null_to_value(store.schema_str),
101
+ modules=_null_to_value(store.schema_str),
102
102
  git_repo=_null_to_value(store.git_repo),
103
103
  keep_artifacts_local=store.keep_artifacts_local, # type: ignore
104
104
  )
@@ -17,7 +17,7 @@ RENAME = {"name": "source", "description": "source_name"}
17
17
 
18
18
  def write_bionty_sources(isettings: InstanceSettings) -> None:
19
19
  """Write bionty sources to Source table."""
20
- if "bionty" not in isettings.schema:
20
+ if "bionty" not in isettings.modules:
21
21
  return None
22
22
  import shutil
23
23
 
@@ -79,7 +79,7 @@ def load_bionty_sources(isettings: InstanceSettings | None = None):
79
79
  # not setting up bionty sources
80
80
  return None
81
81
  if isettings is not None:
82
- if "bionty" not in isettings.schema:
82
+ if "bionty" not in isettings.modules:
83
83
  # no need to setup anything
84
84
  return None
85
85
 
@@ -96,7 +96,7 @@ def load_bionty_sources(isettings: InstanceSettings | None = None):
96
96
  for kwargs in active_records:
97
97
  for db_field, base_col in RENAME.items():
98
98
  kwargs[base_col] = kwargs.pop(db_field)
99
- # TODO: non-bionty schema?
99
+ # TODO: non-bionty modules?
100
100
  kwargs["entity"] = kwargs["entity"].replace("bionty.", "")
101
101
  write_yaml(
102
102
  parse_currently_used_sources(active_records),
@@ -52,14 +52,15 @@ def setup_django(
52
52
  }
53
53
  from .._init_instance import get_schema_module_name
54
54
 
55
- schema_names = ["core"] + list(isettings.schema)
55
+ module_names = ["core"] + list(isettings.modules)
56
56
  raise_import_error = True if init else False
57
- installed_apps = [
57
+ installed_apps = ["django.contrib.contenttypes"]
58
+ installed_apps += [
58
59
  package_name
59
- for n in schema_names
60
+ for name in module_names
60
61
  if (
61
62
  package_name := get_schema_module_name(
62
- n, raise_import_error=raise_import_error
63
+ name, raise_import_error=raise_import_error
63
64
  )
64
65
  )
65
66
  is not None
@@ -119,7 +119,7 @@ def hash_dir(path: Path):
119
119
  hashes_sizes = pool.map(hash_size, files)
120
120
  else:
121
121
  hashes_sizes = map(hash_size, files)
122
- hashes, sizes = zip(*hashes_sizes)
122
+ hashes, sizes = zip(*hashes_sizes, strict=False)
123
123
 
124
124
  hash, hash_type = hash_from_hashes_list(hashes), "md5-d"
125
125
  n_files = len(hashes)
@@ -549,7 +549,7 @@ def compute_file_tree(
549
549
  pointers = [tee] * (len(contents) - 1) + [last]
550
550
  n_files_per_dir_and_type = defaultdict(lambda: 0) # type: ignore
551
551
  # TODO: pass strict=False to zip with python > 3.9
552
- for pointer, child_path in zip(pointers, contents): # type: ignore
552
+ for pointer, child_path in zip(pointers, contents, strict=False): # type: ignore
553
553
  if child_path.is_dir():
554
554
  if include_dirs and child_path not in include_dirs:
555
555
  continue
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lamindb_setup
3
- Version: 1.0a1
3
+ Version: 1.0.1
4
4
  Summary: Setup & configure LaminDB.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
- Requires-Python: >=3.9
6
+ Requires-Python: >=3.10
7
7
  Description-Content-Type: text/markdown
8
8
  Requires-Dist: lamin_utils>=0.3.3
9
9
  Requires-Dist: django>=5,<5.2
@@ -1,47 +1,47 @@
1
- lamindb_setup/__init__.py,sha256=k7P3AZb2980R0v07EyB8b-cVODo3vHm5kzBOn5fYj_4,2646
2
- lamindb_setup/_cache.py,sha256=1XnM-V_KprbjpgPY7Bg3FYn53Iz_2_fEgcMOaSdKKbg,1332
1
+ lamindb_setup/__init__.py,sha256=IMQj8c7P8mhACmlJoPc_4cGqpaw9mK9SCvBBH3WBxHM,2127
2
+ lamindb_setup/_cache.py,sha256=aszT-zk3S5dTLKp5g1W-S_FPh2E5YVCALwWSGPJLWBM,1493
3
3
  lamindb_setup/_check.py,sha256=28PcG8Kp6OpjSLSi1r2boL2Ryeh6xkaCL87HFbjs6GA,129
4
- lamindb_setup/_check_setup.py,sha256=FQA-wrLJgsBMmK5zJv3-2528CWhS-kwe4vOOXJ06yCM,3023
5
- lamindb_setup/_close.py,sha256=cXNwK7QTTyNFt2XTpLnO3KHljJ7ShOcISk95np_dltE,1239
6
- lamindb_setup/_connect_instance.py,sha256=YU54loNCweRy-lqfqd2i2Us6xxwftkUPlmCjiGWJ_wI,16109
4
+ lamindb_setup/_check_setup.py,sha256=DJ4lZp4N9Dcri8H7PEOl-YDoi4qqfQnXvwBuL4venAw,3425
5
+ lamindb_setup/_close.py,sha256=pf8PHrtRBC6TycBtVAXzD9EZSGufoyp5M82o6zLHmt4,1240
6
+ lamindb_setup/_connect_instance.py,sha256=XGYQhUjzGnH-KYniW5a396-U-C90lHXq0QqIzsZXlg0,16778
7
7
  lamindb_setup/_delete.py,sha256=Mip5M9tCxyfsjzdcPCl6x9CQ0TkYTqKNNWDIcJ-KVMo,5677
8
8
  lamindb_setup/_django.py,sha256=uIQflpkp8l3axyPaKURlk3kacgpElVP5KOKmFxYSMGk,1454
9
- lamindb_setup/_entry_points.py,sha256=Hs2oJQOCTaGUdWn-1mufM6qUZr9W_EJ_Oc3f0_Vc0Yw,616
10
- lamindb_setup/_exportdb.py,sha256=VjaeTsYgnhicbQUN05Ae0Au8lFKPAIeii7flOBcaMk4,2117
11
- lamindb_setup/_importdb.py,sha256=yYYShzUajTsR-cTW4CZ-UNDWZY2uE5PAgNbp-wn8Ogc,1874
12
- lamindb_setup/_init_instance.py,sha256=OFoaF_wadtxD_ICLq9uPLHP-IWTqGeu8Ea57F-CqgJ4,13617
13
- lamindb_setup/_migrate.py,sha256=bIW6TkgU93rTdnNAKWcyMgjTF0ypc_dzqsJG2lo_4Iw,9001
9
+ lamindb_setup/_entry_points.py,sha256=sKwXPX9xjOotoAjvgkU5LBwjjHLWVkh0ZGdiSsrch9k,522
10
+ lamindb_setup/_exportdb.py,sha256=QLjoH4dEwqa01A12naKaDPglCCzl2_VLKWFfJRE_uSg,2113
11
+ lamindb_setup/_importdb.py,sha256=fKv9ev5OOj_-bmzC8XZ1GxOcjIjI486yrHSHDWQrJeI,1874
12
+ lamindb_setup/_init_instance.py,sha256=JV34P4ShinIdeUmHeoOvNE3WtzLbk37HcsWxfaEC_ks,13944
13
+ lamindb_setup/_migrate.py,sha256=86ShCTLGnBT3HreYhua4B8YQTy6tyIOgpa0qlsdob1k,9093
14
14
  lamindb_setup/_register_instance.py,sha256=alQuYp2f8Ct8xvRC1gt8p_HZ0tqCd3gZD3kiPBLPpsI,1269
15
15
  lamindb_setup/_schema.py,sha256=b3uzhhWpV5mQtDwhMINc2MabGCnGLESy51ito3yl6Wc,679
16
- lamindb_setup/_schema_metadata.py,sha256=2uO6uwWScjwggK44z_UgYAuxL66BdKfy-ad8V4ebwxI,13985
16
+ lamindb_setup/_schema_metadata.py,sha256=7ITlzIK32GHdhMq9e0GtPM3QbzJWhUvzPutiHrjjPk0,13986
17
17
  lamindb_setup/_set_managed_storage.py,sha256=4tDxXQMt8Gw028uY3vIQxZQ7qBNXhQMc8saarNK_Z-s,2043
18
18
  lamindb_setup/_setup_user.py,sha256=-g7Xj6510BDyM8kuqAsVBZFwehlhBa_uWBSV1rPeuM8,4586
19
19
  lamindb_setup/_silence_loggers.py,sha256=AKF_YcHvX32eGXdsYK8MJlxEaZ-Uo2f6QDRzjKFCtws,1568
20
20
  lamindb_setup/core/__init__.py,sha256=BxIVMX5HQq8oZ1OuY_saUEJz5Tdd7gaCPngxVu5iou4,417
21
21
  lamindb_setup/core/_aws_credentials.py,sha256=_wBWC10MGx3PW9UXGhsVNlq7YvCER3RhfRgAdlxEjNM,6120
22
22
  lamindb_setup/core/_aws_storage.py,sha256=nEjeUv4xUVpoV0Lx-zjjmyb9w804bDyaeiM-OqbfwM0,1799
23
- lamindb_setup/core/_deprecated.py,sha256=3qxUI1dnDlSeR0BYrv7ucjqRBEojbqotPgpShXs4KF8,2520
23
+ lamindb_setup/core/_deprecated.py,sha256=HN7iUBdEgahw5e4NHCd1VJooUfieNb6GRzS5x8jU-q8,2549
24
24
  lamindb_setup/core/_docs.py,sha256=3k-YY-oVaJd_9UIY-LfBg_u8raKOCNfkZQPA73KsUhs,276
25
25
  lamindb_setup/core/_hub_client.py,sha256=cN19XbZmvLCxL_GKdOcKbedNRL7kR47vmLmA--NMv-U,6306
26
26
  lamindb_setup/core/_hub_core.py,sha256=qVGGsWVfP6GK9UzmEz1kuR_B8wFkgTstMJJoMHeUF0c,20007
27
27
  lamindb_setup/core/_hub_crud.py,sha256=IAuPZes1am8OFwtcf5jSRQPGG1eKwVTEsp9Li-uq0cQ,5377
28
- lamindb_setup/core/_hub_utils.py,sha256=08NwQsb53-tXa_pr-f0tPTN0FeeVf_i1p3dEbEWD0F4,3016
28
+ lamindb_setup/core/_hub_utils.py,sha256=6dyDGyzYFgVfR_lE3VN3CP1jGp98gxPtr-T91PAP05U,2687
29
29
  lamindb_setup/core/_private_django_api.py,sha256=KIn43HOhiRjkbTbddyJqv-WNTTa1bAizbM1tWXoXPBg,2869
30
30
  lamindb_setup/core/_settings.py,sha256=eslFO84vb5uRRfJ3r_uu4O8677l8lU5BbpZJMSAYw6A,8244
31
- lamindb_setup/core/_settings_instance.py,sha256=gUbffwhsp_SygjU0P1bohXnRejAQ2sDTjctSg4-O94A,19199
32
- lamindb_setup/core/_settings_load.py,sha256=5OpghcbkrK9KBM_0Iu-61FTI76UbOpPkkJpUittXS-w,4098
31
+ lamindb_setup/core/_settings_instance.py,sha256=agzlSvKhvLyyNPf-Gw-M3FYn2ARpR1QEoCexhIHX5IU,19437
32
+ lamindb_setup/core/_settings_load.py,sha256=boeNntqIZ_DjelRBUAGp0ujc5akmbrrsk-LY28exa7E,4099
33
33
  lamindb_setup/core/_settings_save.py,sha256=rxGxgaK5i9exKqSJERQQyY1WZio20meoQJoYXlVW-1w,3138
34
34
  lamindb_setup/core/_settings_storage.py,sha256=dPIvbA6PkdjM8gsX6zxtH7VNMc4vhkuEO4luVMZY7RQ,12243
35
35
  lamindb_setup/core/_settings_store.py,sha256=WcsgOmgnu9gztcrhp-N4OONNZyxICHV8M0HdJllTaEo,2219
36
36
  lamindb_setup/core/_settings_user.py,sha256=lWqV3HmZCsEq2UsU_iVNW0p9ddsNg7-B6xOaMNH1aw0,1475
37
- lamindb_setup/core/_setup_bionty_sources.py,sha256=jZOPXpipW_5IjMO-bLMk-_wVwk7-5MLd72K2rnqqy7U,4001
37
+ lamindb_setup/core/_setup_bionty_sources.py,sha256=qTPMV5TEbNiTB81QqG2rSs6W8j8kQ7kVQMLOXRzAxBI,4004
38
38
  lamindb_setup/core/cloud_sqlite_locker.py,sha256=i6TrT7HG0lqliPvZTlsZ_uplPaqhPBbabyfeR32SkA8,7107
39
- lamindb_setup/core/django.py,sha256=bJme5D9KHmo98S9dLzFktdS2rZ0Aoj4EdkirniirB1I,3763
39
+ lamindb_setup/core/django.py,sha256=jSbckc_R39BhnANGhO5YFzKA8BHNANJDDgS5rwkDWmU,3828
40
40
  lamindb_setup/core/exceptions.py,sha256=4NpLUNUIfXYVTFX2FvLZF8RW34exk2Vn2X3G4YhnTRg,276
41
- lamindb_setup/core/hashing.py,sha256=2kZy_7NQB1WoUK8SBrhFX90lBpTkBr1V9tf7FS9Fe2Q,3380
41
+ lamindb_setup/core/hashing.py,sha256=EO7NSXMdKZLe9cHxCNHiqd5-6pVhv97uafqpoWV9FKc,3394
42
42
  lamindb_setup/core/types.py,sha256=zJii2le38BJUmsNVvzDrbzGYr0yaeb-9Rw9IKmsBr3k,523
43
- lamindb_setup/core/upath.py,sha256=UqfZcSIEflje2393osJ0tleizGKip5N1VJtXXVFUH7U,31061
44
- lamindb_setup-1.0a1.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
45
- lamindb_setup-1.0a1.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
46
- lamindb_setup-1.0a1.dist-info/METADATA,sha256=YRknY51lYN64_4Nm-ytu8YmaeVvcD4B2XLCutFPNkNo,1689
47
- lamindb_setup-1.0a1.dist-info/RECORD,,
43
+ lamindb_setup/core/upath.py,sha256=iZIGnkvG6uZhjiq2qJ8v4pgABxw2rBwm_XSnZACzHVo,31075
44
+ lamindb_setup-1.0.1.dist-info/LICENSE,sha256=UOZ1F5fFDe3XXvG4oNnkL1-Ecun7zpHzRxjp-XsMeAo,11324
45
+ lamindb_setup-1.0.1.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
46
+ lamindb_setup-1.0.1.dist-info/METADATA,sha256=MpFtq1_UbY_S1hUZpEIZRZVcpJQ3-rVwbrxDkjA0P88,1690
47
+ lamindb_setup-1.0.1.dist-info/RECORD,,