Skip to content

Commit

Permalink
fix typing in StacApiIO (#229)
Browse files Browse the repository at this point in the history
* fix stac_api_io types
* remove ignore-missing-imports
  • Loading branch information
Phil Varner authored Jun 8, 2022
1 parent e4b3bd3 commit 6841066
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 43 deletions.
22 changes: 10 additions & 12 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@ repos:
hooks:
- id: isort
name: isort (python)
# - repo: https://github.com/pre-commit/mirrors-mypy
# rev: v0.960
# hooks:
# - id: mypy
# files: ".*\\.py$"
# exclude: ^(docs/.*|tests/.*)$
# args:
# - --ignore-missing-imports
# additional_dependencies:
# - pystac
# - types-requests
# - types-python-dateutil
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.960
hooks:
- id: mypy
files: ".*\\.py$"
exclude: ^tests/.*$
additional_dependencies:
- pystac
- types-requests
- types-python-dateutil
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Added

- Significantly improved type hints
- lru_cache to several methods [#167](https://github.com/stac-utils/pystac-client/pull/167)
- Direct item GET via ogcapi-features, if conformant [#166](https://github.com/stac-utils/pystac-client/pull/166)
- `py.typed` for downstream type checking [#163](https://github.com/stac-utils/pystac-client/pull/163)
Expand Down
7 changes: 4 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import subprocess
import sys
from pathlib import Path
from typing import List

# -- Path setup --------------------------------------------------------------

Expand All @@ -16,7 +17,7 @@
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
sys.path.insert(0, str(Path(__file__).parent.parent.parent.resolve()))
from pystac_client import __version__ # noqa: E402
from pystac_client import __version__ # type: ignore # noqa: E402

git_branch = (
subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"])
Expand All @@ -34,7 +35,7 @@
package_description = "A Python client for the STAC and STAC-API specs"

# The full version, including alpha/beta/rc tags
version = re.fullmatch(r"^(\d+\.\d+\.\d).*$", __version__).group(1)
version = re.fullmatch(r"^(\d+\.\d+\.\d).*$", __version__).group(1) # type: ignore
release = __version__


Expand Down Expand Up @@ -92,7 +93,7 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
html_static_path: List[str] = []

# -- Options for intersphinx extension ---------------------------------------

Expand Down
5 changes: 3 additions & 2 deletions pystac_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def _supports_collections(self) -> bool:
)

def _conforms_to(self, conformance_class: ConformanceClasses) -> bool:
return self._stac_io.conforms_to(conformance_class)
return self._stac_io.conforms_to(conformance_class) # type: ignore

@classmethod
def from_dict(
Expand All @@ -122,7 +122,8 @@ def from_dict(
preserve_dict: bool = True,
) -> "Client":
try:
return super().from_dict(
# this will return a Client because we have used a StacApiIO instance
return super().from_dict( # type: ignore
d=d, href=href, root=root, migrate=migrate, preserve_dict=preserve_dict
)
except pystac.STACTypeError:
Expand Down
52 changes: 26 additions & 26 deletions pystac_client/stac_api_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import logging
import re
from copy import deepcopy
from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Union
from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional
from urllib.parse import urlparse

import pystac
Expand Down Expand Up @@ -50,33 +50,19 @@ def __init__(
# TODO - this should super() to parent class
self.session = Session()
self.session.headers.update(headers or {})
self.session.params.update(parameters or {})
self.session.params.update(parameters or {}) # type: ignore

self._conformance = conformance

def read_text(
self,
source: Union[str, Link],
*args: Any,
parameters: Optional[Dict[str, Any]] = None,
**kwargs: Any,
) -> str:
def read_text(self, source: pystac.link.HREF, *args: Any, **kwargs: Any) -> str:
"""Read text from the given URI.
Overwrites the default method for reading text from a URL or file to allow
:class:`urllib.request.Request` instances as input. This method also raises
any :exc:`urllib.error.HTTPError` exceptions rather than catching
them to allow us to handle different response status codes as needed.
"""
if isinstance(source, str):
href = source
if bool(urlparse(href).scheme):
return self.request(href, *args, parameters=parameters, **kwargs)
else:
with open(href) as f:
href_contents = f.read()
return href_contents
elif isinstance(source, Link):
if isinstance(source, Link):
link = source.to_dict()
href = link["href"]
# get headers and body from Link and add to request from simple STAC
Expand All @@ -93,13 +79,26 @@ def read_text(
# If "POST" use the body object that and respect the "merge" property.
link_body = link.get("body", {})
if method == "POST":
parameters = {**parameters, **link_body} if merge else link_body
parameters = (
{**(kwargs.get("parameters", {})), **link_body}
if merge
else link_body
)
else:
# parameters are already in the link href
parameters = {}

return self.request(
href, *args, method=method, headers=headers, parameters=parameters
href, method=method, headers=headers, parameters=parameters
)
else: # str or something that can be str'ed
href = str(source)
if bool(urlparse(href).scheme):
return self.request(href, *args, **kwargs)
else:
with open(href) as f:
href_contents = f.read()
return href_contents

def request(
self,
Expand Down Expand Up @@ -157,7 +156,7 @@ def write_text_to_href(self, href: str, *args: Any, **kwargs: Any) -> None:
def stac_object_from_dict(
self,
d: Dict[str, Any],
href: Optional[str] = None,
href: Optional[pystac.link.HREF] = None,
root: Optional["Catalog_Type"] = None,
preserve_dict: bool = True,
) -> "STACObject_Type":
Expand All @@ -181,27 +180,27 @@ def stac_object_from_dict(

# Merge common properties in case this is an older STAC object.
merge_common_properties(
d, json_href=href, collection_cache=collection_cache
d, json_href=str(href), collection_cache=collection_cache
)

info = identify_stac_object(d)
d = migrate_to_latest(d, info)

if info.object_type == pystac.STACObjectType.CATALOG:
result = pystac_client.client.Client.from_dict(
d, href=href, root=root, migrate=False, preserve_dict=preserve_dict
d, href=str(href), root=root, migrate=False, preserve_dict=preserve_dict
)
result._stac_io = self
return result

if info.object_type == pystac.STACObjectType.COLLECTION:
return pystac_client.collection_client.CollectionClient.from_dict(
d, href=href, root=root, migrate=False, preserve_dict=preserve_dict
d, href=str(href), root=root, migrate=False, preserve_dict=preserve_dict
)

if info.object_type == pystac.STACObjectType.ITEM:
return pystac.Item.from_dict(
d, href=href, root=root, migrate=False, preserve_dict=preserve_dict
d, href=str(href), root=root, migrate=False, preserve_dict=preserve_dict
)

raise ValueError(f"Unknown STAC object type {info.object_type}")
Expand Down Expand Up @@ -254,7 +253,8 @@ def conforms_to(self, conformance_class: ConformanceClasses) -> bool:
provides such an endpoint.
Args:
key : The ``ConformanceClasses`` key to check conformance against.
conformance_class : The ``ConformanceClasses`` key to check conformance
against.
Return:
bool: Indicates if the API conforms to the given spec or URI.
Expand Down

0 comments on commit 6841066

Please sign in to comment.