Skip to content
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

refactor: use PEP 548 compatible annotation #346

Merged
merged 2 commits into from
Oct 21, 2024
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
5 changes: 2 additions & 3 deletions docs/_extension/api_admonition.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""A directive to generate an API admonition."""

from typing import Any, Dict
from __future__ import annotations

from docutils import nodes
from docutils.parsers.rst import directives
Expand Down Expand Up @@ -56,7 +55,7 @@ def run(self) -> list[nodes.Node]:
raise RuntimeError # never reached here


def setup(app: Sphinx) -> Dict[str, Any]:
def setup(app: Sphinx) -> dict[str, object]:
"""Add custom configuration to sphinx app.
Args:
Expand Down
6 changes: 2 additions & 4 deletions docs/_extension/docstring.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""A docstring role to read the docstring from a Python method."""
from __future__ import annotations

from typing import Any, Dict, List, Tuple

from docutils import nodes
from sphinx.application import Sphinx
from sphinx.util import logging
Expand All @@ -16,7 +14,7 @@
class DocstringRole(SphinxRole):
"""The docstring role interpreter."""

def run(self) -> Tuple[List[nodes.Node], List[str]]:
def run(self) -> tuple[list[nodes.Node], list[str]]:
"""Setup the role in the builder context."""
members = self.text.split(".")[1:]
o = geetools
Expand All @@ -25,7 +23,7 @@ def run(self) -> Tuple[List[nodes.Node], List[str]]:
return [nodes.Text(o.__doc__.splitlines()[0])], []


def setup(app: Sphinx) -> Dict[str, Any]:
def setup(app: Sphinx) -> dict[str, object]:
"""Add custom configuration to sphinx application."""
app.add_role("docstring", DocstringRole())

Expand Down
17 changes: 6 additions & 11 deletions geetools/Array.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@
import ee

from .accessors import register_class_accessor
from .types import ee_int, ee_number

# hack to have the generated Array class available
# it might create issues in the future with libs that have exotic init methods
# ee.Initialize()


@register_class_accessor(ee.Array, "geetools")
Expand All @@ -22,9 +17,9 @@ def __init__(self, obj: ee.Array):
# -- alternative constructor -----------------------------------------------
def full(
self,
width: ee_number,
height: ee_number,
value: ee_number,
width: float | int | ee.Number,
height: float | int | ee.Number,
value: float | int | ee.Number,
) -> ee.Array:
"""Create an array with the given dimensions, initialized to the given value.

Expand Down Expand Up @@ -52,9 +47,9 @@ def full(
# -- data maniputlation ----------------------------------------------------
def set(
self,
x: ee_int,
y: ee_int,
value: ee_number,
x: int | ee.Number,
y: int | ee.Number,
value: float | int | ee.Number,
) -> ee.Array:
"""Set the value of a cell in an array.

Expand Down
20 changes: 9 additions & 11 deletions geetools/Asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
import os
import re
from pathlib import PurePosixPath
from typing import Optional

import ee

from .accessors import _register_extention
from .types import pathlike
from .utils import format_description


Expand All @@ -34,23 +32,23 @@ def __repr__(self):
"""Return the asset object representation as a string."""
return f"ee.{type(self).__name__}('{self.as_posix()}')"

def __truediv__(self, other: pathlike) -> Asset:
def __truediv__(self, other: os.PathLike) -> Asset:
"""Override the division operator to join the asset with other paths."""
return Asset(self._path / str(other))

def __lt__(self, other: pathlike) -> bool:
def __lt__(self, other: os.PathLike) -> bool:
"""Override the less than operator to compare the asset with other paths."""
return self._path < PurePosixPath(str(other))

def __gt__(self, other: pathlike) -> bool:
def __gt__(self, other: os.PathLike) -> bool:
"""Override the greater than operator to compare the asset with other paths."""
return self._path > PurePosixPath(str(other))

def __le__(self, other: pathlike) -> bool:
def __le__(self, other: os.PathLike) -> bool:
"""Override the less than or equal operator to compare the asset with other paths."""
return self._path <= PurePosixPath(str(other))

def __ge__(self, other: pathlike) -> bool:
def __ge__(self, other: os.PathLike) -> bool:
"""Override the greater than or equal operator to compare the asset with other paths."""
return self._path >= PurePosixPath(str(other))

Expand All @@ -62,7 +60,7 @@ def __ne__(self, other: object) -> bool:
"""Override the not equal operator to compare the asset with other paths."""
return self._path != PurePosixPath(str(other))

def __idiv__(self, other: pathlike) -> Asset:
def __idiv__(self, other: os.PathLike) -> Asset:
"""Override the in-place division operator to join the asset with other paths."""
return Asset(self._path / str(other))

Expand Down Expand Up @@ -271,7 +269,7 @@ def st_size(self):

return int(ee.data.getAsset(self.as_posix())["sizeBytes"])

def is_relative_to(self, other: pathlike) -> bool:
def is_relative_to(self, other: os.PathLike) -> bool:
"""Return True if the asset is relative to another asset.

Args:
Expand Down Expand Up @@ -569,7 +567,7 @@ def move(self, new_asset: Asset, overwrite: bool = False) -> Asset:

return new_asset

def delete(self, recursive: bool = False, dry_run: Optional[bool] = None) -> list:
def delete(self, recursive: bool = False, dry_run: bool | None = None) -> list:
"""Remove the asset.

This method will delete an asset (any type) asset and all its potential children. by default it is not recursive and will raise an error if the container is not empty.
Expand Down Expand Up @@ -639,7 +637,7 @@ def unlink(self) -> list:
self.exists(raised=True)
return self.delete()

def rmdir(self, recursive: bool = False, dry_run: Optional[bool] = None) -> list:
def rmdir(self, recursive: bool = False, dry_run: bool | None = None) -> list:
"""``delete`` alias for containers."""
if not (self.is_project() or self.is_folder() or self.is_image_collection()):
raise ValueError(f"Asset {self.as_posix()} is not a container, use unlink instead.")
Expand Down
9 changes: 4 additions & 5 deletions geetools/ComputedObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@
from __future__ import annotations

import json
import os
from pathlib import Path
from typing import Type

import ee

from .accessors import _register_extention
from .types import pathlike


# -- types management ----------------------------------------------------------
@_register_extention(ee.ComputedObject)
def isInstance(self, klass: Type) -> ee.Number:
def isInstance(self, klass: type) -> ee.Number:
"""Return 1 if the element is the passed type or 0 if not.

Parameters:
Expand All @@ -37,7 +36,7 @@ def isInstance(self, klass: Type) -> ee.Number:

# -- .gee files ----------------------------------------------------------------
@_register_extention(ee.ComputedObject) # type: ignore
def save(self, path: pathlike) -> Path:
def save(self, path: os.PathLike) -> Path:
"""Save a ``ComputedObject`` to a .gee file.

The file contains the JSON representation of the object. it still need to be computed via ``getInfo()`` to be used.
Expand Down Expand Up @@ -70,7 +69,7 @@ def save(self, path: pathlike) -> Path:

@staticmethod # type: ignore
@_register_extention(ee.ComputedObject) # type: ignore
def open(path: pathlike) -> ee.ComputedObject:
def open(path: os.PathLike) -> ee.ComputedObject:
"""Open a .gee file as a ComputedObject.

Parameters:
Expand Down
3 changes: 1 addition & 2 deletions geetools/DateRange.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import ee

from .accessors import register_class_accessor
from .types import ee_int


@register_class_accessor(ee.DateRange, "geetools")
Expand All @@ -16,7 +15,7 @@ def __init__(self, obj: ee.DateRange):
self._obj = obj

# -- date range operations -------------------------------------------------
def split(self, interval: ee_int, unit: str = "day") -> ee.List:
def split(self, interval: int | ee.Number, unit: str = "day") -> ee.List:
"""Convert a ``ee.DateRange`` to a list of ``ee.DateRange``.

The DateRange will be split in multiple DateRanges of the specified interval and Unit.
Expand Down
5 changes: 2 additions & 3 deletions geetools/Dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import ee

from .accessors import register_class_accessor
from .types import ee_list


@register_class_accessor(ee.Dictionary, "geetools")
Expand All @@ -16,7 +15,7 @@ def __init__(self, obj: ee.Dictionary):
self._obj = obj

# -- alternative constructor -----------------------------------------------
def fromPairs(self, list: ee_list) -> ee.Dictionary:
def fromPairs(self, list: list | ee.List) -> ee.Dictionary:
"""Create a dictionary from a list of [[key, value], ...]] pairs.

Parameters:
Expand Down Expand Up @@ -61,7 +60,7 @@ def sort(self) -> ee.Dictionary:
values = orderededKeys.map(lambda key: self._obj.get(key))
return ee.Dictionary.fromLists(orderededKeys, values)

def getMany(self, list: ee_list) -> ee.List:
def getMany(self, list: list | ee.List) -> ee.List:
"""Extract values from a list of keys.

Parameters:
Expand Down
32 changes: 15 additions & 17 deletions geetools/Export.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""Toolbox for the ``ee.Export`` class."""
from __future__ import annotations

from typing import List, Optional

import ee

from .accessors import register_class_accessor
Expand Down Expand Up @@ -30,10 +28,10 @@ def __init__(self):
def toAsset(
imagecollection: ee.ImageCollection,
index_property: str = "system:id",
description: Optional[str] = None,
assetId: Optional[str] = None,
description: str = "",
assetId: str = "",
**kwargs,
) -> List[ee.batch.Task]:
) -> list[ee.batch.Task]:
"""Creates a task to export an EE ImageCollection to an EE Asset.
The method will create the imagecollection asset beforehand and launching the task will
Expand Down Expand Up @@ -68,8 +66,8 @@ def toAsset(
"""
# sanity check on parameters
# renaming them for mypy type reassignment and compactness
desc = description or ee.Asset(assetId).name
aid = ee.Asset(assetId) or ee.Asset("~").expanduser() / description
desc = description if description else ee.Asset(assetId).name
aid = ee.Asset(assetId) if assetId else ee.Asset("~").expanduser() / description

# create the ImageCollection asset
ee.data.createAsset({"type": "IMAGE_COLLECTION"}, aid.as_posix())
Expand Down Expand Up @@ -97,10 +95,10 @@ def toAsset(
def toDrive(
imagecollection: ee.ImageCollection,
index_property: str = "system:id",
description: Optional[str] = None,
folder: Optional[str] = None,
description: str = "",
folder: str = "",
**kwargs,
) -> List[ee.batch.Task]:
) -> list[ee.batch.Task]:
"""Creates a list of tasks to export an EE ImageCollection to Google Drive.
The method will create a folder in Google Drive with the description value and populate
Expand Down Expand Up @@ -134,8 +132,8 @@ def toDrive(
"""
# sanity check on parameters
# renaming them for mypy type reassignment and compactness
desc = description or folder
fid = folder or description
desc = description if description else folder
fid = folder if folder else description

# loop over the collection and export each image
nb_images = imagecollection.size().getInfo()
Expand All @@ -161,10 +159,10 @@ def toDrive(
def toCloudStorage(
imagecollection: ee.ImageCollection,
index_property: str = "system:id",
description: Optional[str] = None,
folder: Optional[str] = None,
description: str = "",
folder: str = "",
**kwargs,
) -> List[ee.batch.Task]:
) -> list[ee.batch.Task]:
"""Creates a list of tasks to export an EE ImageCollection to Google cloud.
The method will create a folder in Google cloud bucket with the description value and populate
Expand Down Expand Up @@ -198,8 +196,8 @@ def toCloudStorage(
"""
# sanity check on parameters
# renaming them for mypy type reassignment and compactness
desc = description or folder
fid = folder or description
desc = description if description else folder
fid = folder if folder else description

# loop over the collection and export each image
nb_images = imagecollection.size().getInfo()
Expand Down
3 changes: 1 addition & 2 deletions geetools/Feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import ee

from .accessors import register_class_accessor
from .types import ee_list


@register_class_accessor(ee.Feature, "geetools")
Expand Down Expand Up @@ -38,7 +37,7 @@ def toFeatureCollection(self) -> ee.FeatureCollection:
fc = geoms.map(lambda g: self._obj.setGeometry(g))
return ee.FeatureCollection(fc)

def removeProperties(self, properties: ee_list) -> ee.Feature:
def removeProperties(self, properties: list | ee.List) -> ee.Feature:
"""Remove properties from a feature.

Args:
Expand Down
Loading