From be238f2a0f6da3932f03329519f489b4feb5e125 Mon Sep 17 00:00:00 2001 From: "Peter A. Jonsson" Date: Sun, 5 Oct 2025 12:11:34 +0200 Subject: [PATCH] Move single-use imports from top level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python import times are noticeable during interactive use of CLI applications, so push the (near) single-use imports into the functions where they are used so the import cost is paid when calling the functions instead of when starting the CLI to print the help or do some other unrelated action. Timings on top of #1583 inside a Python:3.10-bookworm container. Before this change: $ uv run hyperfine --warmup 3 "python3 -c 'import pystac'" Benchmark 1: python3 -c 'import pystac' Time (mean ± σ): 67.2 ms ± 1.6 ms [User: 58.6 ms, System: 8.6 ms] Range (min … max): 62.5 ms … 69.9 ms 45 runs After this change: $ uv run hyperfine --warmup 3 "python3 -c 'import pystac'" Benchmark 1: python3 -c 'import pystac' Time (mean ± σ): 59.9 ms ± 1.5 ms [User: 52.0 ms, System: 7.8 ms] Range (min … max): 56.9 ms … 64.2 ms 48 runs --- CHANGELOG.md | 2 ++ pystac/__init__.py | 3 ++- pystac/asset.py | 9 ++++++--- pystac/catalog.py | 9 +++++++-- pystac/collection.py | 9 ++++++--- pystac/extensions/eo.py | 3 ++- pystac/extensions/file.py | 3 ++- pystac/extensions/grid.py | 3 ++- pystac/extensions/item_assets.py | 5 ++++- pystac/extensions/projection.py | 6 ++++-- pystac/extensions/raster.py | 3 ++- pystac/extensions/scientific.py | 6 ++++-- pystac/extensions/version.py | 3 ++- pystac/item.py | 3 ++- pystac/item_assets.py | 3 ++- pystac/item_collection.py | 9 ++++++--- pystac/layout.py | 9 ++++++--- pystac/link.py | 9 ++++++--- pystac/provider.py | 6 ++++-- pystac/serialization/migrate.py | 3 ++- pystac/stac_io.py | 13 +++++++------ pystac/stac_object.py | 6 ++++-- pystac/summaries.py | 11 +++++++---- pystac/utils.py | 9 ++++++--- pystac/validation/__init__.py | 3 ++- pystac/validation/local_validator.py | 11 ++++++++--- pystac/version.py | 4 ++-- 27 files changed, 109 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f2237dc7..b0e230bf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +- Speed up importing pystac ([#1584](https://github.com/stac-utils/pystac/pull/1584)) + ## [v1.14.1] - 2025-09-18 ### Fixed diff --git a/pystac/__init__.py b/pystac/__init__.py index 1fbbb8343..20be20f10 100644 --- a/pystac/__init__.py +++ b/pystac/__init__.py @@ -44,7 +44,6 @@ "set_stac_version", ] -import os import warnings from typing import Any @@ -199,6 +198,8 @@ def write_file( """ if stac_io is None: stac_io = StacIO.default() + import os + dest_href = None if dest_href is None else str(os.fspath(dest_href)) obj.save_object( include_self_link=include_self_link, dest_href=dest_href, stac_io=stac_io diff --git a/pystac/asset.py b/pystac/asset.py index 46d034bf7..32bbfadb8 100644 --- a/pystac/asset.py +++ b/pystac/asset.py @@ -1,13 +1,10 @@ from __future__ import annotations -import os import shutil from copy import copy, deepcopy -from html import escape from typing import TYPE_CHECKING, Any, Protocol, TypeVar from pystac import MediaType, STACError, common_metadata, utils -from pystac.html.jinja_env import get_jinja_env from pystac.utils import is_absolute_href, make_absolute_href, make_relative_href if TYPE_CHECKING: @@ -182,6 +179,10 @@ def __repr__(self) -> str: return f"" def _repr_html_(self) -> str: + from html import escape + + from pystac.html.jinja_env import get_jinja_env + jinja_env = get_jinja_env() if jinja_env: template = jinja_env.get_template("JSON.jinja2") @@ -259,6 +260,8 @@ def delete(self) -> None: Does not modify the asset. """ + import os + href = _absolute_href(self.href, self.owner, "delete") os.remove(href) diff --git a/pystac/catalog.py b/pystac/catalog.py index ae47787c0..aae2612f3 100644 --- a/pystac/catalog.py +++ b/pystac/catalog.py @@ -1,10 +1,8 @@ from __future__ import annotations import os -import warnings from collections.abc import Callable, Iterable, Iterator from copy import deepcopy -from itertools import chain from typing import ( TYPE_CHECKING, Any, @@ -521,6 +519,8 @@ def get_item(self, id: str, recursive: bool = False) -> Item | None: Return: Item or None: The item with the given ID, or None if not found. """ + import warnings + warnings.warn( "get_item is deprecated and will be removed in v2. " "Use next(self.get_items(id), None) instead", @@ -549,6 +549,8 @@ def get_items(self, *ids: str, recursive: bool = False) -> Iterator[Item]: (if recursive) all catalogs or collections connected to this catalog through child links. """ + from itertools import chain + items: Iterator[Item] if not recursive: items = map( @@ -615,6 +617,9 @@ def get_all_items(self) -> Iterator[Item]: catalogs or collections connected to this catalog through child links. """ + import warnings + from itertools import chain + warnings.warn( "get_all_items is deprecated and will be removed in v2", DeprecationWarning, diff --git a/pystac/collection.py b/pystac/collection.py index be8693d6c..536fd2830 100644 --- a/pystac/collection.py +++ b/pystac/collection.py @@ -1,6 +1,5 @@ from __future__ import annotations -import warnings from collections.abc import Iterable, Sequence from copy import deepcopy from datetime import datetime, timezone @@ -12,8 +11,6 @@ cast, ) -from dateutil import tz - import pystac from pystac import CatalogType, STACObjectType from pystac.asset import Asset, Assets @@ -257,6 +254,8 @@ def from_dict(d: dict[str, Any]) -> TemporalExtent: parsed_intervals: list[list[datetime | None]] = [] for i in d["interval"]: if isinstance(i, str): + import warnings + # d["interval"] is a list of strings, so we correct the list and # try again # https://github.com/stac-utils/pystac/issues/1221 @@ -384,6 +383,8 @@ def from_items( Extent: An Extent that spatially and temporally covers all of the given items. """ + from dateutil import tz + bounds_values: list[list[float]] = [ [float("inf")], [float("inf")], @@ -635,6 +636,8 @@ def from_dict( migrate: bool = True, preserve_dict: bool = True, ) -> C: + import warnings + from pystac.extensions.version import CollectionVersionExtension if migrate: diff --git a/pystac/extensions/eo.py b/pystac/extensions/eo.py index 4de7a0268..1f4b12249 100644 --- a/pystac/extensions/eo.py +++ b/pystac/extensions/eo.py @@ -2,7 +2,6 @@ from __future__ import annotations -import warnings from collections.abc import Iterable from typing import ( Any, @@ -386,6 +385,8 @@ def get_schema_uri(cls) -> str: @classmethod def get_schema_uris(cls) -> list[str]: + import warnings + warnings.warn( "get_schema_uris is deprecated and will be removed in v2", DeprecationWarning, diff --git a/pystac/extensions/file.py b/pystac/extensions/file.py index 61349ef83..b772123bf 100644 --- a/pystac/extensions/file.py +++ b/pystac/extensions/file.py @@ -2,7 +2,6 @@ from __future__ import annotations -import warnings from collections.abc import Iterable from typing import Any, Generic, Literal, TypeVar, cast @@ -370,6 +369,8 @@ def migrate( found_fields[asset_key] = values if found_fields: + import warnings + warnings.warn( f"Assets {list(found_fields.keys())} contain fields: " f"{list(set.union(*found_fields.values()))} which " diff --git a/pystac/extensions/grid.py b/pystac/extensions/grid.py index 112fe75cb..39bca99b1 100644 --- a/pystac/extensions/grid.py +++ b/pystac/extensions/grid.py @@ -3,7 +3,6 @@ from __future__ import annotations import re -import warnings from re import Pattern from typing import Any, Literal @@ -92,6 +91,8 @@ def get_schema_uri(cls) -> str: @classmethod def get_schema_uris(cls) -> list[str]: + import warnings + warnings.warn( "get_schema_uris is deprecated and will be removed in v2", DeprecationWarning, diff --git a/pystac/extensions/item_assets.py b/pystac/extensions/item_assets.py index 140207275..1743deed6 100644 --- a/pystac/extensions/item_assets.py +++ b/pystac/extensions/item_assets.py @@ -2,7 +2,6 @@ from __future__ import annotations -import warnings from typing import Any, Literal import pystac @@ -27,6 +26,8 @@ class AssetDefinition(ItemAssetDefinition): """ def __init__(cls, *args: Any, **kwargs: Any) -> None: + import warnings + warnings.warn( ( "``AssetDefinition`` is deprecated. " @@ -49,6 +50,8 @@ class ItemAssetsExtension(ExtensionManagementMixin[pystac.Collection]): collection: pystac.Collection def __init__(self, collection: pystac.Collection) -> None: + import warnings + warnings.warn( ( "The ``item_assets`` extension is deprecated. " diff --git a/pystac/extensions/projection.py b/pystac/extensions/projection.py index 4adf3dae2..a0979c995 100644 --- a/pystac/extensions/projection.py +++ b/pystac/extensions/projection.py @@ -2,8 +2,6 @@ from __future__ import annotations -import json -import warnings from collections.abc import Iterable from typing import ( Any, @@ -223,6 +221,8 @@ def crs_string(self) -> str | None: elif self.wkt2: return self.wkt2 elif self.projjson: + import json + return json.dumps(self.projjson) else: return None @@ -321,6 +321,8 @@ def get_schema_uri(cls) -> str: @classmethod def get_schema_uris(cls) -> list[str]: + import warnings + warnings.warn( "get_schema_uris is deprecated and will be removed in v2", DeprecationWarning, diff --git a/pystac/extensions/raster.py b/pystac/extensions/raster.py index ed239466f..0f59b45b6 100644 --- a/pystac/extensions/raster.py +++ b/pystac/extensions/raster.py @@ -2,7 +2,6 @@ from __future__ import annotations -import warnings from collections.abc import Iterable from typing import ( Any, @@ -716,6 +715,8 @@ def get_schema_uri(cls) -> str: @classmethod def get_schema_uris(cls) -> list[str]: + import warnings + warnings.warn( "get_schema_uris is deprecated and will be removed in v2", DeprecationWarning, diff --git a/pystac/extensions/scientific.py b/pystac/extensions/scientific.py index b0d7821e7..9f6316b70 100644 --- a/pystac/extensions/scientific.py +++ b/pystac/extensions/scientific.py @@ -7,9 +7,7 @@ from __future__ import annotations -import copy from typing import Any, Generic, Literal, TypeVar, cast -from urllib import parse import pystac from pystac.extensions.base import ( @@ -49,6 +47,8 @@ class ScientificRelType(StringEnum): def doi_to_url(doi: str) -> str: """Converts a DOI to the corresponding URL.""" + from urllib import parse + return DOI_URL_BASE + parse.quote(doi) @@ -72,6 +72,8 @@ def __repr__(self) -> str: return f"" def to_dict(self) -> dict[str, str | None]: + import copy + return copy.deepcopy({"doi": self.doi, "citation": self.citation}) @staticmethod diff --git a/pystac/extensions/version.py b/pystac/extensions/version.py index b74d3f4c9..b1ad6016d 100644 --- a/pystac/extensions/version.py +++ b/pystac/extensions/version.py @@ -2,7 +2,6 @@ from __future__ import annotations -import warnings from collections.abc import Generator from contextlib import contextmanager from typing import ( @@ -437,6 +436,8 @@ def ignore_deprecated() -> Generator[None]: """Context manager for suppressing the :class:`pystac.DeprecatedWarning` when creating a deprecated :class:`~pystac.Item` or :class:`~pystac.Collection` from a dictionary.""" + import warnings + with warnings.catch_warnings(): warnings.simplefilter("ignore", category=DeprecatedWarning) yield diff --git a/pystac/item.py b/pystac/item.py index f95c5a218..6a8bf4f53 100644 --- a/pystac/item.py +++ b/pystac/item.py @@ -1,6 +1,5 @@ from __future__ import annotations -import warnings from copy import copy, deepcopy from typing import TYPE_CHECKING, Any, TypeVar, cast @@ -419,6 +418,8 @@ def from_dict( migrate: bool = True, preserve_dict: bool = True, ) -> T: + import warnings + from pystac.extensions.version import ItemVersionExtension if preserve_dict: diff --git a/pystac/item_assets.py b/pystac/item_assets.py index 2260cdf0b..ab3a1fadb 100644 --- a/pystac/item_assets.py +++ b/pystac/item_assets.py @@ -6,7 +6,6 @@ from __future__ import annotations -from copy import deepcopy from typing import TYPE_CHECKING, Any import pystac @@ -179,6 +178,8 @@ def roles(self, v: list[str] | None) -> None: def to_dict(self) -> dict[str, Any]: """Returns a dictionary representing this ``ItemAssetDefinition``.""" + from copy import deepcopy + return deepcopy(self.properties) def create_asset(self, href: str) -> pystac.Asset: diff --git a/pystac/item_collection.py b/pystac/item_collection.py index 5bf82c649..30634157d 100644 --- a/pystac/item_collection.py +++ b/pystac/item_collection.py @@ -1,8 +1,6 @@ from __future__ import annotations from collections.abc import Collection, Iterable, Iterator -from copy import deepcopy -from html import escape from typing import ( Any, TypeAlias, @@ -11,7 +9,6 @@ import pystac from pystac.errors import STACTypeError -from pystac.html.jinja_env import get_jinja_env from pystac.serialization.identify import identify_stac_object_type from pystac.utils import HREF, is_absolute_href, make_absolute_href, make_posix_style @@ -147,6 +144,10 @@ def to_dict(self, transform_hrefs: bool = False) -> dict[str, Any]: } def _repr_html_(self) -> str: + from html import escape + + from pystac.html.jinja_env import get_jinja_env + jinja_env = get_jinja_env() if jinja_env: template = jinja_env.get_template("JSON.jinja2") @@ -158,6 +159,8 @@ def clone(self) -> ItemCollection: """Creates a clone of this instance. This clone is a deep copy; all :class:`~pystac.Item` instances are cloned and all additional top-level fields are deep copied.""" + from copy import deepcopy + return self.__class__( items=[item.clone() for item in self.items], extra_fields=deepcopy(self.extra_fields), diff --git a/pystac/layout.py b/pystac/layout.py index 88c963d12..b36668488 100644 --- a/pystac/layout.py +++ b/pystac/layout.py @@ -1,12 +1,9 @@ from __future__ import annotations -import os import posixpath -import warnings from abc import ABC, abstractmethod from collections import OrderedDict from collections.abc import Callable -from string import Formatter from typing import TYPE_CHECKING, Any import pystac @@ -30,6 +27,8 @@ class TemplateError(Exception): """ def __init__(self, *args, **kwargs) -> None: # type: ignore + import warnings + warnings.warn( message=( "TemplateError in pystac.layout is deprecated and will be " @@ -109,6 +108,8 @@ class LayoutTemplate: ITEM_TEMPLATE_VARS = ["date", "year", "month", "day", "collection"] def __init__(self, template: str, defaults: dict[str, str] | None = None) -> None: + from string import Formatter + self.template = template self.defaults = defaults or {} @@ -261,6 +262,8 @@ class HrefLayoutStrategy(ABC): def get_href( self, stac_object: STACObject, parent_dir: str, is_root: bool = False ) -> str: + import os + if is_file_path(parent_dir): parent_dir = os.path.dirname(parent_dir) diff --git a/pystac/link.py b/pystac/link.py index 7b1cc4a0d..797f053e4 100644 --- a/pystac/link.py +++ b/pystac/link.py @@ -1,13 +1,10 @@ from __future__ import annotations import os -from copy import copy -from html import escape from typing import TYPE_CHECKING, Any, TypeVar import pystac from pystac.errors import STACError -from pystac.html.jinja_env import get_jinja_env from pystac.utils import ( HREF as HREF, ) @@ -272,6 +269,10 @@ def __repr__(self) -> str: return f"" def _repr_html_(self) -> str: + from html import escape + + from pystac.html.jinja_env import get_jinja_env + jinja_env = get_jinja_env() if jinja_env: template = jinja_env.get_template("JSON.jinja2") @@ -435,6 +436,8 @@ def from_dict(cls: type[L], d: dict[str, Any]) -> L: Returns: Link: Link instance constructed from the dict. """ + from copy import copy + d = copy(d) rel = d.pop("rel") href = d.pop("href") diff --git a/pystac/provider.py b/pystac/provider.py index 4152a28be..4db1f9174 100644 --- a/pystac/provider.py +++ b/pystac/provider.py @@ -1,7 +1,5 @@ -from html import escape from typing import Any -from pystac.html.jinja_env import get_jinja_env from pystac.utils import StringEnum @@ -73,6 +71,10 @@ def __eq__(self, o: object) -> bool: return self.to_dict() == o.to_dict() def _repr_html_(self) -> str: + from html import escape + + from pystac.html.jinja_env import get_jinja_env + jinja_env = get_jinja_env() if jinja_env: template = jinja_env.get_template("JSON.jinja2") diff --git a/pystac/serialization/migrate.py b/pystac/serialization/migrate.py index 8b1871bd2..4ed267437 100644 --- a/pystac/serialization/migrate.py +++ b/pystac/serialization/migrate.py @@ -1,7 +1,6 @@ from __future__ import annotations from collections.abc import Callable -from copy import deepcopy from typing import TYPE_CHECKING, Any import pystac @@ -167,6 +166,8 @@ def migrate_to_latest( dict: A copy of the dict that is migrated to the latest version (the version that is pystac.version.STACVersion.DEFAULT_STAC_VERSION) """ + from copy import deepcopy + result = deepcopy(json_dict) version = info.version_range.latest_valid_version() diff --git a/pystac/stac_io.py b/pystac/stac_io.py index d194a8283..1436d7ffc 100644 --- a/pystac/stac_io.py +++ b/pystac/stac_io.py @@ -1,13 +1,10 @@ from __future__ import annotations import json -import logging import os from abc import ABC, abstractmethod from collections.abc import Callable from typing import TYPE_CHECKING, Any -from urllib.error import HTTPError -from urllib.request import Request, urlopen import pystac from pystac.serialization import ( @@ -37,9 +34,6 @@ from pystac.stac_object import STACObject -logger = logging.getLogger(__name__) - - class StacIO(ABC): _default_io: Callable[[], StacIO] | None = None @@ -296,6 +290,11 @@ def read_text_from_href(self, href: str) -> str: """ href_contents: str if _is_url(href): + import logging + from urllib.error import HTTPError + from urllib.request import Request, urlopen + + logger = logging.getLogger(__name__) try: logger.debug(f"GET {href} Headers: {self.headers}") if HAS_URLLIB3: @@ -451,6 +450,8 @@ def read_text_from_href(self, href: str) -> str: href : The URI of the file to open. """ if _is_url(href): + from urllib.error import HTTPError + # TODO provide a pooled StacIO to enable more efficient network # access (probably named `PooledStacIO`). http = PoolManager() diff --git a/pystac/stac_object.py b/pystac/stac_object.py index c95c83948..81545faf7 100644 --- a/pystac/stac_object.py +++ b/pystac/stac_object.py @@ -2,12 +2,10 @@ from abc import ABC, abstractmethod from collections.abc import Callable, Iterable -from html import escape from typing import TYPE_CHECKING, Any, TypeAlias, TypeVar, cast import pystac from pystac import STACError -from pystac.html.jinja_env import get_jinja_env from pystac.link import Link from pystac.utils import ( HREF, @@ -584,6 +582,10 @@ def to_dict( raise NotImplementedError def _repr_html_(self) -> str: + from html import escape + + from pystac.html.jinja_env import get_jinja_env + jinja_env = get_jinja_env() if jinja_env: template = jinja_env.get_template("JSON.jinja2") diff --git a/pystac/summaries.py b/pystac/summaries.py index 1e3998008..c3b9715bf 100644 --- a/pystac/summaries.py +++ b/pystac/summaries.py @@ -1,11 +1,7 @@ from __future__ import annotations -import importlib.resources -import json -import numbers from abc import abstractmethod from collections.abc import Iterable -from copy import deepcopy from enum import Enum from functools import lru_cache from typing import ( @@ -100,6 +96,9 @@ def __repr__(self) -> str: @lru_cache(maxsize=None) def _get_fields_json(url: str | None) -> dict[str, Any]: if url is None: + import importlib.resources + import json + # Every time pystac is released this file gets pulled from # https://cdn.jsdelivr.net/npm/@radiantearth/stac-fields/fields-normalized.json jsonfields: dict[str, Any] = json.loads( @@ -170,6 +169,8 @@ def _set_field_definitions(self, fields: dict[str, Any]) -> None: self.summaryfields[name] = strategy def _update_with_item(self, summaries: Summaries, item: Item) -> None: + import numbers + for k, v in item.properties.items(): if k in self.summaryfields: strategy = self.summaryfields[k] @@ -310,6 +311,8 @@ def clone(self) -> Summaries: Returns: Summaries: The clone of this object """ + from copy import deepcopy + cls = self.__class__ summaries = cls(summaries=deepcopy(self._summaries), maxcount=self.maxcount) summaries.lists = deepcopy(self.lists) diff --git a/pystac/utils.py b/pystac/utils.py index 4225fd1d5..623ea4889 100644 --- a/pystac/utils.py +++ b/pystac/utils.py @@ -2,7 +2,6 @@ import os import posixpath -import warnings from collections.abc import Callable from datetime import datetime, timezone from enum import Enum @@ -15,8 +14,6 @@ from urllib.parse import ParseResult as URLParseResult from urllib.parse import urljoin, urlparse, urlunparse -import dateutil.parser - from pystac.errors import RequiredPropertyMissing #: HREF string or path-like object. @@ -132,6 +129,8 @@ def from_parsed_uri(parsed_uri: URLParseResult) -> JoinType: Returns: JoinType : The join type for the URI. """ + import warnings + warnings.warn( message=( "from_parsed_uri is deprecated and will be removed in pystac " @@ -166,6 +165,8 @@ def join_path_or_url(join_type: JoinType, *args: str) -> str: Returns: str : The joined path """ + import warnings + warnings.warn( message=( "join_path_or_url is deprecated and will be removed in pystac " @@ -432,6 +433,8 @@ def str_to_datetime(s: str) -> datetime: Returns: str: The :class:`datetime.datetime` represented the by the string. """ + import dateutil.parser + return dateutil.parser.isoparse(s) diff --git a/pystac/validation/__init__.py b/pystac/validation/__init__.py index 4b9be8269..f48629c62 100644 --- a/pystac/validation/__init__.py +++ b/pystac/validation/__init__.py @@ -1,6 +1,5 @@ from __future__ import annotations -import warnings from collections.abc import Iterable, Mapping from typing import TYPE_CHECKING, Any, cast @@ -164,6 +163,8 @@ def validate_all( stac_io = pystac.StacIO.default() if isinstance(stac_object, dict): + import warnings + warnings.warn( "validating a STAC object as a dict is deprecated;" " use validate_all_dict instead", diff --git a/pystac/validation/local_validator.py b/pystac/validation/local_validator.py index 88f2a7447..93a7e40aa 100644 --- a/pystac/validation/local_validator.py +++ b/pystac/validation/local_validator.py @@ -1,10 +1,7 @@ -import importlib.resources import json -import warnings from typing import Any, cast from jsonschema import Draft7Validator, ValidationError -from referencing import Registry, Resource from pystac.errors import STACLocalValidationError from pystac.version import STACVersion @@ -13,6 +10,8 @@ def _read_schema(file_name: str) -> dict[str, Any]: + import importlib.resources + with ( importlib.resources.files("pystac.validation.jsonschemas") .joinpath(file_name) @@ -73,6 +72,8 @@ def get_local_schema_cache() -> dict[str, dict[str, Any]]: def __getattr__(name: str) -> Any: if name in deprecated_names: + import warnings + warnings.warn(f"{name} is deprecated and will be removed in v2.", FutureWarning) return globals()[f"_deprecated_{name}"] raise AttributeError(f"module {__name__} has no attribute {name}") @@ -81,6 +82,8 @@ def __getattr__(name: str) -> Any: class LocalValidator: def __init__(self) -> None: """DEPRECATED""" + import warnings + warnings.warn( "``LocalValidator`` is deprecated and will be removed in v2.", DeprecationWarning, @@ -88,6 +91,8 @@ def __init__(self) -> None: self.schema_cache = get_local_schema_cache() def registry(self) -> Any: + from referencing import Registry, Resource + return Registry().with_resources( [(k, Resource.from_contents(v)) for k, v in self.schema_cache.items()] ) diff --git a/pystac/version.py b/pystac/version.py index 2e5161947..1c54dcd94 100644 --- a/pystac/version.py +++ b/pystac/version.py @@ -1,5 +1,3 @@ -import os - __version__ = "1.14.1" """Library version""" @@ -21,6 +19,8 @@ def get_stac_version(cls) -> str: if cls._override_version is not None: return cls._override_version + import os + env_version = os.environ.get(cls.OVERRIDE_VERSION_ENV_VAR) if env_version is not None: return env_version