Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions .devcontainer/dev_container.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,21 @@ FROM ${BASE_URL}
USER root

# We'll be running as a non-root user in a container and may want root permissions
RUN apt update && apt -y install nano ssh sudo && apt clean

# Install setup tools and dependencies
WORKDIR /app
COPY . /app
RUN pip install --upgrade pip setuptools && pip install .[dev]
RUN apt update && apt -y install --no-install-recommends nano ssh sudo && apt clean

# Set up user to match the host OS (https://stackoverflow.com/a/78621662/415551)
ARG HOST_USER
ARG HOST_UID
ARG HOST_GID

RUN addgroup --gid ${HOST_GID} ${HOST_USER} \
&& adduser --gecos "" --disabled-password --uid ${HOST_UID} --gid ${HOST_GID} ${HOST_USER} \
&& usermod -aG sudo ${HOST_USER} \
RUN addgroup --gid "${HOST_GID}" "${HOST_USER}" \
&& adduser --gecos "" --disabled-password --uid "${HOST_UID}" --gid "${HOST_GID}" "${HOST_USER}" \
&& usermod -aG sudo "${HOST_USER}" \
&& echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

ENV HOME /home/${HOST_USER}
ENV TMPDIR=/tmp
WORKDIR /home/${HOST_USER}

USER ${HOST_USER}
ENV PATH "/home/${HOST_USER}/.local/bin:$PATH"
4 changes: 2 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@
]
}
}
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Uncomment the next line to run commands after the container is created.
// "postCreateCommand": "cat /etc/os-release",
"postCreateCommand": "pip install --upgrade pip setuptools && pip install --no-cache-dir -e .[dev]"
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
Expand Down
4 changes: 2 additions & 2 deletions example/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,13 @@ def api_home(endpoint):


# add in some other endpoints.
@app.route("/")
@app.route("/", methods=["GET"])
def home():
return """This is an example OGC flask app.
See <a href="/ogc_full"> FULL </a> and <a href="/ogc"> PARTIAL </a> endpoints."""


@app.route("/layers/<layer>")
@app.route("/layers/<layer>", methods=["GET"])
def check_layers(layer):
match_object = re.match("[a-zA-Z0-9]+", layer)

Expand Down
6 changes: 3 additions & 3 deletions ogc/edr/edr_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from functools import wraps
from http import HTTPStatus
from datetime import datetime, timezone
from typing import Tuple, List, Dict, Any, Union, Callable
from typing import Tuple, List, Dict, Any, Callable

from traitlets import TraitError
from ogc import podpac as pogc
Expand Down Expand Up @@ -328,12 +328,12 @@ def get_collection_edr_query(
return pygeoedr.get_collection_edr_query(api, request, dataset, instance, query_type, location_id)

@staticmethod
def _temporal_extents(times: List[Union[np.datetime64, datetime]], trs: str | None) -> Dict[str, Any]:
def _temporal_extents(times: List[np.datetime64 | datetime], trs: str | None) -> Dict[str, Any]:
"""Get the temporal extents for the provided times and reference system.

Parameters
----------
times : List[Union[np.datetime64, datetime]]
times : List[np.datetime64 | datetime]
Times used to create the temporal extent.
trs : str | None
The reference system for the times.
Expand Down
10 changes: 5 additions & 5 deletions ogc/edr/test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def set_env_vars():
importlib.reload(settings)


@pytest.fixture()
@pytest.fixture
def layers() -> List[pogc.Layer]:
"""List of test layers.

Expand All @@ -74,7 +74,7 @@ def layers() -> List[pogc.Layer]:
return [layer1, layer2]


@pytest.fixture()
@pytest.fixture
def layers_no_instance() -> List[pogc.Layer]:
"""List of test layers without instances.

Expand All @@ -86,7 +86,7 @@ def layers_no_instance() -> List[pogc.Layer]:
return [layer3]


@pytest.fixture()
@pytest.fixture
def single_layer_cube_args() -> Dict[str, Any]:
"""Dictionary of valid request arguments that align to a single test layer cube request.

Expand All @@ -104,7 +104,7 @@ def single_layer_cube_args() -> Dict[str, Any]:
}


@pytest.fixture()
@pytest.fixture
def single_layer_cube_args_internal() -> Dict[str, Any]:
"""Dictionary of valid arguments that align to a single test layer request with internal pygeoapi keys.

Expand All @@ -123,7 +123,7 @@ def single_layer_cube_args_internal() -> Dict[str, Any]:
}


@pytest.fixture()
@pytest.fixture
def single_layer_cube_args_no_instance_internal() -> Dict[str, Any]:
"""Dictionary of valid arguments that align to a single non-instance test layer request with internal pygeoapi keys.

Expand Down
3 changes: 2 additions & 1 deletion ogc/edr/test/test_edr_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,12 +372,13 @@ def test_edr_routes_collection_query_invalid_bbox(layers: List[pogc.Layer], sing
single_layer_cube_args["bbox"] = "invalid"
request = mock_request(single_layer_cube_args)
edr_routes = EdrRoutes(layers=layers)
instance = next(iter(layers[0].time_instances()))

with pytest.raises(EDRException) as exception_info:
edr_routes.collection_query(
request,
collection_id=layers[0].group,
instance_id=next(iter(layers[0].time_instances())),
instance_id=instance,
query_type="cube",
)

Expand Down
8 changes: 4 additions & 4 deletions ogc/test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,16 +227,16 @@ def test_ogc_core_handle_wms_kv_get_capabilities_hierachical_layers():
root = lxml.etree.fromstring(response.encode("utf-8"))

layers = root.xpath(f".//{capability}/{layer}/{title}/text()")
assert {ogc.service_group_title} == set(layers)
assert set(layers) == {ogc.service_group_title}

layers = root.xpath(f".//{capability}/{layer}/{layer}/{title}/text()")
assert {layer_root.title, layer_nested.group_path[0]} == set(layers)
assert set(layers) == {layer_root.title, layer_nested.group_path[0]}

layers = root.xpath(f".//{capability}/{layer}/{layer}/{layer}/{title}/text()")
assert {layer_nested.group_path[1]} == set(layers)
assert set(layers) == {layer_nested.group_path[1]}

layers = root.xpath(f".//{capability}/{layer}/{layer}/{layer}/{layer}/{title}/text()")
assert {layer_nested.title} == set(layers)
assert set(layers) == {layer_nested.title}


def test_ogc_core_handle_wms_kv_get_capabilities_invalid_service():
Expand Down
2 changes: 1 addition & 1 deletion ogc/test/test_input_security.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def client():
ogc_instance = core.OGC(layers=[layer])
app = servers.FlaskServer(__name__, ogcs=[ogc_instance])
app.config["TESTING"] = True
yield app.test_client()
return app.test_client()


# ---------------------------------------------------------------------------
Expand Down
18 changes: 9 additions & 9 deletions ogc/test/test_input_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ogc import servers
from ogc import settings
from ogc import podpac as pogc
from ogc.settings import EDR_TIME_INSTANCE_DIMENSION
from ogc.settings import EDR_TIME_INSTANCE_DIMENSION, crs_84_uri_format

lat = np.linspace(90, -90, 11)
lon = np.linspace(-180, 180, 21)
Expand Down Expand Up @@ -73,7 +73,7 @@ def client():
"""
Create a test client for the Flask server.

Yields
Returns
------
client : FlaskClient
A test client for the Flask server.
Expand All @@ -84,7 +84,7 @@ def client():
# Create a FlaskServer instance
app = servers.FlaskServer(__name__, ogcs=[ogc])
app.config.update({"TESTING": True})
yield app.test_client()
return app.test_client()


def make_valid_ogc_wms_get_capabilities_args() -> dict:
Expand Down Expand Up @@ -332,7 +332,7 @@ def make_valid_ogc_edr_static_cube_args(layer: str) -> dict:
return {
"f": "CoverageJSON",
"bbox": "-180,-90,180,90",
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
"crs": crs_84_uri_format,
"parameter-name": layer,
"resolution-x": 512,
"resolution-y": 512,
Expand All @@ -355,7 +355,7 @@ def make_valid_ogc_edr_static_area_args(layer: str) -> dict:
return {
"f": "CoverageJSON",
"coords": "POLYGON((-180 90, -180 -90, 180 -90, 180 90, -180 90))",
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
"crs": crs_84_uri_format,
"parameter-name": layer,
"resolution-x": 512,
"resolution-y": 512,
Expand All @@ -378,7 +378,7 @@ def make_valid_ogc_edr_static_position_args(layer: str) -> dict:
return {
"f": "CoverageJSON",
"coords": "POINT(40 50)",
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
"crs": crs_84_uri_format,
"parameter-name": layer,
}

Expand All @@ -401,7 +401,7 @@ def make_valid_ogc_edr_instance_cube_args(layer: str, time: str) -> dict:
return {
"f": "CoverageJSON",
"bbox": "-180,-90,180,90",
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
"crs": crs_84_uri_format,
"datetime": time,
"parameter-name": layer,
"resolution-x": 512,
Expand All @@ -427,7 +427,7 @@ def make_valid_ogc_edr_instance_area_args(layer: str, time: str) -> dict:
return {
"f": "CoverageJSON",
"coords": "POLYGON((-180 90, -180 -90, 180 -90, 180 90, -180 90))",
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
"crs": crs_84_uri_format,
"datetime": time,
"parameter-name": layer,
"resolution-x": 512,
Expand All @@ -453,7 +453,7 @@ def make_valid_ogc_edr_instance_position_args(layer: str, time: str) -> dict:
return {
"f": "CoverageJSON",
"coords": "POINT(40 50)",
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
"crs": crs_84_uri_format,
"datetime": time,
"parameter-name": layer,
}
Expand Down
8 changes: 4 additions & 4 deletions ogc/test/test_servers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def client():
"""
Create a test client for the Flask server.

Yields
Returns
------
client : FlaskClient
A test client for the Flask server.
Expand All @@ -44,7 +44,7 @@ def client():
# Create a FlaskServer instance
app = servers.FlaskServer(__name__, ogcs=[ogc])
app.config.update({"TESTING": True})
yield app.test_client()
return app.test_client()


@pytest.fixture
Expand All @@ -54,7 +54,7 @@ def client_with_percent_and_caret_layer():
contains a % and a ^, mirroring real-world layer names such as
"Relative_humidity_[%]" and "Total_precipitation_[kg/(m^2)]".

Yields
Returns
------
client : FlaskClient
A test client for the Flask server.
Expand All @@ -75,7 +75,7 @@ def client_with_percent_and_caret_layer():
ogc = core.OGC(layers=[layer])
app = servers.FlaskServer(__name__, ogcs=[ogc])
app.config.update({"TESTING": True})
yield app.test_client()
return app.test_client()


@pytest.fixture
Expand Down
2 changes: 1 addition & 1 deletion ogc/wcs_response_1_0_0.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def coverage_offering(self, coverage):
xml += "\n".join(
[
" <wcs:requestResponseCRSs>{epsg}</wcs:requestResponseCRSs>".format(epsg=epsg.upper())
for epsg in list(settings.WCS_CRS.keys())
for epsg in settings.WCS_CRS.keys()
]
)
xml += """
Expand Down
2 changes: 1 addition & 1 deletion ogc/wms_request_1_3_0.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def validate(self):
lons = [self.bbox.lower_corner[0], self.bbox.upper_corner[0]]
lats = [self.bbox.lower_corner[1], self.bbox.upper_corner[1]]
bbox = lons + lats
if any([abs(round(x, 9)) > 20037508.342789244 for x in bbox]):
if any(abs(round(x, 9)) > 20037508.342789244 for x in bbox):
raise ogc_common.WCSException(
exception_code="InvalidParameterValue",
locator="BBOX",
Expand Down
6 changes: 3 additions & 3 deletions ogc/wms_response_1_3_0.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def coverage_layer(self, coverage: Coverage, depth: int) -> str:
None,
)
except AttributeError:
latest_lis_time = next((t for t in reversed(coverage.layer.valid_times)), None)
latest_lis_time = next((reversed(coverage.layer.valid_times)), None)

if latest_lis_time is not None:
# default to latest LIS time, if available
Expand Down Expand Up @@ -303,7 +303,7 @@ def _get_CRS_and_BoundingBox(self, depth=3):
"\n".join(
[
INDENT * depth + """<CRS>{epsg}</CRS>""".format(epsg=epsg.upper())
for epsg, bbox in list(settings.WMS_CRS.items())
for epsg, bbox in settings.WMS_CRS.items()
]
)
+ "\n"
Expand All @@ -329,7 +329,7 @@ def _get_CRS_and_BoundingBox(self, depth=3):
maxx=Capabilities._format_number(bbox["maxx"]),
maxy=Capabilities._format_number(bbox["maxy"]),
)
for epsg, bbox in list(settings.WMS_CRS.items())
for epsg, bbox in settings.WMS_CRS.items()
]
)
return output_text
Expand Down
4 changes: 2 additions & 2 deletions ogc/wmts/test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
)


@pytest.fixture()
@pytest.fixture
def layers() -> List[pogc.Layer]:
"""List of test layers.

Expand All @@ -47,7 +47,7 @@ def layers() -> List[pogc.Layer]:
return [layer1, layer2]


@pytest.fixture()
@pytest.fixture
def coverages() -> List[Coverage]:
"""List of coverages based on layers.

Expand Down
6 changes: 4 additions & 2 deletions ogc/wmts/test/test_wmts_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ def test_handle_wmts_kv_get_capabilities_from_ogc_core(layers: List[pogc.Layer])
}
response = ogc.handle_wmts_kv(args)
assert isinstance(response, str)
assert "Capabilities" in response and "wmts/1.0" in response
assert "Capabilities" in response
assert "wmts/1.0" in response


def test_handle_kv_get_capabilities(coverages: List[Coverage]):
Expand All @@ -71,7 +72,8 @@ def test_handle_kv_get_capabilities(coverages: List[Coverage]):
}
response = wmts_routes.handle_kv(args)
assert isinstance(response, str)
assert "Capabilities" in response and "wmts/1.0" in response
assert "Capabilities" in response
assert "wmts/1.0" in response


def test_handle_kv_get_capabilities_invalid_service(coverages: List[Coverage]):
Expand Down
Loading