Skip to content

Commit ebcdcfb

Browse files
committed
fixups
1 parent 01b12a8 commit ebcdcfb

File tree

7 files changed

+632
-395
lines changed

7 files changed

+632
-395
lines changed

examples/zep8_url_demo.py

Lines changed: 118 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# /// script
2+
# dependencies = [
3+
# "zarr",
4+
# "numpy",
5+
# "fsspec",
6+
# ]
7+
# ///
18
"""
29
ZEP 8 URL Syntax Demo
310
@@ -20,208 +27,158 @@
2027

2128
import zarr
2229
from zarr.core.url_syntax import URLParser, is_zep8_url
23-
from zarr.registry import get_store_adapter
2430
from zarr.storage import ZipStore
2531

2632

2733
def demo_basic_zep8() -> None:
2834
"""Demonstrate basic ZEP 8 URL syntax features."""
2935
print("=== Basic ZEP 8 URL Demo ===")
3036

31-
try:
32-
print("📝 Testing basic ZEP 8 URL formats")
33-
34-
# Memory store
35-
print("\n1. Memory store:")
36-
memory_url = "memory:"
37-
root = zarr.open_group(memory_url, mode="w")
38-
arr = root.create_array("test_data", shape=(10,), dtype="f4")
39-
arr[:] = np.random.random(10)
40-
print(f"✅ Created array via {memory_url}")
41-
print(f" Data shape: {arr.shape}, dtype: {arr.dtype}")
42-
43-
# File store
44-
print("\n2. File store:")
45-
with tempfile.TemporaryDirectory() as tmpdir:
46-
file_url = f"file:{tmpdir}/test.zarr"
47-
root2 = zarr.open_group(file_url, mode="w")
48-
arr2 = root2.create_array("persistent_data", shape=(20,), dtype="i4")
49-
arr2[:] = range(20)
50-
print(f"✅ Created array via {file_url}")
51-
print(f" Data: {list(arr2[:5])}... (first 5 elements)")
37+
print("📝 Testing basic ZEP 8 URL formats")
5238

53-
except Exception as e:
54-
print(f"❌ Demo failed: {e}")
39+
# Memory store
40+
print("\n1. Memory store:")
41+
memory_url = "memory:"
42+
root = zarr.open_group(memory_url, mode="w")
43+
arr = root.create_array("test_data", shape=(10,), dtype="f4")
44+
arr[:] = np.random.random(10)
45+
print(f"✅ Created array via {memory_url}")
46+
print(f" Data shape: {arr.shape}, dtype: {arr.dtype}")
47+
48+
# File store
49+
print("\n2. File store:")
50+
with tempfile.TemporaryDirectory() as tmpdir:
51+
file_url = f"file:{tmpdir}/test.zarr"
52+
root2 = zarr.open_group(file_url, mode="w")
53+
arr2 = root2.create_array("persistent_data", shape=(20,), dtype="i4")
54+
arr2[:] = range(20)
55+
print(f"✅ Created array via {file_url}")
56+
print(f" Data: {list(arr2[:5])}... (first 5 elements)")
5557

5658

5759
def demo_zip_chaining() -> None:
5860
"""Demonstrate ZIP file chaining with ZEP 8 URLs."""
5961
print("\n=== ZIP Chaining Demo ===")
6062

61-
try:
62-
print("📝 Creating ZIP file with zarr data, then accessing via ZEP 8 URL")
63-
64-
with tempfile.TemporaryDirectory() as tmpdir:
65-
zip_path = Path(tmpdir) / "data.zip"
66-
67-
# Step 1: Create ZIP file with zarr data
68-
print(f"Creating ZIP file at: {zip_path}")
69-
with ZipStore(str(zip_path), mode="w") as zip_store:
70-
root = zarr.open_group(zip_store, mode="w")
71-
72-
# Create sample datasets
73-
temps = root.create_array("temperatures", shape=(365,), dtype="f4")
74-
temps[:] = (
75-
20 + 10 * np.sin(np.arange(365) * 2 * np.pi / 365) + np.random.normal(0, 2, 365)
76-
)
77-
temps.attrs["units"] = "celsius"
78-
temps.attrs["description"] = "Daily temperature readings"
79-
80-
metadata = root.create_group("metadata")
81-
info = metadata.create_array("info", shape=(1,), dtype="U50")
82-
info[0] = "Weather data from ZIP demo"
83-
84-
print("✅ Created temperature data in ZIP file")
85-
print(f" Temperature range: {temps[:].min():.1f}°C to {temps[:].max():.1f}°C")
86-
87-
# Step 2: Access via ZEP 8 URL syntax
88-
print("\nAccessing ZIP data via ZEP 8 URL")
89-
zip_url = f"file:{zip_path}|zip:"
90-
root_read = zarr.open_group(zip_url, mode="r")
91-
92-
temps_read = root_read["temperatures"]
93-
info_read = root_read["metadata/info"]
94-
95-
print(f"✅ Successfully read via URL: {zip_url}")
96-
print(f" Temperature units: {temps_read.attrs['units']}")
97-
print(f" Description: {temps_read.attrs['description']}")
98-
print(f" Metadata: {info_read[0]}")
99-
print(f" Data integrity: {np.array_equal(temps[:], temps_read[:])}")
100-
101-
except ImportError as e:
102-
print(f"❌ Required dependencies missing: {e}")
103-
except Exception as e:
104-
print(f"❌ Demo failed: {e}")
63+
print("📝 Creating ZIP file with zarr data, then accessing via ZEP 8 URL")
10564

65+
with tempfile.TemporaryDirectory() as tmpdir:
66+
zip_path = Path(tmpdir) / "data.zip"
10667

107-
def demo_adapter_registry() -> None:
108-
"""Show available store adapters and their usage."""
109-
print("\n=== Store Adapter Registry Demo ===")
68+
# Step 1: Create ZIP file with zarr data
69+
print(f"Creating ZIP file at: {zip_path}")
70+
with ZipStore(str(zip_path), mode="w") as zip_store:
71+
root = zarr.open_group(zip_store, mode="w")
11072

111-
try:
112-
print("📋 Testing common store adapters:")
73+
# Create sample datasets
74+
temps = root.create_array("temperatures", shape=(365,), dtype="f4")
75+
temp_data = (
76+
20 + 10 * np.sin(np.arange(365) * 2 * np.pi / 365) + np.random.normal(0, 2, 365)
77+
)
78+
temps[:] = temp_data
79+
temps.attrs["units"] = "celsius"
80+
temps.attrs["description"] = "Daily temperature readings"
11381

114-
# Test builtin adapters
115-
builtin_adapters = ["memory", "file", "zip"]
82+
metadata = root.create_group("metadata")
83+
info = metadata.create_array("info", shape=(1,), dtype="U50")
84+
info[0] = "Weather data from ZIP demo"
11685

117-
for adapter_name in builtin_adapters:
118-
try:
119-
adapter_cls = get_store_adapter(adapter_name)
120-
print(f"✅ {adapter_name}: {adapter_cls.__name__}")
121-
except KeyError:
122-
print(f"❌ {adapter_name}: Not registered")
86+
print("✅ Created temperature data in ZIP file")
87+
print(f" Temperature range: {temps[:].min():.1f}°C to {temps[:].max():.1f}°C")
12388

124-
# Test optional adapters
125-
optional_adapters = ["icechunk", "ic", "s3", "gcs"]
126-
print("\n📋 Testing optional adapters:")
89+
# Step 2: Access via ZEP 8 URL syntax
90+
print("\nAccessing ZIP data via ZEP 8 URL")
91+
zip_url = f"file:{zip_path}|zip:"
92+
root_read = zarr.open_group(zip_url, mode="r")
12793

128-
for adapter_name in optional_adapters:
129-
try:
130-
adapter_cls = get_store_adapter(adapter_name)
131-
print(f"✅ {adapter_name}: {adapter_cls.__name__}")
132-
except KeyError:
133-
print(f"i {adapter_name}: Not available (requires additional packages)")
94+
temps_read = root_read["temperatures"]
95+
info_read = root_read["metadata/info"]
13496

135-
except Exception as e:
136-
print(f"❌ Demo failed: {e}")
97+
print(f"✅ Successfully read via URL: {zip_url}")
98+
print(f" Temperature units: {temps_read.attrs['units']}")
99+
print(f" Description: {temps_read.attrs['description']}")
100+
print(f" Metadata: {info_read[0]}")
101+
print(f" Data integrity: {np.array_equal(temp_data, temps_read[:])}")
137102

138103

139104
def demo_url_parsing() -> None:
140105
"""Demonstrate ZEP 8 URL parsing and validation."""
141106
print("\n=== URL Parsing Demo ===")
142107

143-
try:
144-
parser = URLParser()
145-
146-
test_urls = [
147-
"memory:",
148-
"file:/tmp/data.zarr",
149-
"file:/tmp/data.zip|zip:",
150-
"s3://bucket/data.zip|zip:|zarr3:",
151-
"memory:|icechunk:branch:main", # This would be rejected by icechunk adapter
152-
"/regular/file/path", # Not a ZEP 8 URL
153-
]
154-
155-
print("📝 Testing URL parsing:")
156-
157-
for url in test_urls:
158-
is_zep8 = is_zep8_url(url)
159-
print(f"\n URL: {url}")
160-
print(f" ZEP 8: {is_zep8}")
161-
162-
if is_zep8:
163-
try:
164-
segments = parser.parse(url)
165-
print(f" Segments: {len(segments)}")
166-
for i, seg in enumerate(segments):
167-
scheme_part = f"scheme={seg.scheme}" if seg.scheme else ""
168-
adapter_part = f"adapter={seg.adapter}" if seg.adapter else ""
169-
path_part = f"path='{seg.path}'" if seg.path else ""
170-
parts = [p for p in [scheme_part, adapter_part, path_part] if p]
171-
print(f" {i}: {', '.join(parts)}")
172-
except Exception as e:
173-
print(f" Parse error: {e}")
108+
parser = URLParser()
174109

175-
except Exception as e:
176-
print(f"❌ Demo failed: {e}")
110+
test_urls = [
111+
"memory:",
112+
"file:/tmp/data.zarr",
113+
"file:/tmp/data.zip|zip:",
114+
"s3://bucket/data.zip|zip:|zarr3:",
115+
"memory:|icechunk:branch:main", # This would be rejected by icechunk adapter
116+
"/regular/file/path", # Not a ZEP 8 URL
117+
]
118+
119+
print("📝 Testing URL parsing:")
120+
121+
for url in test_urls:
122+
is_zep8 = is_zep8_url(url)
123+
print(f"\n URL: {url}")
124+
print(f" ZEP 8: {is_zep8}")
125+
126+
if is_zep8:
127+
try:
128+
segments = parser.parse(url)
129+
print(f" Segments: {len(segments)}")
130+
for i, seg in enumerate(segments):
131+
scheme_part = f"scheme={seg.scheme}" if seg.scheme else ""
132+
adapter_part = f"adapter={seg.adapter}" if seg.adapter else ""
133+
path_part = f"path='{seg.path}'" if seg.path else ""
134+
parts = [p for p in [scheme_part, adapter_part, path_part] if p]
135+
print(f" {i}: {', '.join(parts)}")
136+
except Exception as e:
137+
print(f" Parse error: {e}")
177138

178139

179140
def demo_error_cases() -> None:
180141
"""Demonstrate common error cases and their handling."""
181142
print("\n=== Error Handling Demo ===")
182143

183-
try:
184-
print("🚫 Testing error cases:")
185-
186-
# Test 1: Invalid URL format
187-
print("\n1. Invalid URL formats:")
188-
invalid_urls = [
189-
"|invalid:start", # Starts with pipe
190-
"memory:|", # Ends with pipe
191-
"memory:||zip:", # Double pipe
192-
"", # Empty URL
193-
]
194-
195-
for url in invalid_urls:
196-
try:
197-
zarr.open_group(url, mode="r")
198-
print(f"❌ Should have failed: {url}")
199-
except Exception as e:
200-
print(f"✅ Correctly rejected: {url} -> {type(e).__name__}")
144+
print("🚫 Testing error cases:")
145+
146+
# Test 1: Invalid URL format
147+
print("\n1. Invalid URL formats:")
148+
invalid_urls = [
149+
"|invalid:start", # Starts with pipe
150+
"memory:|", # Ends with pipe
151+
"memory:||zip:", # Double pipe
152+
"", # Empty URL
153+
]
201154

202-
# Test 2: Unknown adapters
203-
print("\n2. Unknown adapters:")
155+
for url in invalid_urls:
204156
try:
205-
zarr.open_group("memory:|unknown_adapter:", mode="r")
206-
print("❌ Should have failed: unknown adapter")
157+
zarr.open_group(url, mode="r")
158+
print(f"❌ Should have failed: {url}")
207159
except Exception as e:
208-
print(f"✅ Correctly rejected unknown adapter -> {type(e).__name__}")
160+
print(f"✅ Correctly rejected: {url} -> {type(e).__name__}")
209161

210-
# Test 3: Fallback behavior
211-
print("\n3. Fallback to regular stores:")
212-
regular_urls = ["memory:", f"file:{tempfile.mkdtemp()}/fallback.zarr"]
162+
# Test 2: Unknown adapters
163+
print("\n2. Unknown adapters:")
164+
try:
165+
zarr.open_group("memory:|unknown_adapter:", mode="r")
166+
print("❌ Should have failed: unknown adapter")
167+
except Exception as e:
168+
print(f"✅ Correctly rejected unknown adapter -> {type(e).__name__}")
213169

214-
for url in regular_urls:
215-
try:
216-
root = zarr.open_group(url, mode="w")
217-
arr = root.create_array("data", shape=(5,), dtype="i4")
218-
arr[:] = [1, 2, 3, 4, 5]
219-
print(f"✅ Fallback works: {url}")
220-
except Exception as e:
221-
print(f"❌ Fallback failed: {url} -> {e}")
170+
# Test 3: Fallback behavior
171+
print("\n3. Fallback to regular stores:")
172+
regular_urls = ["memory:", f"file:{tempfile.mkdtemp()}/fallback.zarr"]
222173

223-
except Exception as e:
224-
print(f"❌ Demo failed: {e}")
174+
for url in regular_urls:
175+
try:
176+
root = zarr.open_group(url, mode="w")
177+
arr = root.create_array("data", shape=(5,), dtype="i4")
178+
arr[:] = [1, 2, 3, 4, 5]
179+
print(f"✅ Fallback works: {url}")
180+
except Exception as e:
181+
print(f"❌ Fallback failed: {url} -> {e}")
225182

226183

227184
if __name__ == "__main__":
@@ -230,7 +187,6 @@ def demo_error_cases() -> None:
230187

231188
demo_basic_zep8()
232189
demo_zip_chaining()
233-
demo_adapter_registry()
234190
demo_url_parsing()
235191
demo_error_cases()
236192

0 commit comments

Comments
 (0)