Skip to content

Use root _stac_io, regex for conformance #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Sep 20, 2021
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

- Improved performance when constructing `pystac.ItemCollection` objects.
- Relax `requests` dependency [#87](https://github.com/stac-utils/pystac-client/pull/87)
- Use regular expressions for checking conformance classes [#97](https://github.com/stac-utils/pystac-client/pull/97)

### Fixed

- `ItemSearch` now correctly handles times without a timezone specifier [#92](https://github.com/stac-utils/pystac-client/issues/92)
Expand Down
File renamed without changes.
12 changes: 2 additions & 10 deletions pystac_client/collection_client.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
from typing import (Iterable, Optional, TYPE_CHECKING)
from typing import (Iterable, TYPE_CHECKING)

import pystac
from pystac_client.conformance import ConformanceClasses
from pystac_client.item_search import ItemSearch

if TYPE_CHECKING:
from pystac.item import Item as Item_Type
from pystac.catalog import Catalog as Catalog_Type


class CollectionClient(pystac.Collection):
def __repr__(self):
return '<CollectionClient id={}>'.format(self.id)

def assert_conforms_to(self, conformance: ConformanceClasses) -> bool:
return self._stac_io.conforms_to(conformance)

@classmethod
def from_dict(cls, *args, root: Optional["Catalog_Type"] = None, **kwargs):
col = super().from_dict(*args, **kwargs)
if root is not None:
col._stac_io = root._stac_io
return col
return self.get_root()._stac_io.conforms_to(conformance)

def get_items(self) -> Iterable["Item_Type"]:
if self.assert_conforms_to(ConformanceClasses.COLLECTIONS):
Expand Down
24 changes: 14 additions & 10 deletions pystac_client/conformance.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""This module defines a :class:`ConformanceClass` class that can be used to check conformance to a spec based on the
"""This module defines a :class:`ConformanceClasses` class that can be used to check conformance to a spec based on the
presence of a conformance URI. Each instance has a single :attr:`ConformanceClass.uri` property that represents the
most up-to-date official conformance URI for that spec. Because the STAC API spec has been rapidly evolving, many APIs
publish other conformance URIs that were defined in previous iterations of the spec, or are defined by other entities.
Expand Down Expand Up @@ -29,18 +29,22 @@
"""
from enum import Enum

STAC_PREFIXES = ['https://api.stacspec.org/v1.0.0-beta.2', 'https://api.stacspec.org/v1.0.0-beta.1']
import re


class ConformanceClasses(Enum):
CORE = [f"{p}/core" for p in STAC_PREFIXES]
ITEM_SEARCH = [f"{p}/item-search" for p in STAC_PREFIXES]
CONTEXT = [f"{p}/item-search#context" for p in STAC_PREFIXES]
FIELDS = [f"{p}/item-search#fields" for p in STAC_PREFIXES]
SORT = [f"{p}/item-search#sort" for p in STAC_PREFIXES]
QUERY = [f"{p}/item-search#query" for p in STAC_PREFIXES]
FILTER = [f"{p}/item-search#filter" for p in STAC_PREFIXES]
COLLECTIONS = ['http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30']

stac_prefix = re.escape("https://api.stacspec.org/v1.0.")

# defined conformance classes regexes
CORE = fr"{stac_prefix}(.*){re.escape('/core')}"
ITEM_SEARCH = fr"{stac_prefix}(.*){re.escape('/item-search')}"
CONTEXT = fr"{stac_prefix}(.*){re.escape('/item-search#context')}"
FIELDS = fr"{stac_prefix}(.*){re.escape('/item-search#fields')}"
SORT = fr"{stac_prefix}(.*){re.escape('/item-search#sort')}"
QUERY = fr"{stac_prefix}(.*){re.escape('/item-search#query')}"
FILTER = fr"{stac_prefix}(.*){re.escape('/item-search#filter')}"
COLLECTIONS = re.escape("http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30")


CONFORMANCE_URIS = {c.name: c.value for c in ConformanceClasses}
9 changes: 6 additions & 3 deletions pystac_client/stac_api_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Union,
)
from urllib.parse import urlparse
import re
from requests import Request, Session

import pystac
Expand Down Expand Up @@ -236,12 +237,14 @@ def conforms_to(self, conformance_class: ConformanceClasses) -> bool:
if self._conformance is None:
return True

uris = CONFORMANCE_URIS.get(conformance_class.name, None)
class_regex = CONFORMANCE_URIS.get(conformance_class.name, None)

if uris is None:
if class_regex is None:
raise Exception(f"Invalid conformance class {conformance_class}")

if not any(uri in uris for uri in self._conformance):
pattern = re.compile(class_regex)

if not any(re.match(pattern, uri) for uri in self._conformance):
return False

return True
Expand Down
164 changes: 82 additions & 82 deletions tests/cassettes/test_cli/TestCLI.test_item_search[inprocess].yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,38 @@ interactions:
response:
body:
string: !!binary |
H4sIAAN/A2EC/82YUW/bNhDHv8pBe1xk2clL4Tc58ZwAcWZEHvYwFMOZOktsKZElaWde0e++oyzb
aucVQ4pWfjLA4x1/vP+RPOtjJPNoHFVSWO302sdGRFeRl14RD88Pw7BQWJNHu4NbXZmNJwvZMr2F
dPHA83Nywkrjpa7ZKyO0osSVInAGedBTZbRFBRWHyNEj7B1Wsi5gitaX4ISkWhAEqyPvoNTOUw6r
HfiS4GsgvL7Q9Vrbyi11NP4jKr03bpwkaOTAeRTOkBhoWyTb0WA4GMYr9h9cJ0JbYt//OVvyJmLX
7OxVTj992JDdta7s+fLyMtCG6kK6AW8oCRESXQiOGK8J/caSi0cJh0vC7rq0r/DW6G6Gr3cvSL9z
rO3bqyjs9s8tWbfXutkuB1ayfu84+R8jS4rHHal1KKSdCXWExigpQinUSROISSyt2XJIpDnIKlpV
B8eSHPBQSHQSluYEJ9Gnq8MyuRbutIynv3xS+kp1SvhX3iYXKbQzv2HZJsJp6bbmkKv2qxs9gITj
kvz+S3YDHU8QCp0jB7IyiiqqjzUvHTiy26a8vwG6S3liP9bxGWzW+ucz6HCq/dfTtDE6+vFx/15l
IrRSJEKwz2Qrpcp/wJJJWaw6KbyfTcZwj7bStfybNZ4pveILcSJ1xQUArBFcD0fDPkB5pkWhZIWe
OsTLMHzbDveRP0vYTeDzNOUMyqKEZ3JabcIsmIbpVgrpd5AKQa4XqR2fW1mTiq9jdd2Fzo4GeKRt
+E374Kv0SnZfdT15GMMcDeh1qMBcNvc5p/AhvNP+i8vih2He5GTCa1mpoOOJ97dslsHN3XQBWWuE
u+m8F6XZLXfo4zexCFp3IB/3FnjDfclhPhxl74MVuYGysRr5DmWaLafP8Dha9gGU444bwDhHqXZx
2a3Iu8YCd8HCt+QLStkjIN/RvmTEGv+NON/b4EmHrjWtiC8fvADWc+k8sPae0L3ixv6X4gtujb2G
Zyl075TnRN9TXprk5/J5kPwyMop1vUF1FjRtTJfFeU76lvNStG9Jz532lrS/w16jw5yqDtlTmqX8
UsP9bAnb4XDUS+/jV91eYr6cZONwTKTXNnx+WFrihxtkDZONrbnD4F6IW6E+UKWO1UZ1v79MnZUw
GsZzCh9cQovB3UX4T9iLvNJ8pu3DYgxPzUpcdmnBJ2OjwpcD7iKxIMuXkNWFxaoP2ALNlw3kjPvd
bgbfHjFu+U+o0kX06R8WRiU5DRMAAA==
H4sIAC8yNWEC/82YUW/bNhDHv8pBe2xk2c5L4TfZ8ZwMcWZYHvowFANNnSV2lMiRlD2vyHfvUZYc
tXOLIcUqv5K84493/ztS+hiINJgEheBGWbVzoebBTeCEk0jDy3YYVpKV6Jg5wkwVunJoINnEM4hX
D7Q+RcuN0E6okqwSZIbnbCsRrGY06LDQyjAJBblImWNwMtiKMoM5My4HywWWHMHPWnQWcmUdprA9
gssRvgVC+3NV7pQp7EYFk9+D3DltJ1HEtBhYx7jVyAfKZNF+NBgOhuGW7AfjiCuDZPsfVws6RGjr
k73K6Ke/KjTHxpQsD4fDQGksM2EHdKDIe4hUxsljuEPmKoM2HEXkLvKn69K+wloxezt8vXmG6oOl
3L6/Cfxp/9ijsadc18clx1KUf1oK/sfAoKRxi3LnhXTUXkdMaym4l0IZ1Y6IxOCOZtpA6jatvMnq
4CzJAQ35QEd+awpwFDzftNukituXbRz+7aLcFbIj4V/pmCRSaFZ+x7a1h5etG80xUu03D9qC+HKJ
3v2c3ELHErhk1qIFUWiJBZZnzQsLFs2+lvd3QHcpX9jPOr6ATbl+cwEdXrT/eprGRyd/VO7/l0y4
khK5d/ZZ2nIh0x+wZVSorei2UjV9mMCSaVA7mAqVirqI3BEefHN0X2Toh2EKFcpKdpv+3BoBo2G4
RN/lH1mZUqv1QuyBrmSWpVh06J7iJL6bL+F+sYH9cDjqh0roz5AeVhN4qneiSy7OjOCV9E2Ucssy
avuwMiozrOgD9jZF7e+gQqK1HerfkkUCt3fzFSTNJFBceykVMkstc+HbkI9DOe5APp5m4C1JsF0P
Y3jEPcpw3AdrxvSXQVxQUfdbJuSGdaju1/N4Avciy2GNVsmqDtvcLydp+p4Tc+7V0AMqo2edCeXI
dXjjZDNfw+No00ufdttuWSw304T6tCqFU8a/TzcGSYMgSphWpqRioRxTCPtAtfQ+EKVXPlVJN+HJ
eaItjbgXGWbbrgoXUxIhMwXF8h961iyk2lJ7pLuvoDcP0LMExsPRsA/QlB3pUyRMmZDHMO9e03f1
DNz5GYI/MCF6BKTQuZwQS/ZvxOVpDp6U/36KC1IlZ1fAeimcLWvvAT1lXJuvZXxFH2lOwVpw1Tvl
paSfKK8t5Zfi2ab8OiLKyrJi8iJoXE9dF+el1Dec15L7hvRStTek/RU7rTSMS1Ewhx28jR+eNcM9
YH0wPMzsoUP0y3rWXotJZXaMI7xj/pfW8/szz4w+kaXKgudPw+j5w6sTAAA=
headers:
Content-Encoding:
- gzip
Content-Length:
- '934'
- '956'
Content-Type:
- application/json
Date:
- Fri, 30 Jul 2021 04:24:35 GMT
- Sun, 05 Sep 2021 21:10:07 GMT
Strict-Transport-Security:
- max-age=15724800; includeSubDomains
Vary:
- Accept-Encoding
X-Azure-Ref:
- 0A38DYQAAAAA/N0b2nlw+Q7ggAREpoEUeQk9TMzFFREdFMDQwNgA5MjdhYmZhNi0xOWY2LTRhZjEtYTA5ZC1jOTU5ZDlhMWU2NDQ=
- 0LzI1YQAAAAAoppImIbPYT5D68jTvK0/2Qk9TMzFFREdFMDQxOAA5MjdhYmZhNi0xOWY2LTRhZjEtYTA5ZC1jOTU5ZDlhMWU2NDQ=
X-Cache:
- CONFIG_NOCACHE
status:
Expand All @@ -72,80 +72,80 @@ interactions:
response:
body:
string: !!binary |
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
headers:
Content-Encoding:
- gzip
Content-Length:
- '3355'
- '3354'
Content-Type:
- application/json
Date:
- Fri, 30 Jul 2021 04:24:36 GMT
- Sun, 05 Sep 2021 21:10:07 GMT
Strict-Transport-Security:
- max-age=15724800; includeSubDomains
Vary:
- Accept-Encoding
X-Azure-Ref:
- 0BH8DYQAAAABJb4sX768ES4zHaHuRSBavQk9TMzFFREdFMDQwNgA5MjdhYmZhNi0xOWY2LTRhZjEtYTA5ZC1jOTU5ZDlhMWU2NDQ=
- 0LzI1YQAAAACJga8tPDOQSroMhwpjppNzQk9TMzFFREdFMDQxOAA5MjdhYmZhNi0xOWY2LTRhZjEtYTA5ZC1jOTU5ZDlhMWU2NDQ=
X-Cache:
- CONFIG_NOCACHE
status:
Expand Down
Loading