mirror of
https://github.com/dh1tw/pyhamtools.git
synced 2025-12-06 06:52:00 +01:00
Added pyhamtools.qsl to load LOTW and EQSL user list
This commit is contained in:
parent
beb8862ebe
commit
250d8e6b79
|
|
@ -1,6 +1,13 @@
|
|||
Changelog
|
||||
---------
|
||||
|
||||
PyHamTools 0.4.2
|
||||
================
|
||||
|
||||
11. October 2014
|
||||
|
||||
* added pyhamtools.qsl (get EQSL.cc and LOTW user lists)
|
||||
|
||||
PyHamTools 0.4.1
|
||||
================
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
import sys
|
||||
import os
|
||||
|
||||
from pyhamtools.version import __version__, __release__
|
||||
|
||||
sys.path.insert(0,"/Users/user/projects/pyhamtools/pyhamtools")
|
||||
|
||||
|
|
@ -58,9 +59,9 @@ copyright = u'2014, Tobias Wellnitz, DH1TW'
|
|||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.4'
|
||||
version = __version__
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.4.1'
|
||||
release = __release__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
:Version: |release|
|
||||
:Code: https://github.com/dh1tw/pyhamtools
|
||||
:License: MIT; see LICENSE file
|
||||
:License: MIT; see :doc:`license` file
|
||||
:Issues: https://github.com/dh1tw/pyhamtools/issues
|
||||
:Documentation: http://pyhamtools.readthedocs.org/
|
||||
:IRC: #hamtests on webirc.deltaxray.org
|
||||
|
|
|
|||
|
|
@ -21,9 +21,18 @@ class LookupConventions:
|
|||
DELETED = "deleted"
|
||||
MARITIME_MOBILE = "mm"
|
||||
AIRCRAFT_MOBILE = "am"
|
||||
LOCATOR = "locator"
|
||||
BEACON = "beacon"
|
||||
SKIMMER = "skimmer"
|
||||
|
||||
#CQ / DIGITAL Skimmer specific
|
||||
|
||||
SKIMMER = "skimmer"
|
||||
FS = "fs" #fieldstrength
|
||||
WPM = "wpm" #words / bytes per second
|
||||
CQ = "cq"
|
||||
NCDXF = "ncdxf"
|
||||
|
||||
|
||||
# Modes
|
||||
CW = "CW"
|
||||
USB = "USB"
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@
|
|||
|
||||
class APIKeyMissingError(AttributeError):
|
||||
""" API Key is Missing """
|
||||
pass
|
||||
pass
|
||||
|
||||
108
pyhamtools/qsl.py
Normal file
108
pyhamtools/qsl.py
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
from datetime import datetime
|
||||
import re
|
||||
|
||||
import requests
|
||||
import redis
|
||||
from requests.exceptions import ConnectionError, HTTPError, Timeout
|
||||
|
||||
|
||||
def get_lotw_users(**kwargs):
|
||||
"""download the latest list of ARRL Logbook of the World (LOTW) inofficial user list
|
||||
which is provided on a weekly basis by `HB9BZA`_. Dates of last activity on LOTW
|
||||
is added by `WD5EAE`_.
|
||||
|
||||
Args:
|
||||
url (str, optional): Download URL
|
||||
|
||||
Returns:
|
||||
dict: Dictionary containing the callsign (unicode) date of estimated last LOTW upload (datetime)
|
||||
|
||||
Raises:
|
||||
IOError: When network is unavailable, file can't be downloaded or processed
|
||||
|
||||
Example:
|
||||
The following example downloads the LOTW user list and check when DH1TW has made his last LOTW upload:
|
||||
|
||||
>>> from pyhamtools.qsl import get_lotw_users
|
||||
>>> mydict = get_lotw_users()
|
||||
>>> mydict['DH1TW']
|
||||
datetime.datetime(2014, 9, 7, 0, 0)
|
||||
|
||||
.. HB9BZA: http://www.hb9bza.net/lotw-users-list
|
||||
.. WD5EAE: http://www.wd5eae.org/HB9BZA_LoTWUsersList.html
|
||||
|
||||
"""
|
||||
url = ""
|
||||
|
||||
lotw = {}
|
||||
|
||||
try:
|
||||
url = kwargs['url']
|
||||
except KeyError:
|
||||
# url = "http://wd5eae.org/LoTW1.txt"
|
||||
url = "http://wd5eae.org/LoTW_Data.txt"
|
||||
|
||||
try:
|
||||
result = requests.get(url)
|
||||
except (ConnectionError, HTTPError, Timeout) as e:
|
||||
raise IOError(e)
|
||||
|
||||
if result.status_code == requests.codes.ok:
|
||||
for el in result.text.split():
|
||||
data = el.split(",")
|
||||
lotw[data[0]] = datetime.strptime(data[1], '%Y-%m-%d')
|
||||
# print call
|
||||
else:
|
||||
raise IOError("HTTP Error: " + str(result.status_code))
|
||||
|
||||
return lotw
|
||||
|
||||
def get_eqsl_users(**kwargs):
|
||||
"""download the latest official list of EQSL.cc users. The list of users can be found `here`_.
|
||||
|
||||
Args:
|
||||
url (str, optional): Download URL
|
||||
|
||||
Returns:
|
||||
list: List containing the callsigns of EQSL users (unicode)
|
||||
|
||||
Raises:
|
||||
IOError: When network is unavailable, file can't be downloaded or processed
|
||||
|
||||
Example:
|
||||
The following example downloads the EQSL user list and checks if DH1TW is a user:
|
||||
|
||||
>>> from pyhamtools.qsl import get_eqsl_users
|
||||
>>> mylist = get_eqsl_users()
|
||||
>>> try:
|
||||
>>> mylist.index('DH1TW')
|
||||
>>> except ValueError as e:
|
||||
>>> print e
|
||||
'DH1TW' is not in list
|
||||
|
||||
.. here: http://www.eqsl.cc/QSLCard/DownloadedFiles/AGMemberlist.txt
|
||||
.. WD5EAE: http://www.wd5eae.org/HB9BZA_LoTWUsersList.html
|
||||
|
||||
"""
|
||||
|
||||
url = ""
|
||||
|
||||
eqsl = []
|
||||
|
||||
try:
|
||||
url = kwargs['url']
|
||||
except KeyError:
|
||||
url = "http://www.eqsl.cc/QSLCard/DownloadedFiles/AGMemberlist.txt"
|
||||
|
||||
try:
|
||||
result = requests.get(url)
|
||||
except (ConnectionError, HTTPError, Timeout) as e:
|
||||
raise IOError(e)
|
||||
|
||||
if result.status_code == requests.codes.ok:
|
||||
eqsl = re.sub("^List.+UTC", "", result.text)
|
||||
eqsl = eqsl.upper().split()
|
||||
else:
|
||||
raise IOError("HTTP Error: " + str(result.status_code))
|
||||
|
||||
return eqsl
|
||||
4
pyhamtools/version.py
Normal file
4
pyhamtools/version.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#VERSION = (0, 5, 0, 'dev')
|
||||
VERSION = (0, 4, 2)
|
||||
__release__ = ''.join(['-.'[type(x) == int]+str(x) for x in VERSION])[1:]
|
||||
__version__ = '.'.join((str(VERSION[0]), str(VERSION[1])))
|
||||
|
|
@ -3,5 +3,5 @@ requests>=2.2.1
|
|||
pytz>=2014.2
|
||||
pyephem>=3.7.5.3
|
||||
redis>=2.10.2
|
||||
|
||||
beautifulsoup4>=4.3.2
|
||||
|
||||
|
|
|
|||
9
setup.py
9
setup.py
|
|
@ -1,14 +1,20 @@
|
|||
#!/usr/bin/env python
|
||||
import sys
|
||||
import os
|
||||
from distutils.core import setup
|
||||
# from pyhamtools import __version__, __release__
|
||||
|
||||
kw = {}
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
kw['use_2to3'] = True
|
||||
|
||||
exec(open(os.path.join("pyhamtools","version.py")).read())
|
||||
|
||||
# from pyhamtools import __version__, __release__
|
||||
|
||||
setup(name='pyhamtools',
|
||||
version='0.4.1',
|
||||
version=__release__,
|
||||
description='Collection of Tools for Amateur Radio developers',
|
||||
author='Tobias Wellnitz, DH1TW',
|
||||
author_email='Tobias@dh1tw.de',
|
||||
|
|
@ -19,6 +25,7 @@ setup(name='pyhamtools',
|
|||
"pytz",
|
||||
"requests",
|
||||
"pyephem",
|
||||
"beautifulsoup4",
|
||||
],
|
||||
**kw
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ import tempfile
|
|||
import os
|
||||
|
||||
|
||||
from apikey import APIKEY
|
||||
from apikey import APIKEY, QRZ_USERNAME, QRZ_PWD
|
||||
from pyhamtools import LookupLib
|
||||
from pyhamtools import Callinfo
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", params=["a", "", 12.5, -5, {"foo" : "bar"}, [5, "foo"]])
|
||||
def fixNonUnsignedInteger(request):
|
||||
return request.param
|
||||
|
|
@ -39,9 +40,6 @@ def fixLists(request):
|
|||
def fixNone(request):
|
||||
return request.param
|
||||
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def fixApiKey(request):
|
||||
return(APIKEY)
|
||||
|
|
@ -77,4 +75,8 @@ def fix_callinfo(request, fixApiKey):
|
|||
@pytest.fixture(scope="module")
|
||||
def fix_redis():
|
||||
import redis
|
||||
return LookupLib(lookuptype="redis", redis_instance=redis.Redis(), redis_prefix="clx")
|
||||
return LookupLib(lookuptype="redis", redis_instance=redis.Redis(), redis_prefix="clx")
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def fix_qrz():
|
||||
return LookupLib(lookuptype="qrz", username=QRZ_USERNAME, pwd=QRZ_PWD)
|
||||
|
|
|
|||
85662
test/fixtures/eqsl_data.html
vendored
Normal file
85662
test/fixtures/eqsl_data.html
vendored
Normal file
File diff suppressed because it is too large
Load diff
1
test/fixtures/eqsl_data.py
vendored
Normal file
1
test/fixtures/eqsl_data.py
vendored
Normal file
File diff suppressed because one or more lines are too long
76928
test/fixtures/lotw_data.html
vendored
Normal file
76928
test/fixtures/lotw_data.html
vendored
Normal file
File diff suppressed because it is too large
Load diff
1
test/fixtures/lotw_data.py
vendored
Normal file
1
test/fixtures/lotw_data.py
vendored
Normal file
File diff suppressed because one or more lines are too long
27
test/test_eqsl.py
Normal file
27
test/test_eqsl.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import os
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from pyhamtools.qsl import get_eqsl_users
|
||||
|
||||
class Test_eqsl_methods:
|
||||
|
||||
|
||||
def test_check_content_with_mocked_http_server(self, httpserver):
|
||||
httpserver.serve_content(open('./fixtures/eqsl_data.html').read(), headers={'content-type': 'text/plain; charset=ISO-8859-1'})
|
||||
|
||||
exec(open(os.path.join("./fixtures/","eqsl_data.py")).read())
|
||||
assert get_eqsl_users(url=httpserver.url) == eqsl_fixture
|
||||
|
||||
def test_download_lotw_list_and_check_types(self):
|
||||
|
||||
data = get_eqsl_users()
|
||||
assert isinstance(data, list)
|
||||
for el in data:
|
||||
assert isinstance(el, unicode)
|
||||
assert len(data) > 1000
|
||||
|
||||
def test_with_invalid_url(self):
|
||||
with pytest.raises(IOError):
|
||||
get_eqsl_users(url="http://www.eqsl.cc/QSLCard/DownloadedFiles/AGMemberlist_my_unit_test.txt")
|
||||
29
test/test_lotw.py
Normal file
29
test/test_lotw.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import os
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from pyhamtools.qsl import get_lotw_users
|
||||
|
||||
class Test_lotw_methods:
|
||||
|
||||
def test_check_content_with_mocked_http_server(self, httpserver):
|
||||
httpserver.serve_content(open('./fixtures/lotw_data.html').read())
|
||||
|
||||
exec(open(os.path.join("./fixtures/","lotw_data.py")).read())
|
||||
assert get_lotw_users(url=httpserver.url) == lotw_fixture
|
||||
|
||||
def test_download_lotw_list_and_check_types(self):
|
||||
|
||||
data = get_lotw_users()
|
||||
assert isinstance(data, dict)
|
||||
for key, value in data.iteritems():
|
||||
assert isinstance(key, unicode)
|
||||
assert isinstance(value, datetime.datetime )
|
||||
assert len(data) > 1000
|
||||
|
||||
def test_with_invalid_url(self):
|
||||
with pytest.raises(IOError):
|
||||
get_lotw_users(url="http://wd5eae.org/LoTW_Data_XXXXX.txt")
|
||||
|
||||
|
||||
Loading…
Reference in a new issue