Skip to content
Open
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
103 changes: 70 additions & 33 deletions erclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -886,16 +886,38 @@ def get_source_provider(self, provider_key):

return None

def get_subject_tracks(self, subject_id='', start=None, end=None):
def get_subject_tracks(self, subject_id='', start=None, end=None, version='1.0', **kwargs):
"""
Get the latest tracks for the Subject having the given subject_id.

Comment on lines +889 to +892
:param subject_id: The UUID of the subject.
:param start: datetime lower-bound filter (sent as ``since``).
:param end: datetime upper-bound filter (sent as ``until``).
:param version: API version string, either '1.0' (default, legacy flat
coordinates) or '2.0' (segmented GeoJSON FeatureCollection).
:param kwargs: Extra query params forwarded to the v2 endpoint such as
``show_excluded``, ``group_by_flags``, ``max_speed_kmh``,
``max_gap_ms``, ``max_gap_seconds``, ``max_gap_minutes``.
:return: Track data (format varies by version).
"""
p = {}
if start is not None and isinstance(start, datetime):
p['since'] = start.isoformat()
if end is not None and isinstance(end, datetime):
p['until'] = end.isoformat()

if version == '2.0':
# v2 supports additional filter params
for key in ('show_excluded', 'group_by_flags', 'max_speed_kmh',
'max_gap_ms', 'max_gap_seconds', 'max_gap_minutes'):
if key in kwargs:
p[key] = kwargs[key]
return self._get(
path=f'subject/{subject_id}/tracks/',
base_url=self._api_root('v2.0'),
params=p,
)

return self._get(path='subject/{0}/tracks'.format(subject_id), params=p)
Comment on lines +889 to 921

def get_subject_source_tracks(self, subject_id='', src_id='', start=None):
Expand Down Expand Up @@ -1601,6 +1623,53 @@ async def get_source_assignments(self, subject_ids: List[str] = None, source_ids

return await self._get(f'subjectsources', params=params)

async def get_subject_tracks(self, subject_id='', start=None, end=None, version='1.0', **kwargs):
"""
Get tracks for the Subject having the given subject_id.

:param subject_id: The UUID of the subject.
:param start: datetime lower-bound filter (sent as ``since``).
:param end: datetime upper-bound filter (sent as ``until``).
:param version: API version string, either '1.0' (default, legacy flat
coordinates) or '2.0' (segmented GeoJSON FeatureCollection).
:param kwargs: Extra query params forwarded to the v2 endpoint such as
``show_excluded``, ``group_by_flags``, ``max_speed_kmh``,
``max_gap_ms``, ``max_gap_seconds``, ``max_gap_minutes``.
:return: Track data (format varies by version).
"""
p = {}
if start is not None and isinstance(start, datetime):
p['since'] = start.isoformat()
if end is not None and isinstance(end, datetime):
p['until'] = end.isoformat()

if version == '2.0':
for key in ('show_excluded', 'group_by_flags', 'max_speed_kmh',
'max_gap_ms', 'max_gap_seconds', 'max_gap_minutes'):
if key in kwargs:
p[key] = kwargs[key]
return await self._get(
path=f'subject/{subject_id}/tracks/',
base_url=self._api_root('v2.0'),
params=p,
)

return await self._get(path=f'subject/{subject_id}/tracks', params=p)

Comment on lines +1646 to +1658
async def get_subject_source_tracks(self, subject_id='', src_id='', start=None):
"""
Get the latest tracks for the Subject having the given subject_id and a source ID.

:param subject_id: The subject UUID
:param src_id: The source UUID
:param start: Optional datetime lower-bound filter (sent as ``since``)
:return: Track data
"""
p = {}
if start and isinstance(start, datetime):
p['since'] = start.isoformat()
return await self._get(path=f'subject/{subject_id}/source/{src_id}/tracks', params=p)

async def get_feature_group(self, feature_group_id: str):
"""
Get a feature group by id
Expand Down Expand Up @@ -1646,38 +1715,6 @@ async def _get_data(self, endpoint, params, batch_size=0):
async def _get(self, path, base_url=None, params=None):
return await self._call(path=path, payload=None, method="GET", params=params, base_url=base_url)

async def _delete(self, path):
"""Issue DELETE request. Returns True on success; raises ERClient* on error."""
try:
auth_headers = await self.auth_headers()
except httpx.HTTPStatusError as e:
self._handle_http_status_error(path, "DELETE", e)
headers = {'User-Agent': self.user_agent, **auth_headers}
if not path.startswith('http'):
path = self._er_url(path)
try:
response = await self._http_session.delete(path, headers=headers)
except httpx.RequestError as e:
reason = str(e)
self.logger.error('Request to ER failed', extra=dict(provider_key=self.provider_key,
url=path,
reason=reason))
raise ERClientException(f'Request to ER failed: {reason}')
if response.is_success:
return True
if response.status_code == 404:
self.logger.error("404 when calling %s", path)
raise ERClientNotFound()
if response.status_code == 403:
try:
reason = response.json().get('status', {}).get('detail', 'unknown reason')
except Exception:
reason = 'unknown reason'
raise ERClientPermissionDenied(reason)
raise ERClientException(
f'Failed to delete: {response.status_code} {response.text}'
)

async def get_file(self, url):
"""
Download a file (e.g. attachment URL). Returns the httpx response; body is read into memory.
Expand Down
Loading
Loading