Skip to content

Commit

Permalink
Merge pull request #18 from PH-KDX/async-rewrite
Browse files Browse the repository at this point in the history
v0.7.0
  • Loading branch information
PH-KDX authored Sep 5, 2022
2 parents 420a4f4 + b12aecd commit 3525b70
Show file tree
Hide file tree
Showing 21 changed files with 701 additions and 603 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_and_lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
unittests:
strategy:
matrix:
python-version: [ '3.7', '3.8', '3.9', '3.10' ]
python-version: [ '3.8', '3.9', '3.10']
runs-on: ubuntu-latest

name: Unit tests, Python ${{ matrix.python-version }}
Expand Down
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
# -- Project information -----------------------------------------------------

project = 'FlightplanDB-py'
copyright = '2021, PH-KDX'
copyright = '2022, PH-KDX'
author = 'PH-KDX'

# The full version, including alpha/beta/rc tags
release = '0.6.0'
release = '0.7.0'
# readthedocs.io insists on the version field being filled for epub builds
version = release

Expand Down
7 changes: 7 additions & 0 deletions docs/source/user/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Changelog
--------------------

0.7.0
^^^^^^^^^^^^^^^^^^^^
This is another complete rewrite of the library, in which it is entirely converted to async.
This should mean faster execution of parallel requests, and no blocking when called from
another async library. Support for Python 3.7 has been dropped in this release. Python 3.11
is not yet supported as aiohttp does not yet support Python 3.11 at the time of release.

0.6.0
^^^^^^^^^^^^^^^^^^^^
This is a complete rewrite of the library, which moves functions out of classes.
Expand Down
15 changes: 11 additions & 4 deletions docs/source/user/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ For more information on Flight Plan Database, see their excellent `About page <h

Prerequisites
^^^^^^^^^^^^^^^^^^^^
FlightplanDB-py works with Python 3.7 or higher. Python 3.6 or
lower is not supported due to dataclasses, which were introduced with
FlightplanDB-py is supported for Python 3.8 or higher. Python 3.7 would probably have worked with
the library, but is not officially supported; the absence of AsyncMock means that the unittests
will not execute.
Python 3.6 or lower will not work due to dataclasses, which were introduced with
`PEP 557 <https://www.python.org/dev/peps/pep-0557/>`_, being used in the library.

Installation
Expand Down Expand Up @@ -66,8 +68,9 @@ To test if the package has correctly installed, open a Python shell

.. code-block:: python3
import flightplandb
flightplandb.api.ping()
import flightplandb
import asyncio
asyncio.run(flightplandb.api.ping())
which should return
``StatusResponse(message='OK', errors=None)``
Expand All @@ -89,6 +92,10 @@ These calls, together with :meth:`flightplandb.api.ping()`, will not increment y
The limit for unauthenticated users is IP-based, and is currently set to 100.
The limit for authenticated users is key-based, and is currently set to 2500.

Please note that some functions which return an iterable, such as the user search or plan search,
can make multiple HTTP requests to fetch all the paginated information, thus increasing your request
count by more than 1.


.. _authentication:

Expand Down
78 changes: 40 additions & 38 deletions docs/source/user/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,46 @@ request limit from 100 to 2500.

.. code-block:: python
import flightplandb as fpdb
# obviously, substitute your own token
API_KEY = "VtF93tXp5IUZE307kPjijoGCUtBq4INmNTS4wlRG"
# list all users named lemon
for user in fpdb.user.search(username="lemon"):
print(user)
# fetch most relevant user named lemon
print(fpdb.user.fetch(username="lemon"))
# fetch first 20 of lemon's plans
lemon_plans = fpdb.user.plans(username="lemon", limit=20)
for plan in lemon_plans:
print(plan)
# define a query to search for all plans
query = fpdb.datatypes.PlanQuery(fromICAO="EHAM",
toICAO="EGLL")
# then search for the first three results of that query, sorted by distance
# the route is included, which requires authentication
resp = fpdb.plan.search(
plan_query=query,
include_route=True,
sort="distance"
limit=3,
key=API_KEY
)
# and print each result in the response
for i in resp:
print(i)
# fetch the weather for Schiphol Airport
print(fpdb.weather.fetch("EHAM"))
# then check remaining requests by subtracting the requests made from the total limit
print(fpdb.api.limit_cap-fpdb.api.limit_used)
import flightplandb as fpdb
import asyncio
# obviously, substitute your own token
API_KEY = "VtF93tXp5IUZE307kPjijoGCUtBq4INmNTS4wlRG"
async def main():
# list all users named lemon
async for user in fpdb.user.search(username="lemon"):
print(user)
# fetch most relevant user named lemon
print(await fpdb.user.fetch(username="lemon"))
# fetch first 20 of lemon's plans
lemon_plans = fpdb.user.plans(username="lemon", limit=20)
async for plan in lemon_plans:
print(plan)
# define a query to search for all plans
query = fpdb.datatypes.PlanQuery(fromICAO="EHAM",
toICAO="EGLL")
# then search for the first three results of that query, sorted by distance
# the route is included, which requires authentication
resp = fpdb.plan.search(
plan_query=query,
include_route=True,
sort="distance"
limit=3,
key=API_KEY
)
# and print each result in the response
async for i in resp:
print(i)
# fetch the weather for Schiphol Airport
print(await fpdb.weather.fetch("EHAM"))
# then check remaining requests by subtracting the requests made from the total limit
print((await fpdb.api.limit_cap())-(await fpdb.api.limit_used()))
Try saving this program in a file in your project directory and running it.
Experiment around with different commands to get a feel for the library.
Expand Down
3 changes: 2 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[pytest]
addopts = --disable-socket
addopts = --disable-socket
asyncio_mode=auto
18 changes: 8 additions & 10 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ def get_version(rel_path):
if line.startswith('__version__'):
delim = '"' if '"' in line else "'"
return line.split(delim)[1]
else:
raise RuntimeError("Unable to find version string.")
raise RuntimeError("Unable to find version string.")


setup(
Expand All @@ -38,26 +37,25 @@ def get_version(rel_path):
packages=find_packages(where="src"),
include_package_data=True,
install_requires=[
"requests==2.26.0",
"python-dateutil==2.8.2"
"aiohttp~=3.8.1",
"python-dateutil~=2.8.2"
],
extras_require={
"dev": [
"Sphinx==4.5.0",
"Sphinx==5.1.1",
"sphinx-rtd-theme==1.0.0"
],
"test": [
"pytest~=6.2.5",
"pytest-mock~=3.6.1",
"pytest_socket~=0.4.1"
"pytest~=7.1.3",
"pytest-socket~=0.5.1",
"pytest-asyncio~=0.19.0"
]
},
python_requires='>=3.7.0',
python_requires='>=3.8.0',
classifiers=[
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Intended Audience :: Developers",
"Natural Language :: English",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
Expand Down
2 changes: 1 addition & 1 deletion src/flightplandb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


# Version of the flightplandb package
__version__ = "0.6.0"
__version__ = "0.7.0"

from . import (
internal, exceptions, datatypes,
Expand Down
29 changes: 15 additions & 14 deletions src/flightplandb/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from flightplandb.datatypes import StatusResponse


def header_value(header_key: str, key: Optional[str] = None) -> str:
async def header_value(header_key: str, key: Optional[str] = None) -> str:
"""Gets header value for key. Do not call directly.
Parameters
Expand All @@ -20,11 +20,12 @@ def header_value(header_key: str, key: Optional[str] = None) -> str:
The value corresponding to the passed key
"""

headers = internal.get_headers(key=key) # Make 1 request to fetch headers
# Make 1 request to fetch headers
headers = await internal.get_headers(key=key)
return headers[header_key]


def version(key: Optional[str] = None) -> int:
async def version(key: Optional[str] = None) -> int:
"""API version that returned the response.
Parameters
Expand All @@ -38,10 +39,10 @@ def version(key: Optional[str] = None) -> int:
API version
"""

return int(header_value(header_key="X-API-Version", key=key))
return int(await header_value(header_key="X-API-Version", key=key))


def units(key: Optional[str] = None) -> str:
async def units(key: Optional[str] = None) -> str:
"""The units system used for numeric values.
https://flightplandatabase.com/dev/api#units
Expand All @@ -56,10 +57,10 @@ def units(key: Optional[str] = None) -> str:
AVIATION, METRIC or SI
"""

return header_value(header_key="X-Units", key=key)
return await header_value(header_key="X-Units", key=key)


def limit_cap(key: Optional[str] = None) -> int:
async def limit_cap(key: Optional[str] = None) -> int:
"""The number of requests allowed per day, operated on an hourly rolling
basis. i.e requests used between 19:00 and 20:00 will become available
again at 19:00 the following day. API key authenticated requests get a
Expand All @@ -77,10 +78,10 @@ def limit_cap(key: Optional[str] = None) -> int:
number of allowed requests per day
"""

return int(header_value(header_key="X-Limit-Cap", key=key))
return int(await header_value(header_key="X-Limit-Cap", key=key))


def limit_used(key: Optional[str] = None) -> int:
async def limit_used(key: Optional[str] = None) -> int:
"""The number of requests used in the current period
by the presented API key or IP address.
See :ref:`request-limits` for more details.
Expand All @@ -96,10 +97,10 @@ def limit_used(key: Optional[str] = None) -> int:
number of requests used in period
"""

return int(header_value(header_key="X-Limit-Used", key=key))
return int(await header_value(header_key="X-Limit-Used", key=key))


def ping(key: Optional[str] = None) -> StatusResponse:
async def ping(key: Optional[str] = None) -> StatusResponse:
"""Checks API status to see if it is up
Parameters
Expand All @@ -113,11 +114,11 @@ def ping(key: Optional[str] = None) -> StatusResponse:
OK 200 means the service is up and running.
"""

resp = internal.get(path="", key=key)
resp = await internal.get(path="", key=key)
return StatusResponse(**resp)


def revoke(key: str) -> StatusResponse:
async def revoke(key: str) -> StatusResponse:
"""Revoke the API key in use in the event it is compromised.
See :ref:`authentication` for more details.
Expand All @@ -138,5 +139,5 @@ def revoke(key: str) -> StatusResponse:
occurred and the errors array will give further details.
"""

resp = internal.get(path="/auth/revoke", key=key)
resp = await internal.get(path="/auth/revoke", key=key)
return StatusResponse(**resp)
Loading

0 comments on commit 3525b70

Please sign in to comment.