Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

One-time version check #1456

Merged
merged 17 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 13 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
20 changes: 19 additions & 1 deletion integrations/client/test_delphi_epidata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

# standard library
import time
import json
from json import JSONDecodeError
from requests.models import Response
from unittest.mock import MagicMock, patch

# first party
Expand Down Expand Up @@ -306,6 +306,24 @@ def test_sandbox(self, get, post):
Epidata.debug = False
Epidata.sandbox = False

@patch('requests.get')
def test_version_check(self, get):
"""Test that in debug + sandbox mode request params are correctly logged, but no queries are sent."""
class MockJson:
def __init__(self, content, status_code):
self.content = content
self.status_code = status_code
def raise_for_status(self): pass
def json(self): return json.loads(self.content)
get.reset_mock()
get.return_value = MockJson(b'{"info": {"version": "0.0.1"}}', 200)
Epidata._version_check()
captured = self.capsys.readouterr()
output = captured.err.splitlines()
self.assertEqual(len(output), 1)
self.assertIn("Client version not up to date", output[0])
self.assertIn("\'latest_version\': \'0.0.1\'", output[0])

def test_geo_value(self):
"""test different variants of geo types: single, *, multi."""

Expand Down
17 changes: 15 additions & 2 deletions src/client/delphi_epidata.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ class Epidata:
BASE_URL = "https://api.delphi.cmu.edu/epidata"
auth = None

client_version = __version__

debug = False # if True, prints extra logging statements
sandbox = False # if True, will not execute any queries

Expand All @@ -54,6 +52,21 @@ def log(evt, **kwargs):
kwargs['timestamp'] = time.strftime("%Y-%m-%d %H:%M:%S %z")
return sys.stderr.write(str(kwargs) + "\n")

# One-time check to verify the client version is up to date.
@staticmethod
def _version_check():
try:
latest_version = requests.get('https://pypi.org/pypi/delphi-epidata/json').json()['info']['version']
if latest_version != __version__:
Epidata.log(
"Client version not up to date",
client_version=__version__,
latest_version=latest_version
)
except Exception as e:
Epidata.log("Error getting latest client version", exception=str(e))
_version_check.__func__() # run this once on module load
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Python <= 3.9, static methods cannot be directly called within the class body.
In Python >= 3.10, it works as you'd expect: _version_check()

Copy link
Contributor

@dshemetov dshemetov Jul 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_version_check.__func__() # run this once on module load
# Run this once on module load. Use dunder method for Python <= 3.9 compatibility
# https://stackoverflow.com/a/12718272
_version_check.__func__()

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plz also add newline above function call!

would it be any better/easier to avoid this pattern here and just call Epidata._version_check() at the end of the file (after the class definition)?


# Helper function to cast values and/or ranges to strings
@staticmethod
def _listitem(value):
Expand Down
Loading