Skip to content

Commit

Permalink
Allow EarthRanger client to be inited from a token (#287)
Browse files Browse the repository at this point in the history
  • Loading branch information
atmorling authored Oct 18, 2024
1 parent 819e6b7 commit b8dd977
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 11 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ jobs:
# https://github.com/mamba-org/setup-micromamba/issues/227
micromamba-version: 1.5.10-0
environment-file: ${{ matrix.env }}
cache-environment: true
cache-downloads: true

- name: Test
env:
Expand Down
23 changes: 23 additions & 0 deletions ecoscope/io/async_earthranger.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import ecoscope
from ecoscope.io.utils import to_hex
from ecoscope.io.earthranger_utils import clean_kwargs, to_gdf, clean_time_cols
from erclient.client import ERClientException, ERClientNotFound

try:
from erclient.client import AsyncERClient
Expand All @@ -30,6 +31,28 @@ def __init__(self, sub_page_size=4000, tcp_limit=5, **kwargs):
kwargs["client_id"] = kwargs.get("client_id", "das_web_client")
super().__init__(**kwargs)

@classmethod
async def create(cls, **kwargs):
client = cls(**kwargs)

await client._init_client()
return client

async def _init_client(self):
if not self.auth:
try:
await self.login()
except ERClientNotFound:
raise ERClientNotFound("Failed login. Check Stack Trace for specific reason.")
else:
try:
await self.get_me()
except ERClientException:
raise ERClientException("Authorization token is invalid or expired.")

async def get_me(self):
return await self._get("user/me", params={})

async def get_sources(
self,
manufacturer_id=None,
Expand Down
19 changes: 13 additions & 6 deletions ecoscope/io/earthranger.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,29 @@ def __init__(self, sub_page_size=4000, tcp_limit=5, **kwargs):
self.tcp_limit = tcp_limit
kwargs["client_id"] = kwargs.get("client_id", "das_web_client")
super().__init__(**kwargs)
try:
self.login()
except ERClientNotFound:
raise ERClientNotFound("Failed login. Check Stack Trace for specific reason.")

if not self.auth:
try:
self.login()
except ERClientNotFound:
raise ERClientNotFound("Failed login. Check Stack Trace for specific reason.")
else:
try:
self.get_me()
except ERClientException:
raise ERClientException("Authorization token is invalid or expired.")

def _token_request(self, payload):
response = requests.post(self.token_url, data=payload)
if response.ok:
self.auth = json.loads(response.text)
self.auth = response.json()
expires_in = int(self.auth["expires_in"]) - 5 * 60
self.auth_expires = pytz.utc.localize(datetime.datetime.utcnow()) + datetime.timedelta(seconds=expires_in)
return True

self.auth = None
self.auth_expires = pytz.utc.localize(datetime.datetime.min)
raise ERClientNotFound(json.loads(response.text)["error_description"])
raise ERClientNotFound(response.json().get("error_description", "invalid token"))

"""
GET Functions
Expand Down
41 changes: 38 additions & 3 deletions tests/test_asyncearthranger_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import pandas as pd
import pytest
import pytest_asyncio
import ecoscope
from erclient import ERClientException

if not pytest.earthranger:
pytest.skip(
Expand All @@ -11,12 +13,12 @@
)


@pytest.fixture
def er_io_async():
@pytest_asyncio.fixture
async def er_io_async():
ER_SERVER = "https://mep-dev.pamdas.org"
ER_USERNAME = os.getenv("ER_USERNAME")
ER_PASSWORD = os.getenv("ER_PASSWORD")
er_io = ecoscope.io.AsyncEarthRangerIO(server=ER_SERVER, username=ER_USERNAME, password=ER_PASSWORD)
er_io = await ecoscope.io.AsyncEarthRangerIO.create(server=ER_SERVER, username=ER_USERNAME, password=ER_PASSWORD)

return er_io

Expand Down Expand Up @@ -251,3 +253,36 @@ async def test_display_map(er_io_async):
await er_io_async.get_event_type_display_name(event_type="shot_rep", event_property="shotrep_timeofshot")
== "Time when shot was heard"
)


@pytest.mark.asyncio
async def test_existing_token(er_io_async):
await er_io_async.login()
new_client = ecoscope.io.AsyncEarthRangerIO(
service_root=er_io_async.service_root,
token_url=er_io_async.token_url,
token=er_io_async.auth.get("access_token"),
)

sources = await new_client.get_sources_dataframe()
assert not sources.empty


@pytest.mark.asyncio
async def test_existing_token_expired(er_io_async):
await er_io_async.login()
token = er_io_async.auth.get("access_token")
await er_io_async.refresh_token()

new_client = ecoscope.io.AsyncEarthRangerIO(
service_root=er_io_async.service_root, token_url=er_io_async.token_url, token=token
)

with pytest.raises(ERClientException):
await new_client.get_sources_dataframe()


@pytest.mark.asyncio
async def test_get_me(er_io_async):
me = await er_io_async.get_me()
assert me.get("username")
21 changes: 21 additions & 0 deletions tests/test_earthranger_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from shapely.geometry import Point

import ecoscope
from erclient import ERClientException

if not pytest.earthranger:
pytest.skip(
Expand Down Expand Up @@ -291,3 +292,23 @@ def test_get_subjects_chunking(er_io):
chunked_request_result = er_io.get_subjects(id=subject_ids, max_ids_per_request=1)

pd.testing.assert_frame_equal(single_request_result, chunked_request_result)


def test_existing_token(er_io):
new_client = ecoscope.io.EarthRangerIO(
service_root=er_io.service_root, token_url=er_io.token_url, token=er_io.auth.get("access_token")
)

events = new_client.get_patrol_events(
since=pd.Timestamp("2017-01-01").isoformat(),
until=pd.Timestamp("2017-04-01").isoformat(),
)
assert not events.empty


def test_existing_token_expired(er_io):
token = er_io.auth.get("access_token")
er_io.refresh_token()

with pytest.raises(ERClientException, match="Authorization token is invalid or expired."):
ecoscope.io.EarthRangerIO(service_root=er_io.service_root, token_url=er_io.token_url, token=token)

0 comments on commit b8dd977

Please sign in to comment.