lamindb_setup 1.5.0__tar.gz → 1.5.2__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 (103) hide show
  1. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/PKG-INFO +3 -3
  2. lamindb_setup-1.5.0/docs/hub-prod/test-connect-anonymously-set-token.ipynb → lamindb_setup-1.5.2/docs/hub-prod/test-connect-anonymously.ipynb +1 -23
  3. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/__init__.py +1 -1
  4. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_schema_metadata.py +13 -2
  5. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_settings_user.py +1 -1
  6. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/django.py +52 -35
  7. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/upath.py +15 -0
  8. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/pyproject.toml +2 -2
  9. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-local/scripts/script-connect-fine-grained-access.py +18 -4
  10. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-local/test_update_schema_in_hub.py +32 -0
  11. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/.github/workflows/build.yml +0 -0
  12. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/.github/workflows/doc-changes.yml +0 -0
  13. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/.gitignore +0 -0
  14. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/.pre-commit-config.yaml +0 -0
  15. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/LICENSE +0 -0
  16. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/README.md +0 -0
  17. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/changelog.md +0 -0
  18. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-cloud/01-init-local-instance.ipynb +0 -0
  19. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-cloud/02-connect-local-instance.ipynb +0 -0
  20. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-cloud/03-add-managed-storage.ipynb +0 -0
  21. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-cloud/04-test-bionty.ipynb +0 -0
  22. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-cloud/05-init-hosted-instance.ipynb +0 -0
  23. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-cloud/06-connect-hosted-instance.ipynb +0 -0
  24. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-cloud/07-keep-artifacts-local.ipynb +0 -0
  25. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-cloud/08-test-multi-session.ipynb +0 -0
  26. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-cloud/test_notebooks.py +0 -0
  27. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-prod/test-cache-management.ipynb +0 -0
  28. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-prod/test-cloud-sync.ipynb +0 -0
  29. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-prod/test-empty-init.ipynb +0 -0
  30. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-prod/test-import-schema.ipynb +0 -0
  31. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-prod/test-init-load-local-anonymously.ipynb +0 -0
  32. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-prod/test-insufficient-user-info.ipynb +0 -0
  33. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-prod/test-invalid-schema.ipynb +0 -0
  34. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-prod/test-sqlite-lock.ipynb +0 -0
  35. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/hub-prod/test_notebooks2.py +0 -0
  36. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/index.md +0 -0
  37. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/notebooks.md +0 -0
  38. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/docs/reference.md +0 -0
  39. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_cache.py +0 -0
  40. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_check.py +0 -0
  41. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_check_setup.py +0 -0
  42. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_connect_instance.py +0 -0
  43. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_delete.py +0 -0
  44. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_disconnect.py +0 -0
  45. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_django.py +0 -0
  46. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_entry_points.py +0 -0
  47. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_exportdb.py +0 -0
  48. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_importdb.py +0 -0
  49. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_init_instance.py +0 -0
  50. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_migrate.py +0 -0
  51. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_register_instance.py +0 -0
  52. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_schema.py +0 -0
  53. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_set_managed_storage.py +0 -0
  54. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_setup_user.py +0 -0
  55. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/_silence_loggers.py +0 -0
  56. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/__init__.py +0 -0
  57. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_aws_options.py +0 -0
  58. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_aws_storage.py +0 -0
  59. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_deprecated.py +0 -0
  60. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_docs.py +0 -0
  61. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_hub_client.py +0 -0
  62. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_hub_core.py +0 -0
  63. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_hub_crud.py +0 -0
  64. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_hub_utils.py +0 -0
  65. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_private_django_api.py +0 -0
  66. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_settings.py +0 -0
  67. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_settings_instance.py +0 -0
  68. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_settings_load.py +0 -0
  69. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_settings_save.py +0 -0
  70. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_settings_storage.py +0 -0
  71. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_settings_store.py +0 -0
  72. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/_setup_bionty_sources.py +0 -0
  73. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/cloud_sqlite_locker.py +0 -0
  74. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/exceptions.py +0 -0
  75. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/hashing.py +0 -0
  76. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/lamindb_setup/core/types.py +0 -0
  77. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/noxfile.py +0 -0
  78. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/scripts/script-init-pass-user-no-writes.py +0 -0
  79. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/scripts/script-to-fail-managed-storage.py +0 -0
  80. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/test_connect_instance.py +0 -0
  81. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/test_delete_instance.py +0 -0
  82. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/test_edge_request.py +0 -0
  83. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/test_fail_managed_storage.py +0 -0
  84. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/test_init_instance.py +0 -0
  85. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/test_init_pass_user_no_writes.py +0 -0
  86. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/test_login.py +0 -0
  87. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/test_migrate.py +0 -0
  88. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-cloud/test_set_storage.py +0 -0
  89. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-local/conftest.py +0 -0
  90. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-local/test_all.py +0 -0
  91. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-prod/conftest.py +0 -0
  92. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-prod/test_aws_options_manager.py +0 -0
  93. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-prod/test_django.py +0 -0
  94. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-prod/test_global_settings.py +0 -0
  95. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-prod/test_switch_and_fallback_env.py +0 -0
  96. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/hub-prod/test_upath.py +0 -0
  97. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/storage/test_entry_point.py +0 -0
  98. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/storage/test_hashing.py +0 -0
  99. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/storage/test_storage_access.py +0 -0
  100. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/storage/test_storage_basis.py +0 -0
  101. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/storage/test_storage_settings.py +0 -0
  102. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/storage/test_storage_stats.py +0 -0
  103. {lamindb_setup-1.5.0 → lamindb_setup-1.5.2}/tests/storage/test_to_url.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lamindb_setup
3
- Version: 1.5.0
3
+ Version: 1.5.2
4
4
  Summary: Setup & configure LaminDB.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Requires-Python: >=3.10
@@ -13,8 +13,8 @@ Requires-Dist: appdirs<2.0.0
13
13
  Requires-Dist: requests
14
14
  Requires-Dist: universal_pathlib==0.2.6
15
15
  Requires-Dist: botocore<2.0.0
16
- Requires-Dist: supabase>=2.8.1,<2.12.0
17
- Requires-Dist: gotrue<2.12.0
16
+ Requires-Dist: supabase>=2.8.1,<=2.15.0
17
+ Requires-Dist: gotrue<=2.12.0
18
18
  Requires-Dist: storage3!=0.11.2; python_version < '3.11'
19
19
  Requires-Dist: pyjwt<3.0.0
20
20
  Requires-Dist: psutil
@@ -14,9 +14,7 @@
14
14
  "outputs": [],
15
15
  "source": [
16
16
  "import pytest\n",
17
- "import lamindb_setup as ln_setup\n",
18
- "from lamindb_setup.core.django import db_token_manager\n",
19
- "from django.db.utils import ProgrammingError"
17
+ "import lamindb_setup as ln_setup"
20
18
  ]
21
19
  },
22
20
  {
@@ -47,26 +45,6 @@
47
45
  "assert ln_setup.settings.storage._root is None"
48
46
  ]
49
47
  },
50
- {
51
- "cell_type": "code",
52
- "execution_count": null,
53
- "metadata": {},
54
- "outputs": [],
55
- "source": [
56
- "# this just tests that the function is setup properly\n",
57
- "# the actual functionality is tested in lamindb\n",
58
- "# set_token sql function is not defined\n",
59
- "db_token_manager.debug = True\n",
60
- "db_token_manager.set(\"test\")\n",
61
- "\n",
62
- "with pytest.raises(ProgrammingError):\n",
63
- " ln_setup.settings.storage.record # makes a db query through django\n",
64
- "\n",
65
- "db_token_manager.reset() # turn off token\n",
66
- "\n",
67
- "ln_setup.settings.storage.record"
68
- ]
69
- },
70
48
  {
71
49
  "cell_type": "code",
72
50
  "execution_count": null,
@@ -33,7 +33,7 @@ Modules & settings:
33
33
 
34
34
  """
35
35
 
36
- __version__ = "1.5.0" # denote a release candidate for 0.1.0 with 0.1rc1
36
+ __version__ = "1.5.2" # denote a release candidate for 0.1.0 with 0.1rc1
37
37
 
38
38
  import os
39
39
 
@@ -150,6 +150,7 @@ class FieldMetadata(BaseModel):
150
150
  is_link_table: bool
151
151
  is_primary_key: bool
152
152
  is_editable: bool
153
+ max_length: int | None = None
153
154
  relation_type: RelationType | None = None
154
155
  related_field_name: str | None = None
155
156
  related_model_name: str | None = None
@@ -168,6 +169,10 @@ class _ModelHandler:
168
169
  self.included_modules = included_modules
169
170
  self.fields = self._get_fields_metadata(self.model)
170
171
  self.is_link_table = issubclass(model, LinkORM)
172
+ self.name_field = model._name_field if hasattr(model, "_name_field") else None
173
+ self.ontology_id_field = (
174
+ model._ontology_id_field if hasattr(model, "_ontology_id_field") else None
175
+ )
171
176
 
172
177
  def to_dict(self, include_django_objects: bool = True):
173
178
  _dict = {
@@ -175,6 +180,8 @@ class _ModelHandler:
175
180
  "class_name": self.class_name,
176
181
  "table_name": self.table_name,
177
182
  "is_link_table": self.is_link_table,
183
+ "name_field": self.name_field,
184
+ "ontology_id_field": self.ontology_id_field,
178
185
  }
179
186
 
180
187
  for field_name in self.fields.keys():
@@ -243,18 +250,21 @@ class _ModelHandler:
243
250
  internal_type = field.get_internal_type()
244
251
  model_name = field.model._meta.model_name
245
252
  relation_type = self._get_relation_type(model, field)
253
+
254
+ schema_name = field.model.__get_module_name__()
255
+
246
256
  if field.related_model is None:
247
- schema_name = field.model.__get_module_name__()
248
257
  related_model_name = None
249
258
  related_schema_name = None
250
259
  related_field_name = None
251
260
  is_editable = field.editable
261
+ max_length = field.max_length
252
262
  else:
253
263
  related_model_name = field.related_model._meta.model_name
254
264
  related_schema_name = field.related_model.__get_module_name__()
255
- schema_name = field.model.__get_module_name__()
256
265
  related_field_name = field.remote_field.name
257
266
  is_editable = False
267
+ max_length = None
258
268
 
259
269
  field_name = field.name
260
270
  is_primary_key = getattr(field, "primary_key", False)
@@ -289,6 +299,7 @@ class _ModelHandler:
289
299
  is_link_table=issubclass(field.model, LinkORM),
290
300
  is_primary_key=is_primary_key,
291
301
  is_editable=is_editable,
302
+ max_length=max_length,
292
303
  column_name=column,
293
304
  relation_type=relation_type,
294
305
  related_schema_name=related_schema_name
@@ -47,7 +47,7 @@ class UserSettings:
47
47
 
48
48
  @property
49
49
  def id(self):
50
- """Integer id valid in current intance."""
50
+ """Integer id valid in current instance."""
51
51
  from lamindb.base.users import current_user_id
52
52
 
53
53
  # there is no cache needed here because current_user_id()
@@ -3,6 +3,8 @@ from __future__ import annotations
3
3
  # flake8: noqa
4
4
  import builtins
5
5
  import os
6
+ import jwt
7
+ import time
6
8
  from pathlib import Path
7
9
  import time
8
10
  from ._settings_instance import InstanceSettings
@@ -14,15 +16,47 @@ IS_MIGRATING = False
14
16
  CONN_MAX_AGE = 299
15
17
 
16
18
 
19
+ # db token that refreshes on access if needed
20
+ class DBToken:
21
+ def __init__(
22
+ self, instance: InstanceSettings | dict, access_token: str | None = None
23
+ ):
24
+ self.instance = instance
25
+ self.access_token = access_token
26
+ # initialized in token_query
27
+ self._token: str | None = None
28
+ self._token_query: str | None = None
29
+ self._expiration: float
30
+
31
+ def _refresh_token(self):
32
+ from ._hub_core import access_db
33
+ from psycopg2.extensions import adapt
34
+
35
+ self._token = access_db(self.instance, self.access_token)
36
+ self._token_query = (
37
+ f"SELECT set_token({adapt(self._token).getquoted().decode()}, true);"
38
+ )
39
+ self._expiration = jwt.decode(self._token, options={"verify_signature": False})[
40
+ "exp"
41
+ ]
42
+
43
+ @property
44
+ def token_query(self) -> str:
45
+ # refresh token if needed
46
+ if self._token is None or time.time() >= self._expiration:
47
+ self._refresh_token()
48
+
49
+ return self._token_query # type: ignore
50
+
51
+
17
52
  # a class to manage jwt in dbs
18
53
  class DBTokenManager:
19
- def __init__(self, debug: bool = False):
54
+ def __init__(self):
20
55
  from django.db.transaction import Atomic
21
56
 
22
- self.debug = debug
23
57
  self.original_atomic_enter = Atomic.__enter__
24
58
 
25
- self.tokens: dict[str, str] = {}
59
+ self.tokens: dict[str, DBToken] = {}
26
60
 
27
61
  def get_connection(self, connection_name: str):
28
62
  from django.db import connections
@@ -32,19 +66,11 @@ class DBTokenManager:
32
66
 
33
67
  return connection
34
68
 
35
- def set(self, token: str, connection_name: str = "default"):
69
+ def set(self, token: DBToken, connection_name: str = "default"):
36
70
  from django.db.transaction import Atomic
37
71
 
38
- # no adapt in psycopg3
39
- from psycopg2.extensions import adapt
40
-
41
72
  connection = self.get_connection(connection_name)
42
73
 
43
- # escape correctly to avoid wrangling with params
44
- set_token_query = (
45
- f"SELECT set_token({adapt(token).getquoted().decode()}, true); "
46
- )
47
-
48
74
  def set_token_wrapper(execute, sql, params, many, context):
49
75
  not_in_atomic_block = (
50
76
  context is None
@@ -53,12 +79,7 @@ class DBTokenManager:
53
79
  )
54
80
  # ignore atomic blocks
55
81
  if not_in_atomic_block:
56
- sql = set_token_query + sql
57
- elif self.debug:
58
- print("--in atomic block--")
59
-
60
- if self.debug:
61
- print(sql)
82
+ sql = token.token_query + sql
62
83
  result = execute(sql, params, many, context)
63
84
  # this ensures that psycopg3 in the current env doesn't break this wrapper
64
85
  # psycopg3 returns a cursor
@@ -69,30 +90,29 @@ class DBTokenManager:
69
90
  and result is not None
70
91
  and hasattr(result, "nextset")
71
92
  ):
72
- if self.debug:
73
- print("(shift cursor)")
74
93
  result.nextset()
75
94
  return result
76
95
 
77
96
  connection.execute_wrappers.append(set_token_wrapper)
78
97
 
98
+ self.tokens[connection_name] = token
99
+
79
100
  # ensure we set the token only once for an outer atomic block
80
101
  def __enter__(atomic):
81
102
  self.original_atomic_enter(atomic)
82
- is_same_connection = (
83
- "default" if atomic.using is None else atomic.using
84
- ) == connection_name
85
- if is_same_connection and len(connection.atomic_blocks) == 1:
86
- # use raw psycopg2 connection here
87
- # atomic block ensures connection
88
- if self.debug:
89
- print("(set transaction token)")
90
- connection.connection.cursor().execute(set_token_query)
103
+ connection_name = "default" if atomic.using is None else atomic.using
104
+ if connection_name in self.tokens:
105
+ # here we don't use the connection from the closure
106
+ # because Atomic is a single class to manage transactions for all connections
107
+ connection = self.get_connection(connection_name)
108
+ if len(connection.atomic_blocks) == 1:
109
+ token = self.tokens[connection_name]
110
+ # use raw psycopg2 connection here
111
+ # atomic block ensures connection
112
+ connection.connection.cursor().execute(token.token_query)
91
113
 
92
114
  Atomic.__enter__ = __enter__
93
115
 
94
- self.tokens[connection_name] = token
95
-
96
116
  def reset(self, connection_name: str = "default"):
97
117
  from django.db.transaction import Atomic
98
118
 
@@ -103,7 +123,6 @@ class DBTokenManager:
103
123
  for w in connection.execute_wrappers
104
124
  if getattr(w, "__name__", None) != "set_token_wrapper"
105
125
  ]
106
- Atomic.__enter__ = self.original_atomic_enter
107
126
 
108
127
  self.tokens.pop(connection_name, None)
109
128
 
@@ -198,9 +217,7 @@ def setup_django(
198
217
  BaseDatabaseWrapper.close_if_health_check_failed = close_if_health_check_failed
199
218
 
200
219
  if isettings._fine_grained_access and isettings._db_permissions == "jwt":
201
- from ._hub_core import access_db
202
-
203
- db_token = access_db(isettings)
220
+ db_token = DBToken(isettings)
204
221
  db_token_manager.set(db_token) # sets for the default connection
205
222
 
206
223
  if configure_only:
@@ -51,6 +51,21 @@ VALID_SIMPLE_SUFFIXES = {
51
51
  ".xml",
52
52
  ".qs", # https://cran.r-project.org/web/packages/qs/vignettes/vignette.html
53
53
  ".rds",
54
+ ".pt",
55
+ ".pth",
56
+ ".ckpt",
57
+ ".state_dict",
58
+ ".keras",
59
+ ".pb",
60
+ ".pbtxt",
61
+ ".savedmodel",
62
+ ".pkl",
63
+ ".pickle",
64
+ ".bin",
65
+ ".safetensors",
66
+ ".model",
67
+ ".mlmodel",
68
+ ".mar",
54
69
  #
55
70
  # with readers (see below)
56
71
  #
@@ -18,8 +18,8 @@ dependencies = [
18
18
  "requests",
19
19
  "universal_pathlib==0.2.6", # is still experimental, need pinning
20
20
  "botocore<2.0.0",
21
- "supabase>=2.8.1,<2.12.0", # from 2.8.1 has correct lower bounds on gotrue
22
- "gotrue<2.12.0", # supabase doesn't have this upper bound
21
+ "supabase>=2.8.1,<=2.15.0", # from 2.8.1 has correct lower bounds on gotrue
22
+ "gotrue<=2.12.0", # supabase doesn't have this upper bound
23
23
  "storage3!=0.11.2; python_version < '3.11'", # 0.11.2 breaks python 3.10 through usage of new types
24
24
  "pyjwt<3.0.0", # needed to decode jwt for sign in with the new api key
25
25
  "psutil",
@@ -2,7 +2,8 @@ import os
2
2
 
3
3
  import lamindb_setup as ln_setup
4
4
  import pytest
5
- from django.db import transaction
5
+ from django.db import connection, transaction
6
+ from django.db.utils import ProgrammingError
6
7
  from lamindb_setup.core._hub_core import access_db
7
8
  from lamindb_setup.core.django import db_token_manager
8
9
 
@@ -16,15 +17,28 @@ assert isettings._fine_grained_access
16
17
  assert isettings._db_permissions == "jwt"
17
18
  assert isettings._api_url is not None
18
19
 
19
- # test querying
20
- db_token_manager.debug = True
21
-
22
20
  storage_record = isettings.storage.record
23
21
 
24
22
  isettings.storage._record = None
25
23
  with transaction.atomic():
26
24
  assert isettings.storage.record.id == storage_record.id
27
25
 
26
+ # check directly
27
+ assert db_token_manager.tokens
28
+
29
+ with connection.cursor() as cur:
30
+ cur.execute("SELECT get_account_id();")
31
+ account_id = cur.fetchall()[0][0]
32
+ assert account_id == ln_setup.settings.user._uuid
33
+
34
+ # check reset
35
+ db_token_manager.reset()
36
+ assert not db_token_manager.tokens
37
+
38
+ # check after reset
39
+ with pytest.raises(ProgrammingError) as error, connection.cursor() as cur:
40
+ cur.execute("SELECT get_account_id();")
41
+ assert "JWT is not set" in error.exconly()
28
42
  # check calling access_db with a dict
29
43
  instance_dict = {
30
44
  "owner": isettings.owner,
@@ -44,6 +44,14 @@ def test_update_schema_in_hub(setup_instance):
44
44
  assert not schema["schema_json"]["core"]["artifact"]["is_link_table"]
45
45
  assert schema["schema_json"]["core"]["artifactulabel"]["is_link_table"]
46
46
 
47
+ assert schema["schema_json"]["core"]["artifact"]["name_field"] is None
48
+ assert schema["schema_json"]["core"]["artifact"]["ontology_id_field"] is None
49
+ assert schema["schema_json"]["bionty"]["gene"]["name_field"] == "symbol"
50
+ assert (
51
+ schema["schema_json"]["bionty"]["gene"]["ontology_id_field"]
52
+ == "ensembl_gene_id"
53
+ )
54
+
47
55
  assert schema["schema_json"]["core"]["artifact"]["fields"]["id"] == {
48
56
  "type": "AutoField",
49
57
  "column_name": "id",
@@ -54,6 +62,24 @@ def test_update_schema_in_hub(setup_instance):
54
62
  "is_link_table": False,
55
63
  "is_primary_key": True,
56
64
  "is_editable": True, # Primary key are read-only even if is_editable is True
65
+ "max_length": None,
66
+ "relation_type": None,
67
+ "related_field_name": None,
68
+ "related_model_name": None,
69
+ "related_schema_name": None,
70
+ }
71
+
72
+ assert schema["schema_json"]["core"]["artifact"]["fields"]["uid"] == {
73
+ "type": "CharField",
74
+ "column_name": "uid",
75
+ "through": None,
76
+ "field_name": "uid",
77
+ "model_name": "artifact",
78
+ "schema_name": "core",
79
+ "is_link_table": False,
80
+ "is_primary_key": False,
81
+ "is_editable": False,
82
+ "max_length": 20,
57
83
  "relation_type": None,
58
84
  "related_field_name": None,
59
85
  "related_model_name": None,
@@ -70,6 +96,7 @@ def test_update_schema_in_hub(setup_instance):
70
96
  "is_link_table": False,
71
97
  "is_primary_key": False,
72
98
  "is_editable": False,
99
+ "max_length": 64,
73
100
  "relation_type": None,
74
101
  "related_field_name": None,
75
102
  "related_model_name": None,
@@ -90,6 +117,7 @@ def test_update_schema_in_hub(setup_instance):
90
117
  "is_link_table": False,
91
118
  "is_primary_key": False,
92
119
  "is_editable": False,
120
+ "max_length": None,
93
121
  "relation_type": "many-to-one",
94
122
  "related_field_name": "created_artifacts",
95
123
  "related_model_name": "user",
@@ -110,6 +138,7 @@ def test_update_schema_in_hub(setup_instance):
110
138
  "is_link_table": False,
111
139
  "is_primary_key": False,
112
140
  "is_editable": False,
141
+ "max_length": None,
113
142
  "relation_type": "many-to-many",
114
143
  "related_field_name": "genes",
115
144
  "related_model_name": "pathway",
@@ -130,6 +159,7 @@ def test_update_schema_in_hub(setup_instance):
130
159
  "is_link_table": False,
131
160
  "is_primary_key": False,
132
161
  "is_editable": False,
162
+ "max_length": None,
133
163
  "relation_type": "many-to-many",
134
164
  "related_field_name": "wells",
135
165
  "related_model_name": "artifact",
@@ -150,6 +180,7 @@ def test_update_schema_in_hub(setup_instance):
150
180
  "is_link_table": False,
151
181
  "is_primary_key": False,
152
182
  "is_editable": False,
183
+ "max_length": None,
153
184
  "relation_type": "many-to-many",
154
185
  "related_field_name": "successors",
155
186
  "related_model_name": "transform",
@@ -170,6 +201,7 @@ def test_update_schema_in_hub(setup_instance):
170
201
  "is_link_table": False,
171
202
  "is_primary_key": False,
172
203
  "is_editable": False,
204
+ "max_length": None,
173
205
  "relation_type": "many-to-many",
174
206
  "related_field_name": "predecessors",
175
207
  "related_model_name": "transform",
File without changes
File without changes
File without changes
File without changes