Skip to content

Commit

Permalink
WIP3
Browse files Browse the repository at this point in the history
  • Loading branch information
mattrayner committed Feb 11, 2024
1 parent 7e1f793 commit c1f6116
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 25 deletions.
10 changes: 0 additions & 10 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ on:
branches:
- main
- dev
tags:
- '*'

jobs:
tests:
Expand Down Expand Up @@ -39,11 +37,3 @@ jobs:
with:
name: code-coverage-report
path: htmlcov/*
- name: Build release package
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
run: make package
- name: Publish package
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
44 changes: 44 additions & 0 deletions .github/workflows/tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Push actions

on:
push:
tags:
- '*'

jobs:
tests:
runs-on: "ubuntu-latest"
name: Test and release
steps:
- name: Check out code from GitHub
uses: "actions/checkout@v3"
- name: Setup Python
uses: "actions/setup-python@v4"
with:
python-version: "3.10"
- name: Install requirements
run: python3 -m pip install -r requirements_test.txt -r requirements_release.txt
- name: Run tests
run: |
python3 -m pytest \
-vv \
-qq \
--timeout=9 \
--durations=10 \
--cov podpointclient \
--cov-report term \
--cov-report html \
-o console_output_style=count \
-p no:sugar \
tests
- name: Archive code coverage results
uses: actions/upload-artifact@v3
with:
name: code-coverage-report
path: htmlcov/*
- name: Build release package
run: make package
- name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Pod Point Client Changelog

## v1.5.0

* Add support for refreshing expired tokens, rather than grabbing new ones each time
* Update example.py to demonstrate token expiry

## v1.4.3

* Remove additional / from pod point api calls
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ package:
python3 setup.py sdist

publish: clean package
twine upload dist/* --verbose
twine upload dist/* --verbose
22 changes: 19 additions & 3 deletions example.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import datetime, timedelta
from podpointclient.client import PodPointClient
import asyncio
import aiohttp
Expand All @@ -19,10 +20,14 @@ async def main(username: str, password: str, http_debug: bool = False, loop=None

# Verify credentials work
verified = await client.async_credentials_verified()
print(f" Credentials verified: {verified}")
print(f"Credentials verified: {verified}")
print(f" Token expiry: {client.auth.access_token_expiry}")

print("Sleeping 2s")
time.sleep(2)

print("Getting user details")
# Get user information
print("Getting user details")
user = await client.async_get_user()
print(f" Account balance {user.account.balance}p")

Expand All @@ -35,7 +40,7 @@ async def main(username: str, password: str, http_debug: bool = False, loop=None
pod = pods[0]
print(f"Selecting first pod: {pod.ppid}")

# Get firmware information for the pod
# Get firmware information for the pod
firmwares = await client.async_get_firmware(pod=pod)
firmware = firmwares[0]
print(f"Gettnig firmware data for {pod.ppid}")
Expand All @@ -58,6 +63,17 @@ async def main(username: str, password: str, http_debug: bool = False, loop=None
energy_used = charges[0].kwh_used
print(f" kW charged: {energy_used}")

# Expire token and exchange a refresh
print("Expiring token and refreshing...")
client.auth.access_token_expiry = datetime.now() - timedelta(minutes=10)
updated = await client.auth.async_update_access_token()
print(f" Token updated? {updated} - New expiry: {client.auth.access_token_expiry}")

# Get user information again
print("Getting user details with new token")
user = await client.async_get_user()
print(f" Account balance {user.account.balance}p")

if __name__ == "__main__":
import time
import argparse
Expand Down
27 changes: 27 additions & 0 deletions podpointclient/helpers/api_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,23 @@ async def post(
headers=headers,
exception_class=exception_class
)
async def post_form_data(
self,
url: str,
body: Any,
headers: Dict[str, Any],
params: Dict[str, Any] = None,
exception_class=APIError
) -> aiohttp.ClientResponse:
"""Make a POST request"""
return await self.__wrapper(
method="post_data",
url=url,
params=params,
data=body,
headers=headers,
exception_class=exception_class
)

async def delete(
self,
Expand Down Expand Up @@ -132,6 +149,16 @@ async def __wrapper(
json=data
)

# ToDo: Fix this, we need to look again at the pattern for this, maybe determine based on data type?
# THIS REALLY SMELLS
elif method == "post_data":
response = await self._session.post(
url,
headers=headers,
params=params,
data=data
)

elif method == "delete":
response = await self._session.delete(url, headers=headers, params=params)

Expand Down
22 changes: 11 additions & 11 deletions podpointclient/helpers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,25 +101,25 @@ async def __update_access_token(self, refresh: bool = False) -> bool:

if refresh:
_LOGGER.debug('Refreshing access token')
url = f"{GOOGLE_TOKEN_BASE_URL}{TOKEN}"
body = f"grant_type=refresh_token&refresh_token={self.refresh_token}"
headers = HEADERS.copy()
headers["Content-type"] = 'application/x-www-form-urlencoded'

id_token_response = 'id_token'
refresh_token_response = 'refresh_token'
expires_in_response = 'expires_in'

response = await wrapper.post_form_data(
url=f"{GOOGLE_TOKEN_BASE_URL}{TOKEN}",
body=f"grant_type=refresh_token&refresh_token={self.refresh_token}",
headers=headers,
exception_class=AuthError)
else:
_LOGGER.debug('Getting a new access token')
url = f"{GOOGLE_BASE_URL}{PASSWORD_VERIFY}"
body = {"email": self.email, "returnSecureToken": True, "password": self.password}
headers = HEADERS.copy()

response = await wrapper.post(
url=url,
body=body,
headers=headers,
exception_class=AuthError)
response = await wrapper.post(
url=f"{GOOGLE_BASE_URL}{PASSWORD_VERIFY}",
body={"email": self.email, "returnSecureToken": True, "password": self.password},
headers=HEADERS,
exception_class=AuthError)

if response.status != 200:
await self.__handle_response_error(response, AuthError)
Expand Down

0 comments on commit c1f6116

Please sign in to comment.