Skip to content

Commit 34acbbe

Browse files
Merge pull request #1412 from datajoint/fix/index-attribute-regex
fix: allow attribute names starting with 'index' in declarations
2 parents 0b4a346 + 49e5862 commit 34acbbe

File tree

5 files changed

+30
-15
lines changed

5 files changed

+30
-15
lines changed

src/datajoint/builtin_codecs/attach.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ def decode(self, stored: bytes, *, key: dict | None = None) -> str:
106106
# Write to download path
107107
config = (key or {}).get("_config")
108108
if config is None:
109-
from ..settings import config
109+
from ..settings import config # type: ignore[assignment]
110+
assert config is not None
110111
download_path = Path(config.get("download_path", "."))
111112
download_path.mkdir(parents=True, exist_ok=True)
112113
local_path = download_path / filename

src/datajoint/builtin_codecs/filepath.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ def encode(self, value: Any, *, key: dict | None = None, store_name: str | None
102102

103103
config = (key or {}).get("_config")
104104
if config is None:
105-
from ..settings import config
105+
from ..settings import config # type: ignore[assignment]
106+
assert config is not None
106107

107108
path = str(value)
108109

src/datajoint/declare.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ def prepare_declare(
370370
adapter,
371371
fk_attribute_map,
372372
)
373-
elif re.match(r"^(unique\s+)?index\s*.*$", line, re.I): # index
373+
elif re.match(r"^(unique\s+)?index\s*\(.*\)$", line, re.I): # index
374374
compile_index(line, index_sql, adapter)
375375
else:
376376
name, sql, store, comment = compile_attribute(line, in_key, foreign_key_sql, context, adapter)

src/datajoint/hash_registry.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,19 @@
3232
datajoint.gc : Garbage collection for orphaned storage items.
3333
"""
3434

35+
from __future__ import annotations
36+
3537
import base64
3638
import hashlib
3739
import logging
38-
from typing import Any
40+
from typing import TYPE_CHECKING, Any
3941

4042
from .errors import DataJointError
4143
from .storage import StorageBackend
4244

45+
if TYPE_CHECKING:
46+
from .settings import Config
47+
4348
logger = logging.getLogger(__name__.split(".")[0])
4449

4550

@@ -130,7 +135,7 @@ def build_hash_path(
130135
return f"_hash/{schema_name}/{content_hash}"
131136

132137

133-
def get_store_backend(store_name: str | None = None, config=None) -> StorageBackend:
138+
def get_store_backend(store_name: str | None = None, config: Config | None = None) -> StorageBackend:
134139
"""
135140
Get a StorageBackend for hash-addressed storage.
136141
@@ -147,13 +152,14 @@ def get_store_backend(store_name: str | None = None, config=None) -> StorageBack
147152
StorageBackend instance.
148153
"""
149154
if config is None:
150-
from .settings import config
155+
from .settings import config # type: ignore[assignment]
156+
assert config is not None
151157
# get_store_spec handles None by using stores.default
152158
spec = config.get_store_spec(store_name)
153159
return StorageBackend(spec)
154160

155161

156-
def get_store_subfolding(store_name: str | None = None, config=None) -> tuple[int, ...] | None:
162+
def get_store_subfolding(store_name: str | None = None, config: Config | None = None) -> tuple[int, ...] | None:
157163
"""
158164
Get the subfolding configuration for a store.
159165
@@ -170,7 +176,8 @@ def get_store_subfolding(store_name: str | None = None, config=None) -> tuple[in
170176
Subfolding pattern (e.g., (2, 2)) or None for flat storage.
171177
"""
172178
if config is None:
173-
from .settings import config
179+
from .settings import config # type: ignore[assignment]
180+
assert config is not None
174181
spec = config.get_store_spec(store_name)
175182
subfolding = spec.get("subfolding")
176183
if subfolding is not None:
@@ -182,7 +189,7 @@ def put_hash(
182189
data: bytes,
183190
schema_name: str,
184191
store_name: str | None = None,
185-
config=None,
192+
config: Config | None = None,
186193
) -> dict[str, Any]:
187194
"""
188195
Store content using hash-addressed storage.
@@ -231,7 +238,7 @@ def put_hash(
231238
}
232239

233240

234-
def get_hash(metadata: dict[str, Any], config=None) -> bytes:
241+
def get_hash(metadata: dict[str, Any], config: Config | None = None) -> bytes:
235242
"""
236243
Retrieve content using stored metadata.
237244
@@ -275,7 +282,7 @@ def get_hash(metadata: dict[str, Any], config=None) -> bytes:
275282
def delete_path(
276283
path: str,
277284
store_name: str | None = None,
278-
config=None,
285+
config: Config | None = None,
279286
) -> bool:
280287
"""
281288
Delete content at the specified path from storage.

tests/integration/test_declare.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,14 +339,20 @@ class WithSuchALongPartNameThatItCrashesMySQL(dj.Part):
339339
schema_any(WhyWouldAnyoneCreateATableNameThisLong)
340340

341341

342-
def test_regex_mismatch(schema_any):
342+
def test_index_attribute_name(schema_any):
343+
"""Attributes named 'index' should not be misclassified as index declarations (#1411)."""
344+
343345
class IndexAttribute(dj.Manual):
344346
definition = """
345-
index: int
347+
index : int
348+
---
349+
index_value : float
346350
"""
347351

348-
with pytest.raises(dj.DataJointError):
349-
schema_any(IndexAttribute)
352+
schema_any(IndexAttribute)
353+
assert "index" in IndexAttribute.heading.attributes
354+
assert "index_value" in IndexAttribute.heading.attributes
355+
IndexAttribute.drop()
350356

351357

352358
def test_table_name_with_underscores(schema_any):

0 commit comments

Comments
 (0)