Skip to content

Commit f5b8bc3

Browse files
authored
Merge pull request #1750 from dandi/copilot/adjust-known-urls-support
Add support for all known instances in short URL format, removed dandi-staging and renamed EMBER* ones into EMBER-DANDI*
2 parents 7cf6ace + 5f60b9b commit f5b8bc3

File tree

10 files changed

+66
-33
lines changed

10 files changed

+66
-33
lines changed

DEVELOPMENT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ development command line options.
6161
variable providing the key for a specific known DANDI instance corresponds to the name
6262
of the instance. For example, the environment variable `DANDI_API_KEY` provides the key
6363
for the known instance named `dandi` and the environment variable
64-
`EMBER_SANDBOX_API_KEY` provides the key for the known instance named `ember-sandbox`.
64+
`EMBER_DANDI_SANDBOX_API_KEY` provides the key for the known instance named `ember-dandi-sandbox`.
6565
I.e., the environment variable name is the capitalized version of the instance's name
6666
with "-" replaced by "_" suffixed by "_API_KEY". Providing API keys through environment
6767
variables avoids using keyrings, thus making it possible to "temporarily" use another

dandi/cli/tests/test_instances.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,10 @@ def test_cmd_instances(monkeypatch):
1919
"dandi-sandbox:\n"
2020
" api: https://api.sandbox.dandiarchive.org/api\n"
2121
" gui: https://sandbox.dandiarchive.org\n"
22-
"dandi-staging:\n"
23-
" api: https://api.sandbox.dandiarchive.org/api\n"
24-
" gui: https://sandbox.dandiarchive.org\n"
25-
"ember:\n"
22+
"ember-dandi:\n"
2623
" api: https://api-dandi.emberarchive.org/api\n"
2724
" gui: https://dandi.emberarchive.org\n"
28-
"ember-sandbox:\n"
25+
"ember-dandi-sandbox:\n"
2926
" api: https://api-dandi-sandbox.emberarchive.org/api\n"
3027
" gui: https://apl-setup--ember-dandi-archive.netlify.app/\n"
3128
"linc:\n"

dandi/consts.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,6 @@ def urls(self) -> Iterator[str]:
123123
"https://dandiarchive.org",
124124
"https://api.dandiarchive.org/api",
125125
),
126-
# Deprecated. Remove early 2026.
127-
# Should come before dandi-sandbox so _rev map does map to sandbox
128-
"dandi-staging": DandiInstance(
129-
"dandi-staging",
130-
"https://sandbox.dandiarchive.org",
131-
"https://api.sandbox.dandiarchive.org/api",
132-
),
133126
"dandi-sandbox": DandiInstance(
134127
"dandi-sandbox",
135128
"https://sandbox.dandiarchive.org",
@@ -150,13 +143,13 @@ def urls(self) -> Iterator[str]:
150143
"https://staging.lincbrain.org",
151144
"https://staging-api.lincbrain.org/api",
152145
),
153-
"ember": DandiInstance(
154-
"ember",
146+
"ember-dandi": DandiInstance(
147+
"ember-dandi",
155148
"https://dandi.emberarchive.org",
156149
"https://api-dandi.emberarchive.org/api",
157150
),
158-
"ember-sandbox": DandiInstance(
159-
"ember-sandbox",
151+
"ember-dandi-sandbox": DandiInstance(
152+
"ember-dandi-sandbox",
160153
"https://apl-setup--ember-dandi-archive.netlify.app/",
161154
"https://api-dandi-sandbox.emberarchive.org/api",
162155
),

dandi/dandiarchive.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,10 @@ class _dandi_url_parser:
573573
dandiset_id_grp = f"(?P<dandiset_id>{DANDISET_ID_REGEX})"
574574
# Should absorb port and "api/":
575575
server_grp = "(?P<server>(?P<protocol>https?)://(?P<hostname>[^/]+)/(api/)?)"
576+
# Build instance name pattern from known instances to avoid matching unknown patterns
577+
instance_name_pattern = "|".join(
578+
re.escape(name.upper()) for name in known_instances
579+
)
576580
known_urls: list[tuple[re.Pattern[str], dict[str, Any], str]] = [
577581
# List of (regex, settings, display string) triples
578582
#
@@ -589,13 +593,12 @@ class _dandi_url_parser:
589593
# for not only "dandiarchive.org" URLs
590594
(
591595
re.compile(
592-
rf"(?P<instance_name>DANDI):"
596+
rf"(?P<instance_name>{instance_name_pattern}):"
593597
rf"{dandiset_id_grp}"
594598
rf"(/(?P<version>{VERSION_REGEX}))?",
595-
flags=re.I,
596599
),
597600
{},
598-
"DANDI:<dandiset id>[/<version>]",
601+
"<INSTANCE>:<dandiset id>[/<version>]",
599602
),
600603
(
601604
re.compile(r"https?://gui\.dandiarchive\.org/.*"),

dandi/tests/test_dandiapi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ def test_asset_as_readable_open(new_dandiset: SampleDandiset, tmp_path: Path) ->
869869
("dandi", "DANDI_API_KEY"),
870870
("dandi-api-local-docker-tests", "DANDI_API_LOCAL_DOCKER_TESTS_API_KEY"),
871871
("dandi-sandbox", "DANDI_SANDBOX_API_KEY"),
872-
("ember-sandbox", "EMBER_SANDBOX_API_KEY"),
872+
("ember-dandi-sandbox", "EMBER_DANDI_SANDBOX_API_KEY"),
873873
],
874874
)
875875
def test_get_api_key_env_var(instance_name: str, expected_env_var_name: str) -> None:

dandi/tests/test_dandiarchive.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,56 @@
108108
version_id="draft",
109109
),
110110
),
111-
# lower cased
111+
# numeric version
112112
(
113-
"dandi:000027/0.210831.2033",
113+
"DANDI:000027/0.210831.2033",
114114
DandisetURL(
115115
instance=known_instances["dandi"],
116116
dandiset_id="000027",
117117
version_id="0.210831.2033",
118118
),
119119
),
120+
# Test other instances with short format
121+
(
122+
"DANDI-SANDBOX:000029",
123+
DandisetURL(
124+
instance=known_instances["dandi-sandbox"],
125+
dandiset_id="000029",
126+
version_id=None,
127+
),
128+
),
129+
(
130+
"LINC:000029",
131+
DandisetURL(
132+
instance=known_instances["linc"],
133+
dandiset_id="000029",
134+
version_id=None,
135+
),
136+
),
137+
(
138+
"LINC:000029/0.210831.2033",
139+
DandisetURL(
140+
instance=known_instances["linc"],
141+
dandiset_id="000029",
142+
version_id="0.210831.2033",
143+
),
144+
),
145+
(
146+
"EMBER-DANDI:000029",
147+
DandisetURL(
148+
instance=known_instances["ember-dandi"],
149+
dandiset_id="000029",
150+
version_id=None,
151+
),
152+
),
153+
(
154+
"EMBER-DANDI-SANDBOX:000029/draft",
155+
DandisetURL(
156+
instance=known_instances["ember-dandi-sandbox"],
157+
dandiset_id="000029",
158+
version_id="draft",
159+
),
160+
),
120161
(
121162
"http://localhost:8000/api/dandisets/000002/",
122163
DandisetURL(

dandi/tests/test_helptext.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def get_helptext(command):
1313

1414
def test_resource_identifier_helptext():
1515
# The \n chars must be included for correct rendering
16-
correct = "Accepted resource identifier patterns:\n - DANDI:<dandiset id>[/<version>]\n"
16+
correct = "Accepted resource identifier patterns:\n - <INSTANCE>:<dandiset id>[/<version>]\n"
1717

1818
ls_helptext = get_helptext(['dandi', 'ls'])
1919
assert correct in ls_helptext

dandi/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,8 @@ def get_instance(dandi_instance_id: str | DandiInstance) -> DandiInstance:
577577
dandi_id = dandi_instance_id
578578
instance = known_instances[dandi_id]
579579
if dandi_id == "dandi-staging":
580-
lgr.warning(
581-
"'dandi-staging' DANDI instance identifier is deprecated. "
580+
raise ValueError(
581+
"'dandi-staging' DANDI instance identifier was removed. "
582582
"The instance was renamed into 'dandi-sandbox', please use that identifier instead."
583583
)
584584
if redirector_url is None:

docs/source/cmdline/instances.rst

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,15 @@ Example output:
2222
dandi-sandbox:
2323
api: https://api.sandbox.dandiarchive.org/api
2424
gui: https://sandbox.dandiarchive.org
25-
dandi-staging:
26-
api: https://api.sandbox.dandiarchive.org/api
27-
gui: https://sandbox.dandiarchive.org
2825
linc-staging:
2926
api: https://staging-api.lincbrain.org/api
3027
gui: https://staging.lincbrain.org
3128
linc:
3229
api: https://api.lincbrain.org/api
3330
gui: https://lincbrain.org
34-
ember-sandbox:
31+
ember-dandi-sandbox:
3532
api: https://api-dandi-sandbox.emberarchive.org/api
3633
gui: https://apl-setup--ember-dandi-archive.netlify.app/
37-
ember:
34+
ember-dandi:
3835
api: https://api-dandi.emberarchive.org/api
3936
gui: https://dandi.emberarchive.org

docs/source/ref/urls.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ has one, and its draft version will be used otherwise.
1717
(case insensitive; ``version`` cannot be "draft") when it redirects
1818
to one of the other URL formats
1919

20-
- :samp:`DANDI:{dandiset-id}[/{version}]` (case insensitive)
21-
— Refers to a Dandiset on the main DANDI Archive instance named "dandi".
20+
- :samp:`{instance-name}:{dandiset-id}[/{version}]` (case insensitive,
21+
where ``instance-name`` is a known DANDI instance such as ``DANDI``,
22+
``DANDI-SANDBOX``, ``LINC``, ``EMBER``, etc.)
23+
— Refers to a Dandiset on the specified DANDI Archive instance.
2224
`parse_dandi_url()` converts this format to a `DandisetURL`.
2325

2426
- Any ``https://gui.dandiarchive.org/`` or

0 commit comments

Comments
 (0)