diff --git a/.github/workflows/build-and-release.yaml b/.github/workflows/build-and-release.yaml
index b464b69..4585084 100644
--- a/.github/workflows/build-and-release.yaml
+++ b/.github/workflows/build-and-release.yaml
@@ -52,7 +52,7 @@ jobs:
uses: actions/checkout@v4
- name: Setup python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
@@ -83,8 +83,8 @@ jobs:
if: "! contains(github.ref_name,'b') && matrix.os == 'ubuntu-20.04' && matrix.python-version == '3.8'"
run: |
source .venv/bin/activate
- coverage html -d dist/tests/
- rm dist/tests/.gitignore
+ coverage html -d target/docs/tests/
+ rm target/docs/tests/.gitignore
- name: Build package
if: "matrix.os == 'ubuntu-20.04' && matrix.python-version == '3.8'"
@@ -97,18 +97,38 @@ jobs:
run: |
source .venv/bin/activate
pip install -e .[doc]
- pdoc3 --html --output-dir dist/ rok4
- cp README.md CHANGELOG.md dist/
-
- - name: Upload packages, tests results and documentation
+ pdoc3 --html --output-dir target/docs/ rok4
+ cp docs/mkdocs.yml target/mkdocs.yml
+ cp -r docs/overrides target/
+ cp docs/unit-tests.md target/docs/unit-tests.md
+ cp docs/documentation.md target/docs/documentation.md
+ cp docs/README.hdr.md target/docs/README.md
+ cp docs/CHANGELOG.hdr.md target/docs/CHANGELOG.md
+ cp docs/CONTRIBUTING.hdr.md target/docs/CONTRIBUTING.md
+ sed "s#x.y.z#${{ github.ref_name }}#g" README.md >>target/docs/README.md
+ cat CHANGELOG.md >>target/docs/CHANGELOG.md
+ cat CONTRIBUTING.md >>target/docs/CONTRIBUTING.md
+
+ - name: Upload packages
if: "matrix.os == 'ubuntu-20.04' && matrix.python-version == '3.8'"
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: dist-py3
path: dist/
if-no-files-found: error
retention-days: 1
+ - name: Publish documentation
+ if: "! contains(github.ref_name,'b') && matrix.os == 'ubuntu-20.04' && matrix.python-version == '3.8'"
+ run: |
+ source .venv/bin/activate
+ pip install -r docs/requirements.txt
+ git config user.name github-actions
+ git config user.email github-actions@github.com
+ cd target/
+ mike deploy --push --update-aliases --branch gh-pages -t "Version ${{ github.ref_name }}" ${{ github.ref_name }} latest
+ mike set-default --push --branch gh-pages ${{ github.ref_name }}
+
publish_artefacts:
name: Add built artefacts to release and PyPI
needs: [create_release, build_and_test]
@@ -117,7 +137,7 @@ jobs:
steps:
- - uses: actions/download-artifact@v3
+ - uses: actions/download-artifact@v4
with:
name: dist-py3
path: dist/
@@ -155,56 +175,6 @@ jobs:
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: to_publish/
- commit_documentation:
- name: Add documentation and unit tests results into gh-pages branch
- needs: build_and_test
- if: "always() && ! contains(github.ref_name,'b') && needs.create_release.outputs.job_status == 'success' && needs.build_and_test.outputs.job_status == 'success'"
- runs-on: ubuntu-latest
-
- steps:
-
- - name: Checkout project on gh-pages
- uses: actions/checkout@v4
- with:
- ref: 'gh-pages'
- token: ${{ secrets.GITHUB_TOKEN }}
-
- - uses: actions/download-artifact@v3
- with:
- name: dist-py3
- path: artifact/
-
- - name: Copy version elements to final location
- run: |
- mkdir -p docs/versions/${{ github.ref_name }}
- cp -r artifact/rok4 docs/versions/${{ github.ref_name }}/
- cp -r artifact/tests docs/versions/${{ github.ref_name }}/
-
- - name: Add pages from templates
- run: |
- sed "s#__version__#${{ github.ref_name }}#" templates/mkdocs.template.yml >mkdocs.yml
-
- sed "s#__version__#${{ github.ref_name }}#" templates/unit-tests.template.md >docs/versions/${{ github.ref_name }}/unit-tests.md
- sed "s#__version__#${{ github.ref_name }}#" templates/documentation.template.md >docs/versions/${{ github.ref_name }}/documentation.md
-
- sed "s#__version__#${{ github.ref_name }}#" templates/index-version.template.md >docs/versions/${{ github.ref_name }}/index.md
- cat artifact/README.md >>docs/versions/${{ github.ref_name }}/index.md
- sed -i "s#x.y.z#${{ github.ref_name }}#g" docs/versions/${{ github.ref_name }}/index.md
-
- cp templates/index-versions.template.md docs/versions/index.md
- sed "s/^## \(.*\)$/## \1 \n\n[➔ Lien vers la documentation](\1\/index.md) /" artifact/CHANGELOG.md >>docs/versions/index.md
-
- sed "s#__version__#${{ github.ref_name }}#" templates/latest.template.html >docs/versions/latest/index.html
- rm -r artifact
-
- - name: Publish on gh-pages branch
- run: |
- git config user.name github-actions
- git config user.email github-actions@github.com
- git add -v docs/versions/${{ github.ref_name }}/ docs/versions/latest/ docs/versions/index.md mkdocs.yml
- git commit -m "Add documentation for version ${{ github.ref_name }}"
- git push
-
delete_version:
name: Remove release and tag if error occured
needs: build_and_test
diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml
deleted file mode 100644
index 53fd700..0000000
--- a/.github/workflows/build-docs.yaml
+++ /dev/null
@@ -1,67 +0,0 @@
-name: Build doc site with mkdocs and deploy
-
-on:
- workflow_dispatch:
-
-jobs:
-
- build:
-
- name: Build doc site with mkdocs
-
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout project
- uses: actions/checkout@v4
- with:
- ref: 'gh-pages'
- token: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Setup python
- uses: actions/setup-python@v4
- with:
- python-version: "3.10"
- cache: 'pip'
-
- - name: Install Mkdocs
- run: pip install -r requirements.txt
-
- - name: Run mkdocs and archive
- run : |
- mkdocs build
- tar \
- --dereference --hard-dereference \
- --directory "site" \
- -cvf "${{ runner.temp }}/site.tar" \
- --exclude=.git \
- --exclude=.github \
- .
-
- - name: Upload pages
- uses: actions/upload-artifact@main
- with:
- name: github-pages
- path: ${{ runner.temp }}/site.tar
- retention-days: 1
-
- deploy:
-
- name: Deploy site to github pages
-
- needs: build
-
- permissions:
- pages: write # to deploy to Pages
- id-token: write # to verify the deployment originates from an appropriate source
-
- # Deploy to the github-pages environment
- environment:
- name: github-pages
- url: ${{ steps.deployment.outputs.page_url }}
-
- runs-on: ubuntu-latest
- steps:
- - name: Deploy to GitHub Pages
- id: deployment
- uses: actions/deploy-pages@v2
diff --git a/.github/workflows/pr-auto-labeler.yml b/.github/workflows/pr-auto-labeler.yml
index 42ec571..a4c9c73 100644
--- a/.github/workflows/pr-auto-labeler.yml
+++ b/.github/workflows/pr-auto-labeler.yml
@@ -10,6 +10,6 @@ jobs:
triage:
runs-on: ubuntu-latest
steps:
- - uses: actions/labeler@v4
+ - uses: actions/labeler@v5
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31e31a0..f656d1b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+## 2.1.0
+
+### [Added]
+
+* Pyramid
+ * Ajout de fonctions pour récupérer la tile_limits et le nombre de canaux de cette pyramide
+ * Ajout de fonctions pour ajouter ou supprimer des niveaux dans une pyramide
+* TileMatrixSet
+ * Ajout de fonctions pour récupérer la hauteur et la largeur de tuiles d'un TileMatrixSet
+
+### [Changed]
+
+* Pyramid
+ * Ajout d'un paramètre optionnel "mask" pour le constructeur from other afin de pouvoir conserver ou non les masques de la pyramide servant de base à la nouvellle
+* Gestion des documentations des différentes versions avec l'outil [mike](https://github.com/jimporter/mike)
+
## 2.0.1
### [Added]
diff --git a/README.md b/README.md
index 2117b06..bad3a97 100644
--- a/README.md
+++ b/README.md
@@ -29,12 +29,14 @@ except Exception as exc:
Plus d'exemple dans la documentation développeur.
+
## Contribuer
* Installer les dépendances de développement :
```sh
python3 -m pip install -e .[dev]
+ pre-commit install
```
* Consulter les [directives de contribution](./CONTRIBUTING.md)
@@ -46,7 +48,7 @@ apt install python3-venv python3-rados python3-gdal
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade build bump2version
-bump2version --allow-dirty --current-version 0.0.0 --new-version x.y.z patch pyproject.toml src/rok4/__init__.py
+bump2version --current-version 0.0.0 --new-version x.y.z patch
# Run unit tests
python3 -m pip install -e .[test]
diff --git a/docs/CHANGELOG.hdr.md b/docs/CHANGELOG.hdr.md
new file mode 100644
index 0000000..e0257d2
--- /dev/null
+++ b/docs/CHANGELOG.hdr.md
@@ -0,0 +1,4 @@
+---
+hide:
+ - navigation
+---
diff --git a/docs/CONTRIBUTING.hdr.md b/docs/CONTRIBUTING.hdr.md
new file mode 100644
index 0000000..e0257d2
--- /dev/null
+++ b/docs/CONTRIBUTING.hdr.md
@@ -0,0 +1,4 @@
+---
+hide:
+ - navigation
+---
diff --git a/docs/README.hdr.md b/docs/README.hdr.md
new file mode 100644
index 0000000..e0257d2
--- /dev/null
+++ b/docs/README.hdr.md
@@ -0,0 +1,4 @@
+---
+hide:
+ - navigation
+---
diff --git a/docs/documentation.md b/docs/documentation.md
new file mode 100644
index 0000000..59f441e
--- /dev/null
+++ b/docs/documentation.md
@@ -0,0 +1,9 @@
+---
+hide:
+ - navigation
+ - toc
+---
+
+# Documentation technique
+
+
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
new file mode 100644
index 0000000..a173ee6
--- /dev/null
+++ b/docs/mkdocs.yml
@@ -0,0 +1,28 @@
+site_name: "Projet ROK4 - Librairies python"
+site_url: https://rok4.github.io/core-python
+
+nav:
+ - Accueil: README.md
+ - Documentation technique: documentation.md
+ - Rapport des tests unitaires: unit-tests.md
+ - Historique des versions: CHANGELOG.md
+ - Contribuer: CONTRIBUTING.md
+
+theme:
+ logo: https://rok4.github.io/assets/images/rok4-carre.png
+ favicon: https://rok4.github.io/assets/images/rok4-carre.png
+ name: material
+ features:
+ - navigation.tabs
+ - navigation.tabs.sticky
+ language: fr
+ custom_dir: overrides
+
+extra_css:
+ - https://rok4.github.io/assets/css/commun.css
+
+extra:
+ homepage: https://rok4.github.io
+ version:
+ provider: mike
+ default: latest
diff --git a/docs/overrides/main.html b/docs/overrides/main.html
new file mode 100644
index 0000000..7c55859
--- /dev/null
+++ b/docs/overrides/main.html
@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+
+{% block outdated %}
+ 🚨 Vous êtes sur la documentation d'une ancienne version. 🚨
+
+ Cliquez ici pour aller sur la dernière version.
+
+{% endblock %}
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..f5f7010
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,3 @@
+mkdocs
+mkdocs-material
+mike
diff --git a/docs/unit-tests.md b/docs/unit-tests.md
new file mode 100644
index 0000000..091c6bd
--- /dev/null
+++ b/docs/unit-tests.md
@@ -0,0 +1,9 @@
+---
+hide:
+ - navigation
+ - toc
+---
+
+# Rapport des tests unitaires
+
+
diff --git a/pyproject.toml b/pyproject.toml
index 9731107..3e9fcf9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -58,7 +58,7 @@ test = [
[project.urls]
"Homepage" = "https://rok4.github.io/core-python"
"Bug Reports" = "https://github.com/rok4/core-python/issues"
-"Changelog" = "https://rok4.github.io/core-python/versions/"
+"Changelog" = "https://rok4.github.io/core-python/latest/CHANGELOG/"
"Source" = "https://github.com/rok4/core-python"
[build-system]
diff --git a/src/rok4/pyramid.py b/src/rok4/pyramid.py
index f55433f..09ea0e4 100644
--- a/src/rok4/pyramid.py
+++ b/src/rok4/pyramid.py
@@ -331,6 +331,10 @@ def slab_width(self) -> int:
def slab_height(self) -> int:
return self.__slab_size[1]
+ @property
+ def tile_limits(self) -> Dict[str, int]:
+ return self.__tile_limits
+
def is_in_limits(self, column: int, row: int) -> bool:
"""Is the tile indices in limits ?
@@ -475,13 +479,14 @@ def from_descriptor(cls, descriptor: str) -> "Pyramid":
return pyramid
@classmethod
- def from_other(cls, other: "Pyramid", name: str, storage: Dict) -> "Pyramid":
+ def from_other(cls, other: "Pyramid", name: str, storage: Dict, **kwargs) -> "Pyramid":
"""Create a pyramid from another one
Args:
other (Pyramid): pyramid to clone
name (str): new pyramid's name
storage (Dict[str, Union[str, int]]): new pyramid's storage informations
+ **mask (bool) : Presence or not of mask (only for RASTER)
Raises:
FormatError: Provided path or the TMS is not a well formed JSON
@@ -493,7 +498,8 @@ def from_other(cls, other: "Pyramid", name: str, storage: Dict) -> "Pyramid":
"""
try:
# On convertit le type de stockage selon l'énumération
- storage["type"] = StorageType[storage["type"]]
+ if type(storage["type"]) is str:
+ storage["type"] = StorageType[storage["type"]]
if storage["type"] == StorageType.FILE and name.find("/") != -1:
raise Exception(f"A FILE stored pyramid's name cannot contain '/' : '{name}'")
@@ -519,7 +525,9 @@ def from_other(cls, other: "Pyramid", name: str, storage: Dict) -> "Pyramid":
# Attributs d'une pyramide raster
if pyramid.type == PyramidType.RASTER:
- if other.own_masks:
+ if "mask" in kwargs:
+ pyramid.__masks = kwargs["mask"]
+ elif other.own_masks:
pyramid.__masks = True
else:
pyramid.__masks = False
@@ -668,6 +676,10 @@ def own_masks(self) -> bool:
def format(self) -> str:
return self.__format
+ @property
+ def channels(self) -> str:
+ return self.raster_specifications["channels"]
+
@property
def tile_extension(self) -> str:
if self.__format in [
@@ -735,10 +747,14 @@ def load_list(self) -> None:
self.__content["loaded"] = True
- def list_generator(self) -> Iterator[Tuple[Tuple[SlabType, str, int, int], Dict]]:
+ def list_generator(
+ self, level_id: str = None
+ ) -> Iterator[Tuple[Tuple[SlabType, str, int, int], Dict]]:
"""Get list content
List is copied as temporary file, roots are read and informations about each slab is returned. If list is already loaded, we yield the cached content
+ Args :
+ level_id (str) : id of the level for load only one level
Examples:
@@ -776,7 +792,11 @@ def list_generator(self) -> Iterator[Tuple[Tuple[SlabType, str, int, int], Dict]
"""
if self.__content["loaded"]:
for slab, infos in self.__content["cache"].items():
- yield slab, infos
+ if level_id is not None:
+ if slab[1] == level_id:
+ yield slab, infos
+ else:
+ yield slab, infos
else:
# Copie de la liste dans un fichier temporaire (cette liste peut être un objet)
list_obj = tempfile.NamedTemporaryFile(mode="r", delete=False)
@@ -824,7 +844,11 @@ def list_generator(self) -> Iterator[Tuple[Tuple[SlabType, str, int, int], Dict]
"md5": slab_md5,
}
- yield ((slab_type, level, column, row), infos)
+ if level_id is not None:
+ if level == level_id:
+ yield ((slab_type, level, column, row), infos)
+ else:
+ yield ((slab_type, level, column, row), infos)
remove(f"file://{list_file}")
@@ -1372,6 +1396,58 @@ def get_tile_indices(
return (level_object.id,) + level_object.tile_matrix.point_to_indices(x, y)
+ def delete_level(self, level_id: str) -> None:
+ """Delete the given level in the description of the pyramid
+
+ Args:
+ level_id: Level identifier
+
+ Raises:
+ Exception: Cannot find level
+ """
+
+ try:
+ del self.__levels[level_id]
+ except Exception:
+ raise Exception(f"The level {level_id} don't exist in the pyramid")
+
+ def add_level(
+ self,
+ level_id: str,
+ tiles_per_width: int,
+ tiles_per_height: int,
+ tile_limits: Dict[str, int],
+ ) -> None:
+ """Add a level in the description of the pyramid
+
+ Args:
+ level_id: Level identifier
+ tiles_per_width : Number of tiles in width by slab
+ tiles_per_height : Number of tiles in height by slab
+ tile_limits : Minimum and maximum tiles' columns and rows of pyramid's content
+ """
+
+ data = {
+ "id": level_id,
+ "tile_limits": tile_limits,
+ "tiles_per_width": tiles_per_width,
+ "tiles_per_height": tiles_per_height,
+ "storage": {"type": self.storage_type.name},
+ }
+ if self.own_masks:
+ data["storage"]["mask_prefix"] = True
+ if self.storage_type == StorageType.FILE:
+ data["storage"]["path_depth"] = self.storage_depth
+
+ lev = Level.from_descriptor(data, self)
+
+ if self.__tms.get_level(lev.id) is None:
+ raise Exception(
+ f"Pyramid {self.name} owns a level with the ID '{lev.id}', not defined in the TMS '{self.tms.name}'"
+ )
+ else:
+ self.__levels[lev.id] = lev
+
@property
def size(self) -> int:
"""Get the size of the pyramid
diff --git a/src/rok4/storage.py b/src/rok4/storage.py
index a3c6975..1cf0f6f 100644
--- a/src/rok4/storage.py
+++ b/src/rok4/storage.py
@@ -11,9 +11,9 @@
Readings uses a LRU cache system with a TTL. It's possible to configure it with environment variables :
- ROK4_READING_LRU_CACHE_SIZE : Number of cached element. Default 64. Set 0 or a negative integer to configure a cache without bound. A power of two make cache more efficient.
-- ROK4_READING_LRU_CACHE_TTL : Validity duration of cached element, in seconds. Default 300. 0 or negative integer to disable time validity.
+- ROK4_READING_LRU_CACHE_TTL : Validity duration of cached element, in seconds. Default 300. 0 or negative integer to get cache without expiration date.
-To disable cache, set ROK4_READING_LRU_CACHE_SIZE to 1 and ROK4_READING_LRU_CACHE_TTL to 0.
+To disable cache (always read data on storage), set ROK4_READING_LRU_CACHE_SIZE to 1 and ROK4_READING_LRU_CACHE_TTL to 1.
Using CEPH storage requires environment variables :
- ROK4_CEPH_CONFFILE
@@ -24,7 +24,6 @@
- ROK4_S3_KEY
- ROK4_S3_SECRETKEY
- ROK4_S3_URL
-- ROK4_SSL_NO_VERIFY (optionnal) with a non empty value disables certificate check.. Define PYTHONWARNINGS to "ignore:Unverified HTTPS request" to disable warnings logs
To use several S3 clusters, each environment variable have to contain a list (comma-separated), with the same number of elements
@@ -74,7 +73,6 @@
__OBJECT_SYMLINK_SIGNATURE = "SYMLINK#"
__S3_CLIENTS = {}
__S3_DEFAULT_CLIENT = None
-
__LRU_SIZE = 64
__LRU_TTL = 300
@@ -97,10 +95,10 @@
pass
-def __get_ttl_hash():
+def __get_ttl_hash() -> int:
"""Return the time string rounded according to time-to-live value"""
if __LRU_TTL == 0:
- return time.time()
+ return 0
else:
return round(time.time() / __LRU_TTL)
@@ -127,7 +125,6 @@ def __get_s3_client(bucket_name: str) -> Tuple[Dict[str, Union["boto3.client", s
verify = True
if "ROK4_SSL_NO_VERIFY" in os.environ and os.environ["ROK4_SSL_NO_VERIFY"] != "":
verify = False
-
# C'est la première fois qu'on cherche à utiliser le stockage S3, chargeons les informations depuis les variables d'environnement
try:
keys = os.environ["ROK4_S3_KEY"].split(",")
@@ -1033,6 +1030,12 @@ def link(target_path: str, link_path: str, hard: bool = False) -> None:
elif target_type == StorageType.FILE:
try:
+ to_tray = get_infos_from_path(link_path)[2]
+ if to_tray != "":
+ os.makedirs(to_tray, exist_ok=True)
+
+ if exists(link_path):
+ remove(link_path)
if hard:
os.link(target_path, link_path)
else:
@@ -1081,7 +1084,7 @@ def get_osgeo_path(path: str) -> str:
def size_path(path: str) -> int:
- """Return the size of the path given (or, for the CEPH, the sum of the size of each object of the .list)
+ """Return the size of the given path (or, for the CEPH, the sum of the size of each object of the .list)
Args:
path (str): Source path
diff --git a/src/rok4/tile_matrix_set.py b/src/rok4/tile_matrix_set.py
index 84a3d22..a51d717 100644
--- a/src/rok4/tile_matrix_set.py
+++ b/src/rok4/tile_matrix_set.py
@@ -177,6 +177,14 @@ def point_to_indices(self, x: float, y: float) -> Tuple[int, int, int, int]:
absolute_pixel_row % self.tile_size[1],
)
+ @property
+ def tile_width(self) -> int:
+ return self.tile_size[0]
+
+ @property
+ def tile_heigth(self) -> int:
+ return self.tile_size[1]
+
class TileMatrixSet:
"""A tile matrix set is multi levels grid definition
diff --git a/src/rok4/utils.py b/src/rok4/utils.py
index 40c7884..050d679 100644
--- a/src/rok4/utils.py
+++ b/src/rok4/utils.py
@@ -1,5 +1,6 @@
"""Provide functions to manipulate OGR / OSR entities
"""
+
# -- IMPORTS --
# standard library
diff --git a/tests/test_pyramid.py b/tests/test_pyramid.py
index f44eed7..007ef45 100644
--- a/tests/test_pyramid.py
+++ b/tests/test_pyramid.py
@@ -1,13 +1,13 @@
import os
from unittest import mock
-from unittest.mock import *
+from unittest.mock import MagicMock
import pytest
from rok4.enums import SlabType, StorageType
-from rok4.exceptions import *
-from rok4.pyramid import *
-from rok4.utils import *
+from rok4.exceptions import FormatError, MissingAttributeError, StorageError
+from rok4.pyramid import Pyramid, b36_path_decode, b36_path_encode
+from rok4.utils import srs_to_spatialreference
@mock.patch("rok4.pyramid.get_data_str", side_effect=StorageError("FILE", "Not found"))
diff --git a/tests/test_storage.py b/tests/test_storage.py
index f5c4889..dd7dddd 100644
--- a/tests/test_storage.py
+++ b/tests/test_storage.py
@@ -1,13 +1,30 @@
import os
from unittest import mock
-from unittest.mock import *
+from unittest.mock import MagicMock, mock_open, patch
import botocore.exceptions
import pytest
from rok4.enums import StorageType
-from rok4.exceptions import *
-from rok4.storage import *
+from rok4.exceptions import MissingEnvironmentError, StorageError
+from rok4.storage import (
+ copy,
+ disconnect_ceph_clients,
+ disconnect_s3_clients,
+ exists,
+ get_data_binary,
+ get_data_str,
+ get_infos_from_path,
+ get_osgeo_path,
+ get_path_from_infos,
+ get_size,
+ hash_file,
+ link,
+ put_data_str,
+ rados,
+ remove,
+ size_path,
+)
@mock.patch.dict(os.environ, {}, clear=True)
@@ -48,7 +65,7 @@ def test_get_path_from_infos():
assert get_path_from_infos(StorageType.CEPH, "toto", "titi/tutu") == "ceph://toto/titi/tutu"
-############ get_data_str
+# -- get_data_str
@mock.patch.dict(os.environ, {}, clear=True)
@@ -196,7 +213,7 @@ def test_http_read_ok(mock_http):
assert False, f"HTTP read raises an exception: {exc}"
-############ put_data_str
+# -- put_data_str
@mock.patch.dict(
@@ -252,7 +269,7 @@ def test_ceph_write_ok(mocked_rados_client):
assert False, f"CEPH write raises an exception: {exc}"
-############ copy
+# -- copy
@mock.patch.dict(os.environ, {}, clear=True)
@@ -571,7 +588,7 @@ def test_copy_http_s3_ok(mock_remove, mock_tempfile, mock_requests, mocked_s3_cl
assert False, f"HTTP -> CEPH copy raises an exception: {exc}"
-############ link
+# -- link
def test_link_type_nok():
@@ -586,9 +603,11 @@ def test_link_hard_nok():
@mock.patch.dict(os.environ, {}, clear=True)
@mock.patch("os.symlink", return_value=None)
-def test_link_file_ok(mock_link):
+@mock.patch("os.makedirs", return_value=None)
+def test_link_file_ok(mock_makedirs, mock_link):
try:
link("file:///path/to/target.ext", "file:///path/to/link.ext")
+ mock_makedirs.assert_called_once_with("/path/to", exist_ok=True)
mock_link.assert_called_once_with("/path/to/target.ext", "/path/to/link.ext")
except Exception as exc:
assert False, f"FILE link raises an exception: {exc}"
@@ -596,9 +615,11 @@ def test_link_file_ok(mock_link):
@mock.patch.dict(os.environ, {}, clear=True)
@mock.patch("os.link", return_value=None)
-def test_hlink_file_ok(mock_link):
+@mock.patch("os.makedirs", return_value=None)
+def test_hlink_file_ok(mock_makedirs, mock_link):
try:
link("file:///path/to/target.ext", "file:///path/to/link.ext", True)
+ mock_makedirs.assert_called_once_with("/path/to", exist_ok=True)
mock_link.assert_called_once_with("/path/to/target.ext", "/path/to/link.ext")
except Exception as exc:
assert False, f"FILE hard link raises an exception: {exc}"
@@ -658,7 +679,7 @@ def test_link_s3_nok(mocked_s3_client):
link("s3://bucket1@a/target.ext", "s3://bucket2@b/link.ext")
-############ get_size
+# -- get_size
@mock.patch.dict(os.environ, {}, clear=True)
@@ -726,7 +747,7 @@ def test_size_http_ok(mock_requests):
assert False, f"HTTP size raises an exception: {exc}"
-############ exists
+# --exists
@mock.patch.dict(os.environ, {}, clear=True)
@@ -817,7 +838,7 @@ def test_exists_http_ok(mock_requests):
assert False, f"HTTP exists raises an exception: {exc}"
-############ remove
+# -- remove
@mock.patch.dict(os.environ, {}, clear=True)
@@ -880,7 +901,7 @@ def test_remove_s3_ok(mocked_s3_client):
assert False, f"S3 deletion raises an exception: {exc}"
-############ get_osgeo_path
+# -- get_osgeo_path
@mock.patch.dict(os.environ, {}, clear=True)
@@ -913,7 +934,7 @@ def test_get_osgeo_path_nok():
get_osgeo_path("ceph://pool/data.ext")
-############ size_path
+# -- size_path
def test_size_path_file_ok():
try:
size = size_path("file://tests/fixtures/TIFF_PBF_MVT")
diff --git a/tests/test_tile_matrix_set.py b/tests/test_tile_matrix_set.py
index 94f89f8..4209daa 100644
--- a/tests/test_tile_matrix_set.py
+++ b/tests/test_tile_matrix_set.py
@@ -4,7 +4,12 @@
import pytest
-from rok4.exceptions import *
+from rok4.exceptions import (
+ FormatError,
+ MissingAttributeError,
+ MissingEnvironmentError,
+ StorageError,
+)
from rok4.tile_matrix_set import TileMatrixSet
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 584e34d..696a3d4 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,13 +1,20 @@
import math
import random
-from unittest import mock
-from unittest.mock import *
+from unittest.mock import MagicMock, Mock, patch
import pytest
from osgeo import gdal, osr
-from rok4.exceptions import *
-from rok4.utils import *
+# from rok4.exceptions import *
+from rok4.utils import (
+ ColorFormat,
+ bbox_to_geometry,
+ compute_bbox,
+ compute_format,
+ reproject_bbox,
+ reproject_point,
+ srs_to_spatialreference,
+)
def test_srs_to_spatialreference_ignf_ok():
@@ -217,10 +224,10 @@ def test_compute_bbox_no_srs_ok():
# Tests for the rok4.utils.compute_format function.
-@mock.patch("rok4.utils.gdal.Info")
-@mock.patch("rok4.utils.gdal.GetColorInterpretationName", return_value="Palette")
-@mock.patch("rok4.utils.gdal.GetDataTypeSize", return_value=8)
-@mock.patch("rok4.utils.gdal.GetDataTypeName", return_value="Byte")
+@patch("rok4.utils.gdal.Info")
+@patch("rok4.utils.gdal.GetColorInterpretationName", return_value="Palette")
+@patch("rok4.utils.gdal.GetDataTypeSize", return_value=8)
+@patch("rok4.utils.gdal.GetDataTypeName", return_value="Byte")
def test_compute_format_bit_ok(
mocked_GetDataTypeName, mocked_GetDataTypeSize, mocked_GetColorInterpretationName, mocked_Info
):
@@ -246,10 +253,10 @@ def test_compute_format_bit_ok(
assert False, f"Color format computation raises an exception: {exc}"
-@mock.patch("rok4.utils.gdal.Info")
-@mock.patch("rok4.utils.gdal.GetColorInterpretationName")
-@mock.patch("rok4.utils.gdal.GetDataTypeSize", return_value=8)
-@mock.patch("rok4.utils.gdal.GetDataTypeName", return_value="Byte")
+@patch("rok4.utils.gdal.Info")
+@patch("rok4.utils.gdal.GetColorInterpretationName")
+@patch("rok4.utils.gdal.GetDataTypeSize", return_value=8)
+@patch("rok4.utils.gdal.GetDataTypeName", return_value="Byte")
def test_compute_format_uint8_ok(
mocked_GetDataTypeName, mocked_GetDataTypeSize, mocked_GetColorInterpretationName, mocked_Info
):
@@ -283,10 +290,10 @@ def test_compute_format_uint8_ok(
assert False, f"Color format computation raises an exception: {exc}"
-@mock.patch("rok4.utils.gdal.Info")
-@mock.patch("rok4.utils.gdal.GetColorInterpretationName")
-@mock.patch("rok4.utils.gdal.GetDataTypeSize", return_value=32)
-@mock.patch("rok4.utils.gdal.GetDataTypeName", return_value="Float32")
+@patch("rok4.utils.gdal.Info")
+@patch("rok4.utils.gdal.GetColorInterpretationName")
+@patch("rok4.utils.gdal.GetDataTypeSize", return_value=32)
+@patch("rok4.utils.gdal.GetDataTypeName", return_value="Float32")
def test_compute_format_float32_ok(
mocked_GetDataTypeName, mocked_GetDataTypeSize, mocked_GetColorInterpretationName, mocked_Info
):
@@ -320,10 +327,10 @@ def test_compute_format_float32_ok(
assert False, f"Color format computation raises an exception: {exc}"
-@mock.patch("rok4.utils.gdal.Info")
-@mock.patch("rok4.utils.gdal.GetColorInterpretationName")
-@mock.patch("rok4.utils.gdal.GetDataTypeSize", return_value=16)
-@mock.patch("rok4.utils.gdal.GetDataTypeName", return_value="UInt16")
+@patch("rok4.utils.gdal.Info")
+@patch("rok4.utils.gdal.GetColorInterpretationName")
+@patch("rok4.utils.gdal.GetDataTypeSize", return_value=16)
+@patch("rok4.utils.gdal.GetDataTypeName", return_value="UInt16")
def test_compute_format_unsupported_nok(
mocked_GetDataTypeName, mocked_GetDataTypeSize, mocked_GetColorInterpretationName, mocked_Info
):
@@ -357,10 +364,10 @@ def test_compute_format_unsupported_nok(
assert False, f"Color format computation raises an exception: {exc}"
-@mock.patch("rok4.utils.gdal.Info")
-@mock.patch("rok4.utils.gdal.GetColorInterpretationName")
-@mock.patch("rok4.utils.gdal.GetDataTypeSize", return_value=16)
-@mock.patch("rok4.utils.gdal.GetDataTypeName", return_value="UInt16")
+@patch("rok4.utils.gdal.Info")
+@patch("rok4.utils.gdal.GetColorInterpretationName")
+@patch("rok4.utils.gdal.GetDataTypeSize", return_value=16)
+@patch("rok4.utils.gdal.GetDataTypeName", return_value="UInt16")
def test_compute_format_no_band_nok(
mocked_GetDataTypeName, mocked_GetDataTypeSize, mocked_GetColorInterpretationName, mocked_Info
):
diff --git a/tests/test_vector.py b/tests/test_vector.py
index 72e9c50..cac0048 100644
--- a/tests/test_vector.py
+++ b/tests/test_vector.py
@@ -1,12 +1,14 @@
+# standard library
import os
from unittest import mock
-from unittest.mock import *
+# 3rd party
import pytest
-from rok4.exceptions import *
+# package
+from rok4.exceptions import MissingEnvironmentError, StorageError
from rok4.storage import disconnect_ceph_clients
-from rok4.vector import *
+from rok4.vector import Vector
@mock.patch.dict(os.environ, {}, clear=True)