Source code for ewokscore.graph.schema
from typing import Dict, Union
import networkx
from packaging.version import parse as parse_version, Version
import logging
from .metadata import SchemaMetadata
from .update import from_v1_0_to_v1_1, v0_update
_VERSIONS = None
[docs]
def get_versions() -> Dict[Version, SchemaMetadata]:
global _VERSIONS
if _VERSIONS is not None:
return _VERSIONS
return {
parse_version("0.0"): SchemaMetadata(("0.0", "0.0.1"), v0_update),
parse_version("1.0"): SchemaMetadata(("0.1.0-rc", None), from_v1_0_to_v1_1),
parse_version("1.1"): SchemaMetadata(("0.1.0-rc", None), None),
}
# Major version: increment when changing the existing schema
# Minor version: increment when adding features or deprecating the existing schema
LATEST_VERSION = list(get_versions().keys())[-1]
# The default version may be set to something else if we don't want the latest version to be the default
DEFAULT_VERSION = LATEST_VERSION
logger = logging.getLogger(__name__)
[docs]
def normalize_schema_version(graph: Union[dict, networkx.Graph]):
if isinstance(graph, dict):
graph_metadata = graph["graph"]
else:
graph_metadata = graph.graph
schema_version = graph_metadata.get("schema_version", None)
if schema_version:
pversion = parse_version(schema_version)
else:
logger.info(
'Graph has no "schema_version": assume version "%s"', DEFAULT_VERSION
)
pversion = DEFAULT_VERSION
if pversion != LATEST_VERSION:
# This warning is given because an exception may occur before `update_graph_schema`
# is called due to the different schema version.
logger.warning(
'Graph schema version "%s" is not equal to the latest version "%s"',
pversion,
LATEST_VERSION,
)
graph_metadata["schema_version"] = str(pversion)
[docs]
def update_graph_schema(graph: networkx.DiGraph):
"""
Updates the graph description to a higher schema version or raises an
exception.
If the schema version is known it will provide library version bounds
in the exception message.
"""
schema_version = parse_version(graph.graph["schema_version"])
schema_metadata = get_versions().get(schema_version)
update_method = schema_metadata.update_method if schema_metadata else None
if not update_method:
raise GraphSchemaError(schema_version)
before = schema_version
try:
update_method(graph)
except Exception:
raise GraphSchemaError(schema_version)
else:
after = parse_version(graph.graph["schema_version"])
if before == after:
raise RuntimeError("graph conversion did not update the schema version")
if before > after:
raise RuntimeError("graph conversion did not increment the schema version")
[docs]
class GraphSchemaError(ValueError):
def __init__(self, schema_version: Version) -> None:
version_metadata = get_versions().get(schema_version)
if not version_metadata:
return super().__init__(
f'Graph schema version "{schema_version}" is either invalid or requires a newer library version: python3 -m pip install --upgrade ewokscore'
)
lbound, ubound = version_metadata.ewokscore_bounds
if not ubound:
return super().__init__(
f'Graph schema version "{schema_version}" requires another library version: python3 -m pip install "ewokscore>={lbound}"'
)
return super().__init__(
f'Graph schema version "{schema_version}" requires another library version: python3 -m pip install "ewokscore>={lbound},<{ubound}"`'
)