lamindb_setup 1.6.0__py3-none-any.whl → 1.7.0__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
@@ -30,18 +30,20 @@ Modules & settings:
30
30
  settings
31
31
  core
32
32
  django
33
+ errors
34
+ types
33
35
 
34
36
  """
35
37
 
36
- __version__ = "1.6.0" # denote a release candidate for 0.1.0 with 0.1rc1
38
+ __version__ = "1.7.0" # denote a release candidate for 0.1.0 with 0.1rc1
37
39
 
38
40
  import os
39
41
 
40
42
  from packaging import version as packaging_version
41
43
 
42
- from . import core
44
+ from . import core, errors, types
43
45
  from ._check_setup import _check_instance_setup
44
- from ._connect_instance import connect, load
46
+ from ._connect_instance import connect
45
47
  from ._delete import delete
46
48
  from ._disconnect import disconnect
47
49
  from ._django import django
lamindb_setup/_cache.py CHANGED
@@ -1,10 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import shutil
4
+ from pathlib import Path
4
5
 
6
+ from dotenv import dotenv_values
5
7
  from lamin_utils import logger
6
8
 
7
- from .core._settings_save import save_system_storage_settings
9
+ from .core._settings_save import save_platform_user_storage_settings
10
+ from .core._settings_store import system_settings_file
8
11
 
9
12
 
10
13
  def clear_cache_dir():
@@ -13,7 +16,7 @@ def clear_cache_dir():
13
16
  try:
14
17
  if settings.instance._is_cloud_sqlite:
15
18
  logger.warning(
16
- "Disconnecting the current instance to update the cloud sqlite database."
19
+ "disconnecting the current instance to update the cloud sqlite database."
17
20
  )
18
21
  disconnect()
19
22
  except SystemExit as e:
@@ -21,9 +24,12 @@ def clear_cache_dir():
21
24
  raise e
22
25
 
23
26
  cache_dir = settings.cache_dir
24
- shutil.rmtree(cache_dir)
25
- cache_dir.mkdir()
26
- logger.success("The cache directory was cleared.")
27
+ if cache_dir.exists():
28
+ shutil.rmtree(cache_dir)
29
+ cache_dir.mkdir()
30
+ logger.success("the cache directory was cleared")
31
+ else:
32
+ logger.warning("the cache directory doesn't exist")
27
33
 
28
34
 
29
35
  def get_cache_dir():
@@ -41,12 +47,41 @@ def set_cache_dir(cache_dir: str):
41
47
 
42
48
  old_cache_dir = settings.cache_dir
43
49
  new_cache_dir = _process_cache_path(cache_dir)
50
+
51
+ system_cache_dir = None
52
+ if (system_settings := system_settings_file()).exists():
53
+ system_cache_dir = dotenv_values(system_settings).get(
54
+ "lamindb_cache_path", None
55
+ )
56
+ system_cache_dir = (
57
+ Path(system_cache_dir) if system_cache_dir is not None else None
58
+ )
59
+
60
+ need_reset = False
44
61
  if new_cache_dir is None:
45
- new_cache_dir = DEFAULT_CACHE_DIR
62
+ need_reset = True
63
+ new_cache_dir = (
64
+ DEFAULT_CACHE_DIR if system_cache_dir is None else system_cache_dir
65
+ )
66
+
46
67
  if new_cache_dir != old_cache_dir:
47
- shutil.copytree(old_cache_dir, new_cache_dir, dirs_exist_ok=True)
48
- shutil.rmtree(old_cache_dir)
49
- logger.info("The current cache directory was moved to the specified location")
50
- new_cache_dir = new_cache_dir.resolve()
51
- save_system_storage_settings(new_cache_dir)
68
+ if old_cache_dir.exists():
69
+ shutil.copytree(old_cache_dir, new_cache_dir, dirs_exist_ok=True)
70
+ logger.info(
71
+ f"the current cache directory was copied to {new_cache_dir.as_posix()} "
72
+ )
73
+ if old_cache_dir != system_cache_dir:
74
+ shutil.rmtree(old_cache_dir)
75
+ logger.info(
76
+ f"cleared the old cache directory {old_cache_dir.as_posix()}"
77
+ )
78
+ else:
79
+ logger.info(
80
+ f"didn't clear the system cache directory {system_cache_dir.as_posix()}, "
81
+ "please clear it manually if you need"
82
+ )
83
+ else:
84
+ new_cache_dir.mkdir(parents=True, exist_ok=True)
85
+ new_cache_dir = new_cache_dir.resolve()
86
+ save_platform_user_storage_settings(None if need_reset else new_cache_dir)
52
87
  settings._cache_dir = new_cache_dir
@@ -12,7 +12,11 @@ from ._silence_loggers import silence_loggers
12
12
  from .core import django as django_lamin
13
13
  from .core._settings import settings
14
14
  from .core._settings_store import current_instance_settings_file
15
- from .core.exceptions import DefaultMessageException
15
+ from .errors import (
16
+ MODULE_WASNT_CONFIGURED_MESSAGE_TEMPLATE,
17
+ InstanceNotSetupError,
18
+ ModuleWasntConfigured,
19
+ )
16
20
 
17
21
  if TYPE_CHECKING:
18
22
  from collections.abc import Callable
@@ -20,24 +24,10 @@ if TYPE_CHECKING:
20
24
  from .core._settings_instance import InstanceSettings
21
25
 
22
26
 
23
- class InstanceNotSetupError(DefaultMessageException):
24
- default_message = """\
25
- To use lamindb, you need to connect to an instance.
26
-
27
- Connect to an instance: `ln.connect()`. Init an instance: `ln.setup.init()`.
28
-
29
- If you used the CLI to set up lamindb in a notebook, restart the Python session.
30
- """
31
-
32
-
33
27
  CURRENT_ISETTINGS: InstanceSettings | None = None
34
28
  IS_LOADING: bool = False
35
29
 
36
30
 
37
- class ModuleWasntConfigured(SystemExit):
38
- pass
39
-
40
-
41
31
  # decorator to disable auto-connect when importing a module such as lamindb
42
32
  def disable_auto_connect(func: Callable):
43
33
  @functools.wraps(func)
@@ -84,18 +74,15 @@ def _normalize_module_name(module_name: str) -> str:
84
74
  def _check_module_in_instance_modules(
85
75
  module: str, isettings: InstanceSettings | None = None
86
76
  ) -> None:
87
- not_in_instance_msg = (
88
- f"'{module}' is missing from this instance. "
89
- "Please go to your instance settings page and add it under 'schema modules'."
90
- )
91
-
92
77
  if isettings is not None:
93
78
  modules_raw = isettings.modules
94
79
  modules = set(modules_raw).union(
95
80
  _normalize_module_name(module) for module in modules_raw
96
81
  )
97
82
  if _normalize_module_name(module) not in modules and module not in modules:
98
- raise ModuleWasntConfigured(not_in_instance_msg)
83
+ raise ModuleWasntConfigured(
84
+ MODULE_WASNT_CONFIGURED_MESSAGE_TEMPLATE.format(module)
85
+ )
99
86
  else:
100
87
  return
101
88
 
@@ -105,7 +92,7 @@ def _check_module_in_instance_modules(
105
92
  # app.name is always unnormalized module (python package) name
106
93
  if module == app.name or module == _normalize_module_name(app.name):
107
94
  return
108
- raise ModuleWasntConfigured(not_in_instance_msg)
95
+ raise ModuleWasntConfigured(MODULE_WASNT_CONFIGURED_MESSAGE_TEMPLATE.format(module))
109
96
 
110
97
 
111
98
  # infer the name of the module that calls this function
@@ -2,18 +2,14 @@ from __future__ import annotations
2
2
 
3
3
  import importlib
4
4
  import os
5
- from typing import TYPE_CHECKING
5
+ from typing import TYPE_CHECKING, Any
6
6
  from uuid import UUID
7
7
 
8
8
  from lamin_utils import logger
9
9
 
10
10
  from ._check_setup import _check_instance_setup, _get_current_instance_settings
11
11
  from ._disconnect import disconnect
12
- from ._init_instance import (
13
- MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE,
14
- CannotSwitchDefaultInstance,
15
- load_from_isettings,
16
- )
12
+ from ._init_instance import load_from_isettings
17
13
  from ._silence_loggers import silence_loggers
18
14
  from .core._hub_core import connect_instance_hub
19
15
  from .core._hub_utils import (
@@ -26,12 +22,13 @@ from .core._settings_load import load_instance_settings
26
22
  from .core._settings_storage import StorageSettings
27
23
  from .core._settings_store import instance_settings_file, settings_dir
28
24
  from .core.cloud_sqlite_locker import unlock_cloud_sqlite_upon_exception
25
+ from .errors import CannotSwitchDefaultInstance
29
26
 
30
27
  if TYPE_CHECKING:
31
28
  from pathlib import Path
32
29
 
33
30
  from .core._settings_user import UserSettings
34
- from .core.types import UPathStr
31
+ from .types import UPathStr
35
32
 
36
33
  # this is for testing purposes only
37
34
  # set to True only to test failed load
@@ -158,7 +155,7 @@ def _connect_instance(
158
155
  isettings = InstanceSettings(
159
156
  id=UUID(instance_result["id"]),
160
157
  owner=owner,
161
- name=name,
158
+ name=instance_result["name"],
162
159
  storage=ssettings,
163
160
  db=db_updated,
164
161
  modules=instance_result["schema_str"],
@@ -189,7 +186,7 @@ def _connect_instance(
189
186
 
190
187
 
191
188
  @unlock_cloud_sqlite_upon_exception(ignore_prev_locker=True)
192
- def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
189
+ def connect(instance: str | None = None, **kwargs: Any) -> str | tuple | None:
193
190
  """Connect to an instance.
194
191
 
195
192
  Args:
@@ -211,7 +208,7 @@ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
211
208
  isettings: InstanceSettings = None # type: ignore
212
209
  # _db is still needed because it is called in init
213
210
  _db: str | None = kwargs.get("_db", None)
214
- _write_settings: bool = kwargs.get("_write_settings", True)
211
+ _write_settings: bool = kwargs.get("_write_settings", False)
215
212
  _raise_not_found_error: bool = kwargs.get("_raise_not_found_error", True)
216
213
  _reload_lamindb: bool = kwargs.get("_reload_lamindb", True)
217
214
  _test: bool = kwargs.get("_test", False)
@@ -241,9 +238,9 @@ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
241
238
  logger.important(f"connected lamindb: {settings.instance.slug}")
242
239
  return None
243
240
  else:
244
- raise CannotSwitchDefaultInstance(
245
- MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE
246
- )
241
+ from lamindb_setup.core.django import reset_django
242
+
243
+ reset_django()
247
244
  elif (
248
245
  _write_settings
249
246
  and settings._instance_exists
@@ -270,15 +267,6 @@ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
270
267
  if _test:
271
268
  return None
272
269
  silence_loggers()
273
- # migrate away from lnschema-core
274
- no_lnschema_core_file = (
275
- settings_dir / f"no_lnschema_core-{isettings.slug.replace('/', '--')}"
276
- )
277
- if not no_lnschema_core_file.exists():
278
- # sqlite file for cloud sqlite instances is already updated here
279
- migrate_lnschema_core(
280
- isettings, no_lnschema_core_file, write_file=_write_settings
281
- )
282
270
  check, msg = isettings._load_db()
283
271
  if not check:
284
272
  local_db = (
@@ -305,8 +293,7 @@ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
305
293
  load_from_isettings(isettings, user=_user, write_settings=_write_settings)
306
294
  if _reload_lamindb:
307
295
  importlib.reload(importlib.import_module("lamindb"))
308
- else:
309
- logger.important(f"connected lamindb: {isettings.slug}")
296
+ logger.important(f"connected lamindb: {isettings.slug}")
310
297
  except Exception as e:
311
298
  if isettings is not None:
312
299
  if _write_settings:
@@ -316,141 +303,6 @@ def connect(instance: str | None = None, **kwargs) -> str | tuple | None:
316
303
  return None
317
304
 
318
305
 
319
- def load(slug: str) -> str | tuple | None:
320
- """Connect to instance and set ``auto-connect`` to true.
321
-
322
- This is exactly the same as ``ln.connect()`` except for that
323
- ``ln.connect()`` doesn't change the state of ``auto-connect``.
324
- """
325
- print("Warning: This is deprecated and will be removed.")
326
- result = connect(slug)
327
- settings.auto_connect = True
328
- return result
329
-
330
-
331
- def migrate_lnschema_core(
332
- isettings: InstanceSettings, no_lnschema_core_file: Path, write_file: bool = True
333
- ):
334
- """Migrate lnschema_core tables to lamindb tables."""
335
- from urllib.parse import urlparse
336
-
337
- # we need to do this because the sqlite file should be already synced
338
- # has no effect if not cloud sqlite
339
- # errors if the sqlite file is not in the cloud and doesn't exist locally
340
- # isettings.db syncs but doesn't error in this case due to error_no_origin=False
341
- isettings._update_local_sqlite_file()
342
-
343
- parsed_uri = urlparse(isettings.db)
344
- db_type = parsed_uri.scheme
345
-
346
- if db_type == "sqlite":
347
- import sqlite3
348
-
349
- # maybe also use LAMINDB_DJANGO_DATABASE_URL here?
350
- conn = sqlite3.connect(parsed_uri.path)
351
- elif db_type in ["postgresql", "postgres"]:
352
- import psycopg2
353
-
354
- # do not ignore LAMINDB_DJANGO_DATABASE_URL if it is set
355
- conn = psycopg2.connect(
356
- os.environ.get("LAMINDB_DJANGO_DATABASE_URL", isettings.db)
357
- )
358
- else:
359
- raise ValueError("Unsupported database type. Use 'sqlite' or 'postgresql' URI.")
360
-
361
- cur = conn.cursor()
362
-
363
- try:
364
- if db_type == "sqlite":
365
- cur.execute(
366
- "SELECT name FROM sqlite_master WHERE type='table' AND name='lamindb_user'"
367
- )
368
- migrated = cur.fetchone() is not None
369
-
370
- # tables that need to be renamed
371
- cur.execute(
372
- "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'lnschema_core_%'"
373
- )
374
- tables_to_rename = [
375
- row[0][len("lnschema_core_") :] for row in cur.fetchall()
376
- ]
377
- else: # postgres
378
- cur.execute(
379
- "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'lamindb_user')"
380
- )
381
- migrated = cur.fetchone()[0]
382
-
383
- # tables that need to be renamed
384
- cur.execute(
385
- "SELECT table_name FROM information_schema.tables WHERE table_name LIKE 'lnschema_core_%'"
386
- )
387
- tables_to_rename = [
388
- row[0][len("lnschema_core_") :] for row in cur.fetchall()
389
- ]
390
-
391
- if migrated:
392
- if write_file:
393
- no_lnschema_core_file.touch(exist_ok=True)
394
- else:
395
- try:
396
- response = input(
397
- f"Do you want to migrate to lamindb 1.0 (integrate lnschema_core into lamindb)? (y/n) -- Will rename {tables_to_rename}"
398
- )
399
- if response != "y":
400
- print("Aborted.")
401
- quit()
402
- if isettings.is_on_hub:
403
- from lamindb_setup.core._hub_client import call_with_fallback_auth
404
- from lamindb_setup.core._hub_crud import (
405
- select_collaborator,
406
- )
407
-
408
- # double check that user is an admin, otherwise will fail below
409
- # due to insufficient SQL permissions with cryptic error
410
- collaborator = call_with_fallback_auth(
411
- select_collaborator,
412
- instance_id=settings.instance._id,
413
- account_id=settings.user._uuid,
414
- )
415
- if collaborator is None or collaborator["role"] != "admin":
416
- raise SystemExit(
417
- "❌ Only admins can deploy migrations, please ensure that you're an"
418
- f" admin: https://lamin.ai/{settings.instance.slug}/settings"
419
- )
420
- for table in tables_to_rename:
421
- if db_type == "sqlite":
422
- cur.execute(
423
- f"ALTER TABLE lnschema_core_{table} RENAME TO lamindb_{table}"
424
- )
425
- else: # postgres
426
- cur.execute(
427
- f"ALTER TABLE lnschema_core_{table} RENAME TO lamindb_{table};"
428
- )
429
-
430
- cur.execute(
431
- "UPDATE django_migrations SET app = 'lamindb' WHERE app = 'lnschema_core'"
432
- )
433
- print(
434
- "Renaming tables finished.\nNow, *please* call: lamin migrate deploy"
435
- )
436
- if write_file:
437
- no_lnschema_core_file.touch(exist_ok=True)
438
- except Exception:
439
- # read-only users can't rename tables
440
- pass
441
-
442
- conn.commit()
443
-
444
- except Exception as e:
445
- print(f"An error occurred: {e}")
446
- conn.rollback()
447
-
448
- finally:
449
- # close the cursor and connection
450
- cur.close()
451
- conn.close()
452
-
453
-
454
306
  def get_owner_name_from_identifier(identifier: str):
455
307
  if "/" in identifier:
456
308
  if identifier.startswith("https://lamin.ai/"):
@@ -8,7 +8,7 @@ from uuid import UUID
8
8
 
9
9
  import click
10
10
  from django.core.exceptions import FieldError
11
- from django.db.utils import OperationalError, ProgrammingError
11
+ from django.db.utils import IntegrityError, OperationalError, ProgrammingError
12
12
  from lamin_utils import logger
13
13
 
14
14
  from ._disconnect import disconnect
@@ -19,12 +19,13 @@ from .core._settings import settings
19
19
  from .core._settings_instance import is_local_db_url
20
20
  from .core._settings_storage import StorageSettings, init_storage
21
21
  from .core.upath import UPath
22
+ from .errors import CannotSwitchDefaultInstance
22
23
 
23
24
  if TYPE_CHECKING:
24
25
  from pydantic import PostgresDsn
25
26
 
26
27
  from .core._settings_user import UserSettings
27
- from .core.types import UPathStr
28
+ from .types import UPathStr
28
29
 
29
30
 
30
31
  class InstanceNotCreated(click.ClickException):
@@ -49,37 +50,31 @@ def get_schema_module_name(module_name, raise_import_error: bool = True) -> str
49
50
 
50
51
 
51
52
  def register_storage_in_instance(ssettings: StorageSettings):
52
- from lamindb.base.users import current_user_id
53
53
  from lamindb.models import Storage
54
54
 
55
- from .core.hashing import hash_and_encode_as_b62
56
-
57
- if ssettings._instance_id is not None:
58
- instance_uid = hash_and_encode_as_b62(ssettings._instance_id.hex)[:12]
59
- else:
60
- instance_uid = None
61
55
  # how do we ensure that this function is only called passing
62
56
  # the managing instance?
63
- defaults = {
57
+ kwargs = {
64
58
  "root": ssettings.root_as_str,
65
59
  "type": ssettings.type,
66
60
  "region": ssettings.region,
67
- "instance_uid": instance_uid,
68
- "created_by_id": current_user_id(),
61
+ "instance_uid": ssettings.instance_uid,
69
62
  "run": None,
63
+ "_skip_preparation": True,
70
64
  }
71
65
  if ssettings._uid is not None:
72
- defaults["uid"] = ssettings._uid
73
- storage, _ = Storage.objects.update_or_create(
74
- root=ssettings.root_as_str,
75
- defaults=defaults,
76
- )
66
+ kwargs["uid"] = ssettings._uid
67
+ # this checks if the storage already exists under the hood
68
+ storage = Storage(**kwargs).save()
77
69
  return storage
78
70
 
79
71
 
80
- def register_user(usettings):
72
+ def register_user(usettings: UserSettings, update_user: bool = True):
81
73
  from lamindb.models import User
82
74
 
75
+ if not update_user and User.objects.filter(uid=usettings.uid).exists():
76
+ return
77
+
83
78
  try:
84
79
  # need to have try except because of integer primary key migration
85
80
  user, created = User.objects.update_or_create(
@@ -90,37 +85,38 @@ def register_user(usettings):
90
85
  },
91
86
  )
92
87
  # for users with only read access, except via ProgrammingError
93
- # ProgrammingError: permission denied for table lnschema_core_user
94
- except (OperationalError, FieldError, ProgrammingError):
88
+ # ProgrammingError: permission denied for table lamindb_user
89
+ # IntegrityError: when trying to update a user on a fine-grained access instance
90
+ except (OperationalError, FieldError, ProgrammingError, IntegrityError):
95
91
  pass
96
92
 
97
93
 
98
- def register_initial_records(isettings: InstanceSettings, usettings):
94
+ def register_initial_records(isettings: InstanceSettings, usettings: UserSettings):
99
95
  """Register space, user & storage in DB."""
100
96
  from django.db.utils import OperationalError
101
97
  from lamindb.models import Branch, Space
102
98
 
103
99
  try:
104
100
  Space.objects.get_or_create(
105
- uid="A",
106
- name="All",
101
+ uid="a",
102
+ name="all",
107
103
  description="Every team & user with access to the instance has access.",
108
104
  )
109
105
  Branch.objects.get_or_create(
110
106
  id=-1,
111
- uid="T",
112
- name="Trash",
107
+ uid="t",
108
+ name="trash",
113
109
  description="The trash.",
114
110
  )
115
111
  Branch.objects.get_or_create(
116
112
  id=0,
117
- uid="A",
118
- name="Archive",
113
+ uid="a",
114
+ name="archive",
119
115
  description="The archive.",
120
116
  )
121
117
  Branch.objects.get_or_create(
122
- uid="M",
123
- name="Main",
118
+ uid="m",
119
+ name="main",
124
120
  description="The main & default branch of the instance.",
125
121
  )
126
122
  register_user(usettings)
@@ -178,7 +174,7 @@ def validate_init_args(
178
174
  _user: UserSettings | None = None,
179
175
  ) -> tuple[
180
176
  str,
181
- UUID | None,
177
+ UUID,
182
178
  Literal[
183
179
  "connected",
184
180
  "instance-corrupted-or-deleted",
@@ -204,33 +200,21 @@ def validate_init_args(
204
200
  _write_settings=_write_settings,
205
201
  _user=_user,
206
202
  )
203
+ instance_id: UUID
207
204
  instance_state: Literal[
208
205
  "connected",
209
206
  "instance-corrupted-or-deleted",
210
207
  "account-not-exists",
211
208
  "instance-not-found",
212
- ] = "connected"
213
- instance_id = None
214
- if response is not None:
209
+ ]
210
+ if response is None:
211
+ instance_state, instance_id = "connected", settings.instance._id
212
+ else:
215
213
  instance_id, instance_state = process_connect_response(response, instance_slug)
216
214
  modules = process_modules_arg(modules)
217
215
  return name_str, instance_id, instance_state, instance_slug
218
216
 
219
217
 
220
- class CannotSwitchDefaultInstance(SystemExit):
221
- pass
222
-
223
-
224
- MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE = """
225
- You cannot write to different instances in the same Python session.
226
-
227
- Do you want to read from another instance via `SQLRecord.using()`? For example:
228
-
229
- ln.Artifact.using("laminlabs/cellxgene").filter()
230
-
231
- Or do you want to switch off auto-connect via `lamin settings set auto-connect false`?
232
- """
233
-
234
218
  DOC_STORAGE_ARG = "A local or remote folder (`'s3://...'` or `'gs://...'`). Defaults to current working directory."
235
219
  DOC_INSTANCE_NAME = (
236
220
  "Instance name. If not passed, it will equal the folder name passed to `storage`."
@@ -278,7 +262,9 @@ def init(
278
262
  from ._check_setup import _check_instance_setup
279
263
 
280
264
  if _check_instance_setup() and not _test:
281
- raise CannotSwitchDefaultInstance(MESSAGE_CANNOT_SWITCH_DEFAULT_INSTANCE)
265
+ from lamindb_setup.core.django import reset_django
266
+
267
+ reset_django()
282
268
  elif _write_settings:
283
269
  disconnect(mute=True)
284
270
  from .core._hub_core import init_instance_hub
@@ -296,13 +282,11 @@ def init(
296
282
  if _write_settings:
297
283
  settings.auto_connect = True # we can also debate this switch here
298
284
  return None
299
- # the conditions here match `isettings.is_remote`, but I currently don't
300
- # see a way of making this more elegant; should become possible if we
301
- # remove the instance.storage_id FK on the hub
302
285
  prevent_register_hub = is_local_db_url(db) if db is not None else False
303
286
  ssettings, _ = init_storage(
304
287
  storage,
305
288
  instance_id=instance_id,
289
+ instance_slug=f"{user_handle}/{name_str}",
306
290
  init_instance=True,
307
291
  prevent_register_hub=prevent_register_hub,
308
292
  created_by=user__uuid,
@@ -370,7 +354,7 @@ def init(
370
354
  and (user_handle != "anonymous" or access_token is not None)
371
355
  and ssettings.is_on_hub
372
356
  ):
373
- delete_storage_record(ssettings._uuid, access_token=access_token) # type: ignore
357
+ delete_storage_record(ssettings, access_token=access_token) # type: ignore
374
358
  if isettings is not None:
375
359
  if (
376
360
  user_handle != "anonymous" or access_token is not None
@@ -404,7 +388,9 @@ def load_from_isettings(
404
388
  # this is our best proxy for that the user might not
405
389
  # yet be registered
406
390
  if not isettings._get_settings_file().exists():
407
- register_user(user)
391
+ # do not try to update the user on fine grained access instances
392
+ # this is blocked anyways, only select and insert are allowed
393
+ register_user(user, update_user=not isettings._fine_grained_access)
408
394
  isettings._persist(write_to_disk=write_settings)
409
395
 
410
396
 
@@ -12,7 +12,7 @@ def register(_test: bool = False):
12
12
  from ._check_setup import _check_instance_setup
13
13
  from .core._hub_core import init_instance_hub, init_storage_hub
14
14
 
15
- logger.warning("""lamin register will be removed soon""")
15
+ logger.warning("note that register() is only for testing purposes")
16
16
 
17
17
  isettings = settings.instance
18
18
  if not _check_instance_setup() and not _test:
@@ -16,6 +16,7 @@ from django.db.models import (
16
16
  OneToOneField,
17
17
  OneToOneRel,
18
18
  )
19
+ from lamin_utils import logger
19
20
  from pydantic import BaseModel
20
21
 
21
22
  from lamindb_setup import settings
@@ -25,6 +26,9 @@ from lamindb_setup.core._hub_client import call_with_fallback_auth
25
26
  # surpress pydantic warning about `model_` namespace
26
27
  try:
27
28
  BaseModel.model_config["protected_namespaces"] = ()
29
+ logger.debug(
30
+ "pydantic.BaseModel.model_config['protected_namespaces'] has been set to ()"
31
+ )
28
32
  except Exception:
29
33
  pass
30
34