Skip to content

Commit 04f1873

Browse files
committed
links can be at any level
1 parent 37f5f87 commit 04f1873

File tree

4 files changed

+46
-15
lines changed

4 files changed

+46
-15
lines changed

tests/plugins/xcube/processors/test_mldataset.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
from xrlint.plugins.xcube.util import LevelInfo, LevelsMeta
1717
from xrlint.result import Message
1818

19-
# TODO: This tests requires zarr >=2, <3, because the test used fsspec's
20-
# memory filesystem, which is not async but zarr wants all filesystems
21-
# to be async now.
22-
2319

2420
class MultiLevelDatasetProcessorTest(TestCase):
2521
levels_name = "xrlint-test"

tests/plugins/xcube/test_util.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright © 2025 Brockmann Consult GmbH.
2+
# This software is distributed under the terms and conditions of the
3+
# MIT license (https://mit-license.org/).
4+
5+
from unittest import TestCase
6+
7+
from xrlint.plugins.xcube.util import is_absolute_path
8+
from xrlint.plugins.xcube.util import resolve_path
9+
10+
11+
class UtilTest(TestCase):
12+
def test_is_absolute_path(self):
13+
self.assertTrue(is_absolute_path("/home/forman"))
14+
self.assertTrue(is_absolute_path("//bcserver2/fs1"))
15+
self.assertTrue(is_absolute_path("file://home/forman"))
16+
self.assertTrue(is_absolute_path("s3://xcube-data"))
17+
self.assertTrue(is_absolute_path(r"C:\Users\Norman"))
18+
self.assertTrue(is_absolute_path(r"C:/Users/Norman"))
19+
self.assertTrue(is_absolute_path(r"C:/Users/Norman"))
20+
self.assertTrue(is_absolute_path(r"\\bcserver2\fs1"))
21+
22+
self.assertFalse(is_absolute_path(r"data"))
23+
self.assertFalse(is_absolute_path(r"./data"))
24+
self.assertFalse(is_absolute_path(r"../data"))
25+
26+
def test_resolve_path(self):
27+
self.assertEqual(
28+
"/home/forman/data", resolve_path("data", root_path="/home/forman")
29+
)
30+
self.assertEqual(
31+
"/home/forman/data", resolve_path("./data", root_path="/home/forman")
32+
)
33+
self.assertEqual(
34+
"/home/data", resolve_path("../data", root_path="/home/forman")
35+
)
36+
self.assertEqual("s3://opensr/test.zarr", resolve_path("s3://opensr/test.zarr"))

xrlint/plugins/xcube/processors/mldataset.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from xrlint.plugins.xcube.util import (
1616
LevelsMeta,
1717
attach_dataset_level_infos,
18-
norm_link_path,
18+
resolve_path,
1919
)
2020
from xrlint.processor import ProcessorOp
2121
from xrlint.result import Message
@@ -46,11 +46,11 @@ def preprocess(
4646
meta = LevelsMeta.from_value(json.load(stream))
4747

4848
# check for optional ".zgroup"
49-
if ".zgroup" in file_names:
50-
with fs.open(f"{fs_path}/.zgroup") as stream:
51-
group_props = json.load(stream)
49+
# if ".zgroup" in file_names:
50+
# with fs.open(f"{fs_path}/.zgroup") as stream:
51+
# group_props = json.load(stream)
5252

53-
level_paths, num_levels = parse_levels(fs, fs_path, file_names)
53+
level_paths, num_levels = parse_levels(fs, file_path, file_names)
5454

5555
engine = opener_options.pop("engine", "zarr")
5656

@@ -93,7 +93,7 @@ def parse_levels(
9393
if m is not None:
9494
level = int(m.group(1))
9595
link_path = fs.read_text(f"{dataset_path}/{file_name}")
96-
level_paths[level] = norm_link_path(dataset_path, link_path)
96+
level_paths[level] = resolve_path(link_path, root_path=dataset_path)
9797
# check for regular "<level>.zarr"
9898
m = level_pattern.match(file_name)
9999
if m is not None:

xrlint/plugins/xcube/util.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,10 @@ def get_spatial_size(
9595
return None
9696

9797

98-
def norm_link_path(dataset_path: str, link_path: str) -> str:
99-
if is_absolute_path(link_path):
100-
abs_level_path = link_path
101-
else:
102-
abs_level_path = f"{dataset_path}/{link_path}"
98+
def resolve_path(path: str, root_path: str | None = None) -> str:
99+
abs_level_path = path
100+
if root_path is not None and not is_absolute_path(path):
101+
abs_level_path = f"{root_path}/{path}"
103102
parts = abs_level_path.rstrip("/").replace("\\", "/").split("/")
104103
return "/".join(
105104
p

0 commit comments

Comments
 (0)