afscgap.cursor

Interfaces for cursor objects which iterate over real or inferred records.

(c) 2023 Regents of University of California / The Eric and Wendy Schmidt Center for Data Science and the Environment at UC Berkeley.

This file is part of afscgap released under the BSD 3-Clause License. See LICENSE.md.

  1"""
  2Interfaces for cursor objects which iterate over real or inferred records.
  3
  4(c) 2023 Regents of University of California / The Eric and Wendy Schmidt Center
  5for Data Science and the Environment at UC Berkeley.
  6
  7This file is part of afscgap released under the BSD 3-Clause License. See
  8LICENSE.md.
  9"""
 10
 11import queue
 12import typing
 13
 14import afscgap.model
 15
 16from afscgap.typesdef import OPT_INT
 17
 18
 19class Cursor(typing.Iterable[afscgap.model.Record]):
 20    """Interface for objects allowing generation / retrieval of records."""
 21
 22    def get_base_url(self) -> str:
 23        """Get the URL at which the first page of query results can be found.
 24
 25        Returns:
 26            The URL for the query without pagination information.
 27        """
 28        raise NotImplementedError('Use implementor.')
 29
 30    def get_limit(self) -> OPT_INT:
 31        """Get the page size limit.
 32
 33        Returns:
 34            The maximum number of records to return per page.
 35        """
 36        raise NotImplementedError('Use implementor.')
 37
 38    def get_start_offset(self) -> OPT_INT:
 39        """Get the number of inital records to ignore.
 40
 41        Returns:
 42            The number of records being skipped at the start of the result set.
 43        """
 44        raise NotImplementedError('Use implementor.')
 45
 46    def get_filtering_incomplete(self) -> bool:
 47        """Determine if this cursor is silently filtering incomplete records.
 48
 49        Returns:
 50            Flag indicating if incomplete records should be silently filtered.
 51            If true, they will not be returned during iteration and placed in
 52            the queue at get_invalid(). If false, they will be returned and
 53            those incomplete records' get_complete() will return false.
 54        """
 55        raise NotImplementedError('Use implementor.')
 56
 57    def get_page_url(self, offset: OPT_INT = None,
 58        limit: OPT_INT = None) -> str:
 59        """Get a URL at which a page can be found using this cursor's base url.
 60
 61        Args:
 62            offset: The number of records to skip prior to the page.
 63            limit: The maximum number of records to return in the page.
 64        Returns:
 65            URL at which the requested page can be found.
 66        """
 67        raise NotImplementedError('Use implementor.')
 68
 69    def get_page(self, offset: OPT_INT = None,
 70        limit: OPT_INT = None,
 71        ignore_invalid: bool = False) -> typing.List[afscgap.model.Record]:
 72        """Get a page using this cursor's base url.
 73
 74        Args:
 75            offset: The number of records to skip prior to the page.
 76            limit: The maximum number of records to return in the page.
 77            ignore_invalid: Flag indicating how to handle invalid records. If
 78                true, will silently throw away records which could not be
 79                parsed. If false, will raise an exception if a record can not
 80                be parsed.
 81
 82        Returns:
 83            Results from the page which, regardless of ignore_invalid, may
 84            contain a mixture of complete and incomplete records.
 85        """
 86        raise NotImplementedError('Use implementor.')
 87
 88    def get_invalid(self) -> 'queue.Queue[dict]':
 89        """Get a queue of invalid / incomplete records found so far.
 90
 91        Returns:
 92            Queue with dictionaries containing the raw data returned from the
 93            API that did not have valid values for all required fields. Note
 94            that this will include incomplete records as well if
 95            get_filtering_incomplete() is true and will not contain incomplete
 96            records otherwise.
 97        """
 98        raise NotImplementedError('Use implementor.')
 99
100    def to_dicts(self) -> typing.Iterable[dict]:
101        """Create an iterator which converts Records to dicts.
102
103        Returns:
104            Iterator which returns dictionaries instead of Record objects but
105            has otherwise the same beahavior as iterating in this Cursor
106            directly.
107        """
108        raise NotImplementedError('Use implementor.')
109
110    def get_next(self) -> typing.Optional[afscgap.model.Record]:
111        """Get the next value for this Cursor.
112
113        Returns:
114            The next value waiting if cached in the cursor's results queue or
115            as just retrieved from a new page gathered by HTTP request. Will
116            return None if no remain.
117        """
118        raise NotImplementedError('Use implementor.')
119
120    def __iter__(self) -> typing.Iterator[afscgap.model.Record]:
121        """Indicate that this Cursor can be iterated on.
122
123        Returns:
124            This object as an iterator.
125        """
126        return self
127
128    def __next__(self) -> afscgap.model.Record:
129        """Get the next value for this Cursor inside an interator operation.
130
131        Returns:
132            The next value waiting if cached in the cursor's results queue or
133            as just retrieved from a new page gathered by HTTP request.
134
135        Raises:
136            StopIteration: Raised if no data remain.
137        """
138        next_maybe = self.get_next()
139        if next_maybe is not None:
140            return next_maybe
141        else:
142            raise StopIteration()
class Cursor(typing.Iterable[afscgap.model.Record]):
 20class Cursor(typing.Iterable[afscgap.model.Record]):
 21    """Interface for objects allowing generation / retrieval of records."""
 22
 23    def get_base_url(self) -> str:
 24        """Get the URL at which the first page of query results can be found.
 25
 26        Returns:
 27            The URL for the query without pagination information.
 28        """
 29        raise NotImplementedError('Use implementor.')
 30
 31    def get_limit(self) -> OPT_INT:
 32        """Get the page size limit.
 33
 34        Returns:
 35            The maximum number of records to return per page.
 36        """
 37        raise NotImplementedError('Use implementor.')
 38
 39    def get_start_offset(self) -> OPT_INT:
 40        """Get the number of inital records to ignore.
 41
 42        Returns:
 43            The number of records being skipped at the start of the result set.
 44        """
 45        raise NotImplementedError('Use implementor.')
 46
 47    def get_filtering_incomplete(self) -> bool:
 48        """Determine if this cursor is silently filtering incomplete records.
 49
 50        Returns:
 51            Flag indicating if incomplete records should be silently filtered.
 52            If true, they will not be returned during iteration and placed in
 53            the queue at get_invalid(). If false, they will be returned and
 54            those incomplete records' get_complete() will return false.
 55        """
 56        raise NotImplementedError('Use implementor.')
 57
 58    def get_page_url(self, offset: OPT_INT = None,
 59        limit: OPT_INT = None) -> str:
 60        """Get a URL at which a page can be found using this cursor's base url.
 61
 62        Args:
 63            offset: The number of records to skip prior to the page.
 64            limit: The maximum number of records to return in the page.
 65        Returns:
 66            URL at which the requested page can be found.
 67        """
 68        raise NotImplementedError('Use implementor.')
 69
 70    def get_page(self, offset: OPT_INT = None,
 71        limit: OPT_INT = None,
 72        ignore_invalid: bool = False) -> typing.List[afscgap.model.Record]:
 73        """Get a page using this cursor's base url.
 74
 75        Args:
 76            offset: The number of records to skip prior to the page.
 77            limit: The maximum number of records to return in the page.
 78            ignore_invalid: Flag indicating how to handle invalid records. If
 79                true, will silently throw away records which could not be
 80                parsed. If false, will raise an exception if a record can not
 81                be parsed.
 82
 83        Returns:
 84            Results from the page which, regardless of ignore_invalid, may
 85            contain a mixture of complete and incomplete records.
 86        """
 87        raise NotImplementedError('Use implementor.')
 88
 89    def get_invalid(self) -> 'queue.Queue[dict]':
 90        """Get a queue of invalid / incomplete records found so far.
 91
 92        Returns:
 93            Queue with dictionaries containing the raw data returned from the
 94            API that did not have valid values for all required fields. Note
 95            that this will include incomplete records as well if
 96            get_filtering_incomplete() is true and will not contain incomplete
 97            records otherwise.
 98        """
 99        raise NotImplementedError('Use implementor.')
100
101    def to_dicts(self) -> typing.Iterable[dict]:
102        """Create an iterator which converts Records to dicts.
103
104        Returns:
105            Iterator which returns dictionaries instead of Record objects but
106            has otherwise the same beahavior as iterating in this Cursor
107            directly.
108        """
109        raise NotImplementedError('Use implementor.')
110
111    def get_next(self) -> typing.Optional[afscgap.model.Record]:
112        """Get the next value for this Cursor.
113
114        Returns:
115            The next value waiting if cached in the cursor's results queue or
116            as just retrieved from a new page gathered by HTTP request. Will
117            return None if no remain.
118        """
119        raise NotImplementedError('Use implementor.')
120
121    def __iter__(self) -> typing.Iterator[afscgap.model.Record]:
122        """Indicate that this Cursor can be iterated on.
123
124        Returns:
125            This object as an iterator.
126        """
127        return self
128
129    def __next__(self) -> afscgap.model.Record:
130        """Get the next value for this Cursor inside an interator operation.
131
132        Returns:
133            The next value waiting if cached in the cursor's results queue or
134            as just retrieved from a new page gathered by HTTP request.
135
136        Raises:
137            StopIteration: Raised if no data remain.
138        """
139        next_maybe = self.get_next()
140        if next_maybe is not None:
141            return next_maybe
142        else:
143            raise StopIteration()

Interface for objects allowing generation / retrieval of records.

def get_base_url(self) -> str:
23    def get_base_url(self) -> str:
24        """Get the URL at which the first page of query results can be found.
25
26        Returns:
27            The URL for the query without pagination information.
28        """
29        raise NotImplementedError('Use implementor.')

Get the URL at which the first page of query results can be found.

Returns:

The URL for the query without pagination information.

def get_limit(self) -> Optional[int]:
31    def get_limit(self) -> OPT_INT:
32        """Get the page size limit.
33
34        Returns:
35            The maximum number of records to return per page.
36        """
37        raise NotImplementedError('Use implementor.')

Get the page size limit.

Returns:

The maximum number of records to return per page.

def get_start_offset(self) -> Optional[int]:
39    def get_start_offset(self) -> OPT_INT:
40        """Get the number of inital records to ignore.
41
42        Returns:
43            The number of records being skipped at the start of the result set.
44        """
45        raise NotImplementedError('Use implementor.')

Get the number of inital records to ignore.

Returns:

The number of records being skipped at the start of the result set.

def get_filtering_incomplete(self) -> bool:
47    def get_filtering_incomplete(self) -> bool:
48        """Determine if this cursor is silently filtering incomplete records.
49
50        Returns:
51            Flag indicating if incomplete records should be silently filtered.
52            If true, they will not be returned during iteration and placed in
53            the queue at get_invalid(). If false, they will be returned and
54            those incomplete records' get_complete() will return false.
55        """
56        raise NotImplementedError('Use implementor.')

Determine if this cursor is silently filtering incomplete records.

Returns:

Flag indicating if incomplete records should be silently filtered. If true, they will not be returned during iteration and placed in the queue at get_invalid(). If false, they will be returned and those incomplete records' get_complete() will return false.

def get_page_url(self, offset: Optional[int] = None, limit: Optional[int] = None) -> str:
58    def get_page_url(self, offset: OPT_INT = None,
59        limit: OPT_INT = None) -> str:
60        """Get a URL at which a page can be found using this cursor's base url.
61
62        Args:
63            offset: The number of records to skip prior to the page.
64            limit: The maximum number of records to return in the page.
65        Returns:
66            URL at which the requested page can be found.
67        """
68        raise NotImplementedError('Use implementor.')

Get a URL at which a page can be found using this cursor's base url.

Arguments:
  • offset: The number of records to skip prior to the page.
  • limit: The maximum number of records to return in the page.
Returns:

URL at which the requested page can be found.

def get_page( self, offset: Optional[int] = None, limit: Optional[int] = None, ignore_invalid: bool = False) -> List[afscgap.model.Record]:
70    def get_page(self, offset: OPT_INT = None,
71        limit: OPT_INT = None,
72        ignore_invalid: bool = False) -> typing.List[afscgap.model.Record]:
73        """Get a page using this cursor's base url.
74
75        Args:
76            offset: The number of records to skip prior to the page.
77            limit: The maximum number of records to return in the page.
78            ignore_invalid: Flag indicating how to handle invalid records. If
79                true, will silently throw away records which could not be
80                parsed. If false, will raise an exception if a record can not
81                be parsed.
82
83        Returns:
84            Results from the page which, regardless of ignore_invalid, may
85            contain a mixture of complete and incomplete records.
86        """
87        raise NotImplementedError('Use implementor.')

Get a page using this cursor's base url.

Arguments:
  • offset: The number of records to skip prior to the page.
  • limit: The maximum number of records to return in the page.
  • ignore_invalid: Flag indicating how to handle invalid records. If true, will silently throw away records which could not be parsed. If false, will raise an exception if a record can not be parsed.
Returns:

Results from the page which, regardless of ignore_invalid, may contain a mixture of complete and incomplete records.

def get_invalid(self) -> queue.Queue[dict]:
89    def get_invalid(self) -> 'queue.Queue[dict]':
90        """Get a queue of invalid / incomplete records found so far.
91
92        Returns:
93            Queue with dictionaries containing the raw data returned from the
94            API that did not have valid values for all required fields. Note
95            that this will include incomplete records as well if
96            get_filtering_incomplete() is true and will not contain incomplete
97            records otherwise.
98        """
99        raise NotImplementedError('Use implementor.')

Get a queue of invalid / incomplete records found so far.

Returns:

Queue with dictionaries containing the raw data returned from the API that did not have valid values for all required fields. Note that this will include incomplete records as well if get_filtering_incomplete() is true and will not contain incomplete records otherwise.

def to_dicts(self) -> Iterable[dict]:
101    def to_dicts(self) -> typing.Iterable[dict]:
102        """Create an iterator which converts Records to dicts.
103
104        Returns:
105            Iterator which returns dictionaries instead of Record objects but
106            has otherwise the same beahavior as iterating in this Cursor
107            directly.
108        """
109        raise NotImplementedError('Use implementor.')

Create an iterator which converts Records to dicts.

Returns:

Iterator which returns dictionaries instead of Record objects but has otherwise the same beahavior as iterating in this Cursor directly.

def get_next(self) -> Optional[afscgap.model.Record]:
111    def get_next(self) -> typing.Optional[afscgap.model.Record]:
112        """Get the next value for this Cursor.
113
114        Returns:
115            The next value waiting if cached in the cursor's results queue or
116            as just retrieved from a new page gathered by HTTP request. Will
117            return None if no remain.
118        """
119        raise NotImplementedError('Use implementor.')

Get the next value for this Cursor.

Returns:

The next value waiting if cached in the cursor's results queue or as just retrieved from a new page gathered by HTTP request. Will return None if no remain.