Skip to content
5 changes: 3 additions & 2 deletions src/pysofar/sofar.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,19 +574,20 @@ def __str__(self):


# ---------------------------------- Util Functions -------------------------------------- #
def get_and_update_spotters(_api=None):
def get_and_update_spotters(_api=None, _processes=None):
"""
:return: A list of the Spotter objects associated with this account
"""
from itertools import repeat

api = _api or SofarApi()
processes = _processes or 16

# grab device id's and query for device data
# initialize Spotter objects
spot_data = api.devices

pool = ThreadPool(processes=16)
pool = ThreadPool(processes=processes)
spotters = pool.starmap(_spot_worker, zip(spot_data, repeat(api)))
pool.close()

Expand Down
55 changes: 31 additions & 24 deletions tests/test_sofar_api_class.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
"""
This file is part of pysofar: A client for interfacing with Sofar Oceans Spotter API
This file is part of pysofar:
A client for interfacing with Sofar Ocean Technologies Spotter API

Contents: Tests for device endpoints

Copyright (C) 2019
Copyright (C) 2019-2023
Sofar Ocean Technologies

Authors: Mike Sosa
Authors: Mike Sosa et al
"""
import os
import pytest

from pysofar import wavefleet_exceptions
from pysofar.sofar import SofarApi
from unittest.mock import patch

# try to read custom token from environment.
# if absent, default to hard-coded value in this source module
custom_token = os.getenv('PYSOFAR_CUSTOM_TOKEN', 'custom_api_token_here')
custom_spotter_id = os.getenv('PYSOFAR_TEST_SPOTTER_ID', 'SPOT-30344R')

# The custom token will fail to authenticate so use a mock to bypass the `_sync step`
with patch.object(SofarApi, '_sync', return_value=None) as mock_method:
custom_api = SofarApi(custom_token='custom_api_token_here')
custom_token = os.getenv('PYSOFAR_CUSTOM_TOKEN', 'custom_api_token_here')
custom_api = SofarApi(custom_token=custom_token)

def test_custom_api():
# test that custom api token is set
assert custom_api.token == 'custom_api_token_here'

assert custom_api.token == custom_token

api = SofarApi()
latest_dat = api.get_latest_data('SPOT-0350', include_wind_data=True)

latest_dat = api.get_latest_data(custom_spotter_id, include_wind_data=True)

def test_get_latest_data():
# test basic that latest_data is able to be queried
Expand All @@ -41,16 +48,16 @@ def test_get_and_update_spotters():
from pysofar.spotter import Spotter
from pysofar.sofar import get_and_update_spotters

sptrs = get_and_update_spotters(_api=api)
sptrs = get_and_update_spotters(_api=api, _processes=2)

assert sptrs is not None
assert all(map(lambda x: isinstance(x, Spotter), sptrs))


def test_get_all_wave_data():
# Test that all wave data is able to be queried in a time range
st = '2019-05-02'
end = '2019-07-10'
st = '2023-05-02'
end = '2023-05-10'
dat = api.get_wave_data(start_date=st, end_date=end)

assert dat is not None
Expand All @@ -61,42 +68,41 @@ def test_get_all_wave_data():

def test_get_all_wind_data():
# Test that all wind data over all time is able to be queried
st = '2021-05-02'
end = '2021-07-10'
st = '2023-05-02'
end = '2023-05-10'
dat = api.get_wind_data(start_date=st, end_date=end)

assert dat is not None
assert isinstance(dat, dict)
assert 'wind' in dat
assert len(dat['wind']) > 0


def test_get_all_tracking_data():
# Test that all tracking data is able to be queried in a time range
st = '2021-05-02'
end = '2021-06-10'
st = '2023-05-02'
end = '2023-05-10'
dat = api.get_track_data(start_date=st, end_date=end)

assert dat is not None
assert isinstance(dat, dict)
assert 'track' in dat
assert len(dat['track']) > 0


@pytest.mark.xfail(reason="A Spotter will return no frequency data if it was not in Waves:Spectrum")
def test_get_all_frequency_data():
# Test that all frequency data is able to be queried in a time range
st = '2021-06-08'
end = '2021-06-10'
st = '2022-07-26'
end = '2022-08-04'
dat = api.get_frequency_data(start_date=st, end_date=end)

print(dat.keys())
assert dat is not None
assert isinstance(dat, dict)
assert 'frequency' in dat
assert len(dat['frequency']) > 0


def test_get_all_data():
# Test that grabbing data from all spotters from all data types works
# Test that grabbing data from all Spotters from all data types works
st = '2019-01-18'
end = '2019-01-25'

Expand All @@ -112,12 +118,13 @@ def test_get_all_data():

def test_get_sensor_data():
# Test that getting sensor data in a time range works
spotter_id = 'SPOT-9999'
st = '2021-07-18'
end = '2021-07-19'
spotter_id = 'SPOT-30081D'
st = '2022-08-01'
end = '2022-08-02'

dat = api.get_sensor_data(spotter_id, start_date=st, end_date=end)

assert dat is not None
print(dat)
assert 'sensorPosition' in dat[-1]

24 changes: 13 additions & 11 deletions tests/test_spotter_class.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
"""
This file is part of pysofar: A client for interfacing with Sofar Oceans Spotter API
This file is part of pysofar:
A client for interfacing with Sofar Ocean Technologies Spotter API

Contents: Tests for device endpoints

Copyright (C) 2019
Copyright (C) 2019-2023
Sofar Ocean Technologies

Authors: Mike Sosa
Authors: Mike Sosa et al
"""
import os
import pytest

from pysofar.sofar import SofarApi
from pysofar.spotter import Spotter

api = SofarApi()

device = Spotter('SPOT-0350', '')

device = Spotter(os.getenv('PYSOFAR_TEST_SPOTTER_ID', 'SPOT-30344R'), '', session = api)

def test_spotter_update():
# tests the spotter updates correctly
# tests the Spotter updates correctly
device.update()

assert device.mode is not None
Expand Down Expand Up @@ -67,18 +70,17 @@ def test_spotter_edit():


def test_spotter_mode():
# test the spotter mode property is set correctly
# test the Spotter mode property is set correctly
device.mode = 'track'
assert device.mode == 'tracking'

device.mode = 'full'
assert device.mode == 'waves_spectrum'


def test_spotter_grab_data():
# test spotter can correctly grab data
@pytest.mark.xfail(reason="will fail if device is not owned by the token making the request")
def test_spotter_grab_data_with_limit():
# test Spotter can correctly grab data with limit
dat = device.grab_data(limit=20)
print(dat)

assert 'waves' in dat
assert len(dat['waves']) <= 20
45 changes: 23 additions & 22 deletions tests/test_wave_query_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@

Contents: Tests for device endpoints

Copyright (C) 2019
Copyright (C) 2019-2023
Sofar Ocean Technologies

Authors: Mike Sosa
Authors: Mike Sosa et al
"""
import os

from pysofar.sofar import WaveDataQuery

st = '2019-05-02'
end = '2019-05-10'
q = WaveDataQuery('SPOT-0350', limit=100, start_date=st, end_date=end)
st = '2023-05-02'
end = '2023-05-10'
q = WaveDataQuery(os.getenv('PYSOFAR_TEST_SPOTTER_ID', 'SPOT-30344R'), limit=100, start_date=st, end_date=end)
q.wind(True)


Expand All @@ -28,7 +30,7 @@ def test_query_execute():


def test_query_no_dates():
# resturned latest data first
# returned latest data first
q.limit(10)
q.clear_start_date()
q.clear_end_date()
Expand All @@ -42,7 +44,7 @@ def test_query_no_dates():


def test_query_no_start():
# resturned
# returned
q.limit(10)

q.clear_start_date()
Expand Down Expand Up @@ -70,18 +72,17 @@ def test_query_no_end():
assert 'waves' in response
assert 'wind' in response

# TODO: need to get a viable spotter for testing
# def test_query_surface_temp():
# q.surface_temp(True)
# q.limit = 10
#
# q.clear_end_date()
# response = q.execute()
# q.set_start_date(st)
#
# assert response is not None
# assert isinstance(response, dict)
#
# assert 'waves' in response
# assert 'wind' in response
# assert 'surfaceTemp' in response
def test_query_surface_temp():
q.surface_temp(True)
q.limit = 10

q.clear_end_date()
response = q.execute()
q.set_start_date(st)

assert response is not None
assert isinstance(response, dict)

assert 'waves' in response
assert 'wind' in response
assert 'surfaceTemp' in response