Skip to content

Commit

Permalink
Merge pull request #529 from pyinat/controller-refactor
Browse files Browse the repository at this point in the history
Refactor controller methods
  • Loading branch information
JWCook committed Dec 12, 2023
2 parents ab1d6a2 + 2d19325 commit 769114f
Show file tree
Hide file tree
Showing 16 changed files with 731 additions and 135 deletions.
10 changes: 4 additions & 6 deletions pyinaturalist/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
from logging import getLogger
from typing import Any, Callable, Dict, Optional, Type

from requests import Session

from pyinaturalist.auth import get_access_token
from pyinaturalist.constants import RequestParams
from pyinaturalist.controllers import (
Expand Down Expand Up @@ -62,7 +60,7 @@ def __init__(
default_params: Optional[Dict[str, Any]] = None,
dry_run: bool = False,
loop: Optional[AbstractEventLoop] = None,
session: Optional[Session] = None,
session: Optional[ClientSession] = None,
**kwargs,
):
self.creds = creds or {}
Expand Down Expand Up @@ -94,7 +92,7 @@ def __init__(
self
) #: Interface for :py:class:`user requests <.UserController>`

def add_client_settings(
def add_defaults(
self, request_function, kwargs: Optional[RequestParams] = None, auth: bool = False
) -> RequestParams:
"""Add any applicable client settings to request parameters before sending a request.
Expand Down Expand Up @@ -133,7 +131,7 @@ def paginate(
cls: Alternative Paginator class to use
params: Original request parameters
"""
kwargs = self.add_client_settings(request_function, kwargs, auth)
kwargs = self.add_defaults(request_function, kwargs, auth)
return cls(request_function, model, loop=self.loop, **kwargs)

def request(self, request_function: Callable, *args, auth: bool = False, **kwargs):
Expand All @@ -147,5 +145,5 @@ def request(self, request_function: Callable, *args, auth: bool = False, **kwarg
Returns:
Results of ``request_function()``
"""
kwargs = self.add_client_settings(request_function, kwargs, auth)
kwargs = self.add_defaults(request_function, kwargs, auth)
return request_function(*args, **kwargs)
47 changes: 39 additions & 8 deletions pyinaturalist/controllers/annotation_controller.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from logging import getLogger
from typing import Dict, List

from pyinaturalist.constants import API_V2, IntOrStr
from pyinaturalist.controllers import BaseController
from pyinaturalist.docs import document_common_args, document_controller_params
from pyinaturalist.models import Annotation, ControlledTerm
from pyinaturalist.session import delete, post
from pyinaturalist.v1 import get_controlled_terms, get_controlled_terms_for_taxon

logger = getLogger(__name__)


class AnnotationController(BaseController):
""":fa:`tag` Controller for Annotation and ControlledTerm requests"""
Expand All @@ -22,13 +24,41 @@ def term_lookup(self) -> Dict[int, ControlledTerm]:
self._term_lookup = {term.id: term for term in self.all()}
return self._term_lookup

@document_controller_params(get_controlled_terms)
def all(self, **params) -> List[ControlledTerm]:
"""List controlled terms and their possible values
.. rubric:: Notes
* API reference: :v1:`GET /controlled_terms <Controlled_Terms/get_controlled_terms>`
Example:
>>> terms = client.annotations
>>> pprint(response[0])
1: Life Stage
2: Adult
3: Teneral
4: Pupa
...
"""
response = get_controlled_terms(**params)
return ControlledTerm.from_json_list(response['results'])

@document_controller_params(get_controlled_terms_for_taxon)
def for_taxon(self, taxon_id: int, **params) -> List[ControlledTerm]:
"""List controlled terms that are valid for the specified taxon.
.. rubric:: Notes
* API reference: :v1:`GET /controlled_terms/for_taxon <Controlled_Terms/get_controlled_terms_for_taxon>`
Example:
>>> client.annotations.for_taxon(12345)
Args:
taxon_id: Taxon ID to get controlled terms for
Raises:
:py:exc:`.TaxonNotFound`: If an invalid ``taxon_id`` is specified
"""
response = get_controlled_terms_for_taxon(taxon_id, **params)
return ControlledTerm.from_json_list(response['results'])

Expand All @@ -47,10 +77,12 @@ def lookup(self, annotations: List[Annotation]) -> List[Annotation]:
if term:
annotation.controlled_attribute = term
annotation.controlled_value = term.get_value_by_id(annotation.controlled_value.id)
else:
logger.warning(
f'No controlled attribute found for ID: {annotation.controlled_attribute.id}'
)
return annotations

# TODO: Allow passing labels instead of IDs
@document_common_args
def create(
self,
controlled_attribute_id: int,
Expand All @@ -68,10 +100,9 @@ def create(
resource_type: Resource type, if something other than an observation
Example:
Add a 'Plant phenology: Flowering' annotation to an observation (via IDs):
Add a 'Plant phenology: Flowering' annotation to an observation:
>>> annotation = client.annotations.create(12, 13, 164609837)
>>> client.annotations.create(12, 13, 164609837)
Returns:
The newly created Annotation object
Expand Down
Loading

0 comments on commit 769114f

Please sign in to comment.