Skip to content

Commit e90e05b

Browse files
authored
Merge pull request #1276 from VisLab/fix_extras
Removed prerelease flag from schema loading
2 parents 9c70089 + 4ff470e commit e90e05b

17 files changed

Lines changed: 176 additions & 363 deletions

CHANGELOG.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22

33
## Enhancements
44

5-
### Prerelease library schemas can now partner with prerelease standard schemas
5+
### Prerelease schemas are now always included in version lookups
66

7-
Loading a library schema with `withStandard` pointing to a prerelease version of the standard schema (e.g. `withStandard="8.5.0"`) would fail with a `BAD_WITH_STANDARD` error because the `withStandard` partner lookup was always restricted to released schemas, with no way to opt in to prerelease partner resolution.
7+
Previously, loading a schema whose version existed only in the prerelease cache required passing `check_prerelease=True` through every layer of the loading API. This flag has been **removed** from all public functions (`load_schema_version`, `load_schema`, `from_string`, `from_dataframes`), all schema loader classes, and all internal helpers. Prerelease schemas are now found automatically whenever they are present in the cache.
88

99
**Changes:**
1010

11-
- `load_schema()` and `from_string()` in `hed_schema_io.py` now accept a `check_prerelease=False` parameter. When `True`, the `withStandard` partner schema is also searched in the prerelease cache.
12-
- `SchemaLoader` (base class) and all subclasses (`SchemaLoaderXML`, `SchemaLoaderWiki`, `SchemaLoaderJSON`, `SchemaLoaderDF`) accept and forward `check_prerelease`.
13-
- `check_schema_loading.py` (`hed_check_schema_loading` script and `run_loading_check()`) now automatically passes `check_prerelease=True` when loading schemas from a prerelease directory, so `test_all_prerelease_schemas` in `spec_tests` works correctly for library prereleases partnered with a prerelease standard.
11+
- Removed the `check_prerelease` parameter from `load_schema_version()`, `load_schema()`, `from_string()`, and `from_dataframes()` in `hed_schema_io.py`.
12+
- Removed the parameter from `SchemaLoader` (base class) and all subclasses (`SchemaLoaderXML`, `SchemaLoaderWiki`, `SchemaLoaderJSON`, `SchemaLoaderDF`).
13+
- `get_hed_version_path()` in `hed_cache.py` now always searches both regular and prerelease directories (regular first).
14+
- `get_hed_versions()` in `hed_cache.py` now defaults to `check_prerelease=True`. **This is a silent API change**: external callers that omitted `check_prerelease` will now receive prerelease versions. Internal callers that need released-only versions (compliance checker, `deprecatedFrom` validation, hedId comparison) explicitly pass `check_prerelease=False`.
15+
- Default schema version is now resolved dynamically from the cache (highest released version) instead of being hardcoded, so new schema releases no longer require a code change.
16+
- `check_schema_loading.py` simplified — removed `_is_prerelease_partner()` helper.
1417
- `run_loading_check()` now raises `ValueError` immediately for mutually exclusive flag combinations (`prerelease_only` + `exclude_prereleases`, or `library_filter` + `standard_only`), consistent with the existing CLI-level validation.
1518

1619
# Release 0.9.0 January 22, 2026

hed/schema/hed_cache.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,16 @@ def get_cache_directory(cache_folder=None) -> str:
7979
return HED_CACHE_DIRECTORY
8080

8181

82-
def get_hed_versions(local_hed_directory=None, library_name=None, check_prerelease=False) -> Union[list, dict]:
82+
def get_hed_versions(local_hed_directory=None, library_name=None, check_prerelease=True) -> Union[list, dict]:
8383
"""Get the HED versions in the HED directory.
8484
8585
Parameters:
8686
local_hed_directory (str): Directory to check for versions which defaults to hed_cache.
8787
library_name (str or None): An optional schema library name.
8888
None retrieves the standard schema only.
8989
Pass "all" to retrieve all standard and library schemas as a dict.
90-
check_prerelease (bool): If True, results can include prerelease schemas
90+
check_prerelease (bool): If True, results can include prerelease schemas.
91+
Pass False to get only released versions (used by compliance checks).
9192
9293
Returns:
9394
Union[list, dict]: List of version numbers or dictionary {library_name: [versions]}.
@@ -101,7 +102,7 @@ def get_hed_versions(local_hed_directory=None, library_name=None, check_prerelea
101102

102103
all_hed_versions = {}
103104
local_directories = [local_hed_directory]
104-
if check_prerelease and not local_hed_directory.endswith(prerelease_suffix):
105+
if check_prerelease and Path(local_hed_directory).name != "prerelease":
105106
local_directories.append(os.path.join(local_hed_directory, "prerelease"))
106107

107108
hed_files = []
@@ -134,25 +135,22 @@ def get_hed_versions(local_hed_directory=None, library_name=None, check_prerelea
134135
return all_hed_versions
135136

136137

137-
def get_hed_version_path(
138-
xml_version, library_name=None, local_hed_directory=None, check_prerelease=False
139-
) -> Union[str, None]:
138+
def get_hed_version_path(xml_version, library_name=None, local_hed_directory=None) -> Union[str, None]:
140139
"""Get HED XML file path in a directory. Only returns filenames that exist.
141140
142141
Parameters:
143-
library_name (str or None): Optional the schema library name.
144142
xml_version (str): Returns this version if it exists
143+
library_name (str or None): Optional the schema library name.
145144
local_hed_directory (str): Path to local HED directory. Defaults to HED_CACHE_DIRECTORY
146-
check_prerelease (bool): Also check for prerelease schemas
147145
148146
Returns:
149-
Union[str, None]: The path to the latest HED version the HED directory.
147+
Union[str, None]: The path to the requested HED version the HED directory.
150148
151149
"""
152150
if not local_hed_directory:
153151
local_hed_directory = HED_CACHE_DIRECTORY
154152

155-
hed_versions = get_hed_versions(local_hed_directory, library_name, check_prerelease)
153+
hed_versions = get_hed_versions(local_hed_directory, library_name)
156154
if not hed_versions or not xml_version:
157155
return None
158156
if xml_version in hed_versions:
@@ -161,11 +159,10 @@ def get_hed_version_path(
161159
if os.path.exists(regular_path):
162160
return regular_path
163161

164-
# If check_prerelease is True, also check prerelease directory
165-
if check_prerelease:
166-
prerelease_path = _create_xml_filename(xml_version, library_name, local_hed_directory, True)
167-
if os.path.exists(prerelease_path):
168-
return prerelease_path
162+
# Also check prerelease directory
163+
prerelease_path = _create_xml_filename(xml_version, library_name, local_hed_directory, True)
164+
if os.path.exists(prerelease_path):
165+
return prerelease_path
169166
return None
170167

171168

hed/schema/hed_schema_io.py

Lines changed: 30 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@
2222
MAX_MEMORY_CACHE = 40
2323

2424

25-
def load_schema_version(
26-
xml_version=None, xml_folder=None, check_prerelease=False
27-
) -> Union["HedSchema", "HedSchemaGroup"]:
25+
def load_schema_version(xml_version=None, xml_folder=None) -> Union["HedSchema", "HedSchemaGroup"]:
2826
"""Return a HedSchema or HedSchemaGroup extracted from xml_version
2927
3028
Parameters:
@@ -33,7 +31,6 @@ def load_schema_version(
3331
based on the output of HedSchema.get_formatted_version
3432
Basic format: `[schema_namespace:][library_name_]X.Y.Z`.
3533
xml_folder (str): Path to a folder containing schema.
36-
check_prerelease (bool): If True, check the prerelease directory for schemas.
3734
3835
Returns:
3936
Union[HedSchema, HedSchemaGroup]: The schema or schema group extracted.
@@ -53,19 +50,18 @@ def load_schema_version(
5350
if xml_version and isinstance(xml_version, list):
5451
xml_versions = parse_version_list(xml_version)
5552
schemas = [
56-
_load_schema_version(xml_version=version, xml_folder=xml_folder, check_prerelease=check_prerelease)
57-
for version in xml_versions.values()
53+
_load_schema_version(xml_version=version, xml_folder=xml_folder) for version in xml_versions.values()
5854
]
5955
if len(schemas) == 1:
6056
return schemas[0]
6157

6258
name = ",".join([schema.version for schema in schemas])
6359
return HedSchemaGroup(schemas, name=name)
6460
else:
65-
return _load_schema_version(xml_version=xml_version, xml_folder=xml_folder, check_prerelease=check_prerelease)
61+
return _load_schema_version(xml_version=xml_version, xml_folder=xml_folder)
6662

6763

68-
def load_schema(hed_path, schema_namespace=None, schema=None, name=None, check_prerelease=False) -> "HedSchema":
64+
def load_schema(hed_path, schema_namespace=None, schema=None, name=None) -> "HedSchema":
6965
"""Load a schema from the given file or URL path.
7066
7167
Parameters:
@@ -77,7 +73,6 @@ def load_schema(hed_path, schema_namespace=None, schema=None, name=None, check_p
7773
schema (HedSchema or None): A HED schema to merge this new file into
7874
It must be a with-standard schema with the same value.
7975
name (str or None): User supplied identifier for this schema
80-
check_prerelease (bool): If True, allow the partnered standard schema (withStandard) to be a prerelease version.
8176
8277
Returns:
8378
HedSchema: The loaded schema.
@@ -103,22 +98,21 @@ def load_schema(hed_path, schema_namespace=None, schema=None, name=None, check_p
10398
file_as_string,
10499
schema_format=os.path.splitext(hed_path.lower())[1],
105100
name=name,
106-
check_prerelease=check_prerelease,
107101
)
108102
elif hed_path.lower().endswith(".xml"):
109-
hed_schema = SchemaLoaderXML.load(hed_path, schema=schema, name=name, check_prerelease=check_prerelease)
103+
hed_schema = SchemaLoaderXML.load(hed_path, schema=schema, name=name)
110104
elif hed_path.lower().endswith(".mediawiki"):
111-
hed_schema = SchemaLoaderWiki.load(hed_path, schema=schema, name=name, check_prerelease=check_prerelease)
105+
hed_schema = SchemaLoaderWiki.load(hed_path, schema=schema, name=name)
112106
elif hed_path.lower().endswith(".json"):
113-
hed_schema = SchemaLoaderJSON.load(hed_path, schema=schema, name=name, check_prerelease=check_prerelease)
107+
hed_schema = SchemaLoaderJSON.load(hed_path, schema=schema, name=name)
114108
elif hed_path.lower().endswith(".tsv") or os.path.isdir(hed_path):
115109
if schema is not None:
116110
raise HedFileError(
117111
HedExceptions.INVALID_HED_FORMAT,
118112
"Cannot pass a schema to merge into spreadsheet loading currently.",
119113
filename=name,
120114
)
121-
hed_schema = SchemaLoaderDF.load_spreadsheet(filenames=hed_path, name=name, check_prerelease=check_prerelease)
115+
hed_schema = SchemaLoaderDF.load_spreadsheet(filenames=hed_path, name=name)
122116
else:
123117
raise HedFileError(HedExceptions.INVALID_EXTENSION, "Unknown schema extension", filename=hed_path)
124118

@@ -128,9 +122,7 @@ def load_schema(hed_path, schema_namespace=None, schema=None, name=None, check_p
128122
return hed_schema
129123

130124

131-
def from_string(
132-
schema_string, schema_format=".xml", schema_namespace=None, schema=None, name=None, check_prerelease=False
133-
) -> "HedSchema":
125+
def from_string(schema_string, schema_format=".xml", schema_namespace=None, schema=None, name=None) -> "HedSchema":
134126
"""Create a schema from the given string.
135127
136128
Parameters:
@@ -141,7 +133,6 @@ def from_string(
141133
schema (HedSchema or None): A HED schema to merge this new file into
142134
It must be a with-standard schema with the same value.
143135
name (str or None): User supplied identifier for this schema
144-
check_prerelease (bool): If True, allow the partnered standard schema (withStandard) to be a prerelease version.
145136
146137
Returns:
147138
HedSchema: The loaded schema.
@@ -162,17 +153,11 @@ def from_string(
162153
schema_string = schema_string.replace("\r\n", "\n")
163154

164155
if schema_format.endswith(".xml"):
165-
hed_schema = SchemaLoaderXML.load(
166-
schema_as_string=schema_string, schema=schema, name=name, check_prerelease=check_prerelease
167-
)
156+
hed_schema = SchemaLoaderXML.load(schema_as_string=schema_string, schema=schema, name=name)
168157
elif schema_format.endswith(".mediawiki"):
169-
hed_schema = SchemaLoaderWiki.load(
170-
schema_as_string=schema_string, schema=schema, name=name, check_prerelease=check_prerelease
171-
)
158+
hed_schema = SchemaLoaderWiki.load(schema_as_string=schema_string, schema=schema, name=name)
172159
elif schema_format.endswith(".json"):
173-
hed_schema = SchemaLoaderJSON.load(
174-
schema_as_string=schema_string, schema=schema, name=name, check_prerelease=check_prerelease
175-
)
160+
hed_schema = SchemaLoaderJSON.load(schema_as_string=schema_string, schema=schema, name=name)
176161
else:
177162
raise HedFileError(HedExceptions.INVALID_EXTENSION, f"Unknown schema extension {schema_format}", filename=name)
178163

@@ -181,15 +166,14 @@ def from_string(
181166
return hed_schema
182167

183168

184-
def from_dataframes(schema_data, schema_namespace=None, name=None, check_prerelease=False) -> "HedSchema":
169+
def from_dataframes(schema_data, schema_namespace=None, name=None) -> "HedSchema":
185170
"""Create a schema from the given string.
186171
187172
Parameters:
188173
schema_data (dict of str or None): A dict of DF_SUFFIXES:file_as_string_or_df
189174
Should have an entry for all values of DF_SUFFIXES.
190175
schema_namespace (str, None): The name_prefix all tags in this schema will accept.
191176
name (str or None): User supplied identifier for this schema
192-
check_prerelease (bool): If True, allow the partnered standard schema (withStandard) to be a prerelease version.
193177
194178
Returns:
195179
HedSchema: The loaded schema.
@@ -207,9 +191,7 @@ def from_dataframes(schema_data, schema_namespace=None, name=None, check_prerele
207191
HedExceptions.BAD_PARAMETERS, "Empty or non dict value passed to HedSchema.from_dataframes", filename=name
208192
)
209193

210-
hed_schema = SchemaLoaderDF.load_spreadsheet(
211-
schema_as_strings_or_df=schema_data, name=name, check_prerelease=check_prerelease
212-
)
194+
hed_schema = SchemaLoaderDF.load_spreadsheet(schema_as_strings_or_df=schema_data, name=name)
213195

214196
if schema_namespace:
215197
hed_schema.set_schema_prefix(schema_namespace=schema_namespace)
@@ -274,7 +256,7 @@ def parse_version_list(xml_version_list) -> dict:
274256

275257

276258
@functools.lru_cache(maxsize=MAX_MEMORY_CACHE)
277-
def _load_schema_version(xml_version=None, xml_folder=None, check_prerelease=False):
259+
def _load_schema_version(xml_version=None, xml_folder=None):
278260
"""Return specified version
279261
280262
Parameters:
@@ -284,7 +266,6 @@ def _load_schema_version(xml_version=None, xml_folder=None, check_prerelease=Fal
284266
The schema namespace must be the same and not repeated if loading multiple merged schemas.
285267
286268
xml_folder (str): Path to a folder containing schema.
287-
check_prerelease (bool): If True, check the prerelease directory for schemas.
288269
289270
Returns:
290271
Union[HedSchema, HedSchemaGroup]: The requested HedSchema object.
@@ -308,9 +289,7 @@ def _load_schema_version(xml_version=None, xml_folder=None, check_prerelease=Fal
308289
else:
309290
xml_versions = [""]
310291

311-
first_schema = _load_schema_version_sub(
312-
xml_versions[0], schema_namespace, xml_folder=xml_folder, check_prerelease=check_prerelease, name=name
313-
)
292+
first_schema = _load_schema_version_sub(xml_versions[0], schema_namespace, xml_folder=xml_folder, name=name)
314293
filenames = [os.path.basename(first_schema.filename)]
315294

316295
# Collect all duplicate issues for proper error reporting
@@ -321,7 +300,6 @@ def _load_schema_version(xml_version=None, xml_folder=None, check_prerelease=Fal
321300
version,
322301
schema_namespace,
323302
xml_folder=xml_folder,
324-
check_prerelease=check_prerelease,
325303
schema=first_schema,
326304
name=name,
327305
)
@@ -357,16 +335,14 @@ def _load_schema_version(xml_version=None, xml_folder=None, check_prerelease=Fal
357335
return first_schema
358336

359337

360-
def _load_schema_version_sub(
361-
xml_version, schema_namespace="", xml_folder=None, check_prerelease=False, schema=None, name=""
362-
):
363-
"""Return specified version(single version only for this one)
338+
def _load_schema_version_sub(xml_version, schema_namespace="", xml_folder=None, schema=None, name=""):
339+
"""Return specified version (single version only for this one).
364340
365341
Parameters:
366-
xml_version (str): HED version format string. Expected format: '[library_name_]X.Y.Z'
342+
xml_version (str): HED version format string. Expected format: '[library_name_]X.Y.Z'.
343+
If empty, the latest released standard schema version from the cache is used.
367344
schema_namespace (str): The prefix this will have
368345
xml_folder (str): Path to a folder containing schema
369-
check_prerelease (bool): If True, check the prerelease directory for schemas
370346
schema (HedSchema or None): A HED schema to merge this new file into.
371347
name (str): User supplied identifier for this schema
372348
@@ -381,7 +357,15 @@ def _load_schema_version_sub(
381357
- The prefix is invalid
382358
"""
383359
if not xml_version:
384-
xml_version = "8.4.0"
360+
versions = hed_cache.get_hed_versions(xml_folder, check_prerelease=False)
361+
if isinstance(versions, list) and versions:
362+
xml_version = versions[0]
363+
else:
364+
raise HedFileError(
365+
HedExceptions.FILE_NOT_FOUND,
366+
"No HED standard schema versions found in cache. Ensure schemas are installed or cached.",
367+
"",
368+
)
385369

386370
# Parse library name from version string before validation
387371
library_name = ""
@@ -402,16 +386,13 @@ def _load_schema_version_sub(
402386
version_to_validate,
403387
library_name=library_name,
404388
local_hed_directory=xml_folder,
405-
check_prerelease=check_prerelease,
406389
)
407390

408391
if hed_file_path:
409392
hed_schema = load_schema(hed_file_path, schema_namespace=schema_namespace, schema=schema, name=name)
410393
else:
411394
library_string = f"for library '{library_name}'" if library_name else ""
412-
known_versions = hed_cache.get_hed_versions(
413-
xml_folder, library_name=library_name if library_name else "all", check_prerelease=check_prerelease
414-
)
395+
known_versions = hed_cache.get_hed_versions(xml_folder, library_name=library_name if library_name else "all")
415396
raise HedFileError(
416397
HedExceptions.FILE_NOT_FOUND,
417398
f"HED version {library_string}: '{version_to_validate}' not found. Check {hed_cache.get_cache_directory(xml_folder)} for cache or https://github.com/hed-standard/hed-schemas/tree/main/library_schemas. "

0 commit comments

Comments
 (0)