mirror of
https://github.com/dh1tw/pyhamtools.git
synced 2026-01-07 01:00:42 +01:00
added qrz.com and callsign exception file
This commit is contained in:
parent
c037bcee71
commit
63eb9a2447
BIN
docs/build/doctrees/environment.pickle
vendored
BIN
docs/build/doctrees/environment.pickle
vendored
Binary file not shown.
BIN
docs/build/doctrees/help.doctree
vendored
BIN
docs/build/doctrees/help.doctree
vendored
Binary file not shown.
BIN
docs/build/doctrees/index.doctree
vendored
BIN
docs/build/doctrees/index.doctree
vendored
Binary file not shown.
BIN
docs/build/doctrees/license.doctree
vendored
BIN
docs/build/doctrees/license.doctree
vendored
Binary file not shown.
2
docs/build/html/.buildinfo
vendored
2
docs/build/html/.buildinfo
vendored
|
|
@ -1,4 +1,4 @@
|
|||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 28550054b902e31426622d239c737bb6
|
||||
config: 7a49ae1f4a901a2bfa6bcbedb16df815
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
|
|
|||
80
docs/build/html/genindex.html
vendored
80
docs/build/html/genindex.html
vendored
|
|
@ -7,7 +7,7 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Index — pyhamtools 0.4.1 documentation</title>
|
||||
<title>Index — pyhamtools 0.4.2 documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: './',
|
||||
VERSION: '0.4.1',
|
||||
VERSION: '0.4.2',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="pyhamtools 0.4.1 documentation" href="index.html" />
|
||||
<link rel="top" title="pyhamtools 0.4.2 documentation" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
<li class="right" >
|
||||
<a href="py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
@ -61,33 +61,33 @@
|
|||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_distance">calculate_distance() (in module pyhamtools.locator)</a>, <a href="locator.html#pyhamtools.locator.calculate_distance">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_distance">calculate_distance() (in module pyhamtools.locator)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_distance_longpath">calculate_distance_longpath() (in module pyhamtools.locator)</a>, <a href="locator.html#pyhamtools.locator.calculate_distance_longpath">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_distance_longpath">calculate_distance_longpath() (in module pyhamtools.locator)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_heading">calculate_heading() (in module pyhamtools.locator)</a>, <a href="locator.html#pyhamtools.locator.calculate_heading">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_heading">calculate_heading() (in module pyhamtools.locator)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_heading_longpath">calculate_heading_longpath() (in module pyhamtools.locator)</a>, <a href="locator.html#pyhamtools.locator.calculate_heading_longpath">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_heading_longpath">calculate_heading_longpath() (in module pyhamtools.locator)</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_sunrise_sunset">calculate_sunrise_sunset() (in module pyhamtools.locator)</a>, <a href="locator.html#pyhamtools.locator.calculate_sunrise_sunset">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.locator.calculate_sunrise_sunset">calculate_sunrise_sunset() (in module pyhamtools.locator)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo">Callinfo (class in pyhamtools.callinfo)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo">Callinfo (class in pyhamtools.callinfo)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.copy_data_in_redis">copy_data_in_redis() (pyhamtools.lookuplib.LookupLib method)</a>, <a href="lookupLib.html#pyhamtools.lookuplib.LookupLib.copy_data_in_redis">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.copy_data_in_redis">copy_data_in_redis() (pyhamtools.lookuplib.LookupLib method)</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
|
|
@ -102,7 +102,7 @@
|
|||
|
||||
<dd><dl>
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.utils.freq_to_band">(in module pyhamtools.utils)</a>, <a href="utils.html#pyhamtools.utils.freq_to_band">[1]</a>, <a href="frequency.html#pyhamtools.utils.freq_to_band">[2]</a>
|
||||
<dt><a href="reference.html#pyhamtools.utils.freq_to_band">(in module pyhamtools.utils)</a>
|
||||
</dt>
|
||||
|
||||
</dl></dd>
|
||||
|
|
@ -113,37 +113,45 @@
|
|||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_adif_id">get_adif_id() (pyhamtools.callinfo.Callinfo method)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo.get_adif_id">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_adif_id">get_adif_id() (pyhamtools.callinfo.Callinfo method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_all">get_all() (pyhamtools.callinfo.Callinfo method)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo.get_all">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_all">get_all() (pyhamtools.callinfo.Callinfo method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_continent">get_continent() (pyhamtools.callinfo.Callinfo method)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo.get_continent">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_continent">get_continent() (pyhamtools.callinfo.Callinfo method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_country_name">get_country_name() (pyhamtools.callinfo.Callinfo method)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo.get_country_name">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_country_name">get_country_name() (pyhamtools.callinfo.Callinfo method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_cqz">get_cqz() (pyhamtools.callinfo.Callinfo method)</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_cqz">get_cqz() (pyhamtools.callinfo.Callinfo method)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo.get_cqz">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.qsl.get_eqsl_users">get_eqsl_users() (in module pyhamtools.qsl)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_homecall">get_homecall() (pyhamtools.callinfo.Callinfo static method)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo.get_homecall">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_homecall">get_homecall() (pyhamtools.callinfo.Callinfo static method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_ituz">get_ituz() (pyhamtools.callinfo.Callinfo method)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo.get_ituz">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_ituz">get_ituz() (pyhamtools.callinfo.Callinfo method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_lat_long">get_lat_long() (pyhamtools.callinfo.Callinfo method)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo.get_lat_long">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.get_lat_long">get_lat_long() (pyhamtools.callinfo.Callinfo method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.qsl.get_lotw_users">get_lotw_users() (in module pyhamtools.qsl)</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
|
|
@ -153,13 +161,13 @@
|
|||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.is_invalid_operation">is_invalid_operation() (pyhamtools.lookuplib.LookupLib method)</a>, <a href="lookupLib.html#pyhamtools.lookuplib.LookupLib.is_invalid_operation">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.is_invalid_operation">is_invalid_operation() (pyhamtools.lookuplib.LookupLib method)</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.is_valid_callsign">is_valid_callsign() (pyhamtools.callinfo.Callinfo method)</a>, <a href="callinfo.html#pyhamtools.callinfo.Callinfo.is_valid_callsign">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.callinfo.Callinfo.is_valid_callsign">is_valid_callsign() (pyhamtools.callinfo.Callinfo method)</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
|
|
@ -169,33 +177,33 @@
|
|||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.locator.latlong_to_locator">latlong_to_locator() (in module pyhamtools.locator)</a>, <a href="locator.html#pyhamtools.locator.latlong_to_locator">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.locator.latlong_to_locator">latlong_to_locator() (in module pyhamtools.locator)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.locator.locator_to_latlong">locator_to_latlong() (in module pyhamtools.locator)</a>, <a href="locator.html#pyhamtools.locator.locator_to_latlong">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.locator.locator_to_latlong">locator_to_latlong() (in module pyhamtools.locator)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.lookup_callsign">lookup_callsign() (pyhamtools.lookuplib.LookupLib method)</a>, <a href="lookupLib.html#pyhamtools.lookuplib.LookupLib.lookup_callsign">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.lookup_callsign">lookup_callsign() (pyhamtools.lookuplib.LookupLib method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.lookup_entity">lookup_entity() (pyhamtools.lookuplib.LookupLib method)</a>, <a href="lookupLib.html#pyhamtools.lookuplib.LookupLib.lookup_entity">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.lookup_entity">lookup_entity() (pyhamtools.lookuplib.LookupLib method)</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.lookup_prefix">lookup_prefix() (pyhamtools.lookuplib.LookupLib method)</a>, <a href="lookupLib.html#pyhamtools.lookuplib.LookupLib.lookup_prefix">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.lookup_prefix">lookup_prefix() (pyhamtools.lookuplib.LookupLib method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.lookup_zone_exception">lookup_zone_exception() (pyhamtools.lookuplib.LookupLib method)</a>, <a href="lookupLib.html#pyhamtools.lookuplib.LookupLib.lookup_zone_exception">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib.lookup_zone_exception">lookup_zone_exception() (pyhamtools.lookuplib.LookupLib method)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib">LookupLib (class in pyhamtools.lookuplib)</a>, <a href="lookupLib.html#pyhamtools.lookuplib.LookupLib">[1]</a>
|
||||
<dt><a href="reference.html#pyhamtools.lookuplib.LookupLib">LookupLib (class in pyhamtools.lookuplib)</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
|
|
@ -205,7 +213,7 @@
|
|||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#module-pyhamtools.callinfo">pyhamtools.callinfo (module)</a>, <a href="callinfo.html#module-pyhamtools.callinfo">[1]</a>
|
||||
<dt><a href="reference.html#module-pyhamtools.callinfo">pyhamtools.callinfo (module)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
|
|
@ -213,17 +221,21 @@
|
|||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#module-pyhamtools.locator">pyhamtools.locator (module)</a>, <a href="reference.html#module-pyhamtools.locator">[1]</a>, <a href="locator.html#module-pyhamtools.locator">[2]</a>
|
||||
<dt><a href="reference.html#module-pyhamtools.locator">pyhamtools.locator (module)</a>, <a href="reference.html#module-pyhamtools.locator">[1]</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
<td style="width: 33%" valign="top"><dl>
|
||||
|
||||
<dt><a href="reference.html#module-pyhamtools.lookuplib">pyhamtools.lookuplib (module)</a>, <a href="lookupLib.html#module-pyhamtools.lookuplib">[1]</a>
|
||||
<dt><a href="reference.html#module-pyhamtools.lookuplib">pyhamtools.lookuplib (module)</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#module-pyhamtools.utils">pyhamtools.utils (module)</a>, <a href="utils.html#module-pyhamtools.utils">[1]</a>, <a href="frequency.html#module-pyhamtools.utils">[2]</a>
|
||||
<dt><a href="reference.html#module-pyhamtools.qsl">pyhamtools.qsl (module)</a>, <a href="reference.html#module-pyhamtools.qsl">[1]</a>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt><a href="reference.html#module-pyhamtools.utils">pyhamtools.utils (module)</a>
|
||||
</dt>
|
||||
|
||||
</dl></td>
|
||||
|
|
@ -265,7 +277,7 @@
|
|||
<li class="right" >
|
||||
<a href="py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
|
|
|
|||
10
docs/build/html/help.html
vendored
10
docs/build/html/help.html
vendored
|
|
@ -6,7 +6,7 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>help — pyhamtools 0.4.1 documentation</title>
|
||||
<title>help — pyhamtools 0.4.2 documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: './',
|
||||
VERSION: '0.4.1',
|
||||
VERSION: '0.4.2',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="pyhamtools 0.4.1 documentation" href="index.html" />
|
||||
<link rel="top" title="pyhamtools 0.4.2 documentation" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
<li class="right" >
|
||||
<a href="py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
<li class="right" >
|
||||
<a href="py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
|
|
|
|||
18
docs/build/html/index.html
vendored
18
docs/build/html/index.html
vendored
|
|
@ -6,7 +6,7 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>PyHamTools — pyhamtools 0.4.1 documentation</title>
|
||||
<title>PyHamTools — pyhamtools 0.4.2 documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: './',
|
||||
VERSION: '0.4.1',
|
||||
VERSION: '0.4.2',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="pyhamtools 0.4.1 documentation" href="#" />
|
||||
<link rel="top" title="pyhamtools 0.4.2 documentation" href="#" />
|
||||
<link rel="next" title="Reference" href="reference.html" />
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
<li class="right" >
|
||||
<a href="reference.html" title="Reference"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li><a href="#">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="#">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
@ -54,11 +54,11 @@
|
|||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field-odd field"><th class="field-name">Version:</th><td class="field-body">0.4.1</td>
|
||||
<tr class="field-odd field"><th class="field-name">Version:</th><td class="field-body">0.4.2</td>
|
||||
</tr>
|
||||
<tr class="field-even field"><th class="field-name">Code:</th><td class="field-body"><a class="reference external" href="https://github.com/dh1tw/pyhamtools">https://github.com/dh1tw/pyhamtools</a></td>
|
||||
</tr>
|
||||
<tr class="field-odd field"><th class="field-name">License:</th><td class="field-body">MIT; see LICENSE file</td>
|
||||
<tr class="field-odd field"><th class="field-name">License:</th><td class="field-body">MIT; see <a class="reference internal" href="license.html"><em>license</em></a> file</td>
|
||||
</tr>
|
||||
<tr class="field-even field"><th class="field-name">Issues:</th><td class="field-body"><a class="reference external" href="https://github.com/dh1tw/pyhamtools/issues">https://github.com/dh1tw/pyhamtools/issues</a></td>
|
||||
</tr>
|
||||
|
|
@ -85,6 +85,7 @@ with some modules and classes which are frequently needed:</p>
|
|||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">Reference</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-pyhamtools.locator">pyhamtools.locator</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-pyhamtools.qsl">pyhamtools.qsl</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-pyhamtools.frequency">pyhamtools.frequency</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-pyhamtools.callinfo">pyhamtools.callinfo</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#module-pyhamtools.lookuplib">pyhamtools.lookuplib</a></li>
|
||||
|
|
@ -95,10 +96,11 @@ with some modules and classes which are frequently needed:</p>
|
|||
<li class="toctree-l2"><a class="reference internal" href="examples.html#calculate-shortpath-and-longpath-heading-between-two-locators">Calculate Shortpath and Longpath Heading between two locators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#calculate-distance-between-two-wgs84-coordinates">Calculate Distance between two WGS84 Coordinates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#calculate-sunrise-and-sunset-for-jn48qm-on-the-1-january-2015">Calculate Sunrise and Sunset for JN48QM on the 1. January 2015</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#decode-a-callsign-and-get-country-itu-zone-cq-zone-latitude-longitude">Decode a Callsign and get Country, ITU Zone, CQ Zone, Latitude & Longitude</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#decode-a-callsign-and-get-country-name-adif-id-latitude-longitude">Decode a Callsign and get Country name, ADIF ID, Latitude & Longitude</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Changelog</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="changelog.html#pyhamtools-0-4-2">PyHamTools 0.4.2</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="changelog.html#pyhamtools-0-4-1">PyHamTools 0.4.1</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="changelog.html#pyhamtools-0-4-0">PyHamTools 0.4.0</a></li>
|
||||
</ul>
|
||||
|
|
@ -167,7 +169,7 @@ with some modules and classes which are frequently needed:</p>
|
|||
<li class="right" >
|
||||
<a href="reference.html" title="Reference"
|
||||
>next</a> |</li>
|
||||
<li><a href="#">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="#">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
|
|
|
|||
10
docs/build/html/license.html
vendored
10
docs/build/html/license.html
vendored
|
|
@ -6,7 +6,7 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>license — pyhamtools 0.4.1 documentation</title>
|
||||
<title>license — pyhamtools 0.4.2 documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: './',
|
||||
VERSION: '0.4.1',
|
||||
VERSION: '0.4.2',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="pyhamtools 0.4.1 documentation" href="index.html" />
|
||||
<link rel="top" title="pyhamtools 0.4.2 documentation" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
<li class="right" >
|
||||
<a href="py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ SOFTWARE.</p>
|
|||
<li class="right" >
|
||||
<a href="py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
|
|
|
|||
BIN
docs/build/html/objects.inv
vendored
BIN
docs/build/html/objects.inv
vendored
Binary file not shown.
17
docs/build/html/py-modindex.html
vendored
17
docs/build/html/py-modindex.html
vendored
|
|
@ -6,7 +6,7 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Python Module Index — pyhamtools 0.4.1 documentation</title>
|
||||
<title>Python Module Index — pyhamtools 0.4.2 documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: './',
|
||||
VERSION: '0.4.1',
|
||||
VERSION: '0.4.2',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="pyhamtools 0.4.1 documentation" href="index.html" />
|
||||
<link rel="top" title="pyhamtools 0.4.2 documentation" href="index.html" />
|
||||
|
||||
|
||||
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
<li class="right" >
|
||||
<a href="#" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
@ -87,7 +87,12 @@
|
|||
<tr class="cg-1">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="utils.html#module-pyhamtools.utils"><tt class="xref">pyhamtools.utils</tt></a></td><td>
|
||||
<a href="reference.html#module-pyhamtools.qsl"><tt class="xref">pyhamtools.qsl</tt></a></td><td>
|
||||
<em></em></td></tr>
|
||||
<tr class="cg-1">
|
||||
<td></td>
|
||||
<td>
|
||||
<a href="reference.html#module-pyhamtools.utils"><tt class="xref">pyhamtools.utils</tt></a></td><td>
|
||||
<em></em></td></tr>
|
||||
</table>
|
||||
|
||||
|
|
@ -123,7 +128,7 @@
|
|||
<li class="right" >
|
||||
<a href="#" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
|
|
|
|||
10
docs/build/html/search.html
vendored
10
docs/build/html/search.html
vendored
|
|
@ -6,7 +6,7 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Search — pyhamtools 0.4.1 documentation</title>
|
||||
<title>Search — pyhamtools 0.4.2 documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: './',
|
||||
VERSION: '0.4.1',
|
||||
VERSION: '0.4.2',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<script type="text/javascript" src="_static/searchtools.js"></script>
|
||||
<link rel="top" title="pyhamtools 0.4.1 documentation" href="index.html" />
|
||||
<link rel="top" title="pyhamtools 0.4.2 documentation" href="index.html" />
|
||||
<script type="text/javascript">
|
||||
jQuery(function() { Search.loadIndex("searchindex.js"); });
|
||||
</script>
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
<li class="right" >
|
||||
<a href="py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
@ -94,7 +94,7 @@
|
|||
<li class="right" >
|
||||
<a href="py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.1 documentation</a> »</li>
|
||||
<li><a href="index.html">pyhamtools 0.4.2 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
|
|
|
|||
2
docs/build/html/searchindex.js
vendored
2
docs/build/html/searchindex.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,26 @@
|
|||
Changelog
|
||||
---------
|
||||
|
||||
PyHamTools 0.5.0
|
||||
================
|
||||
|
||||
5. April 2015
|
||||
|
||||
* implemented QRZ.com interface into LookupLib [LookupLib]
|
||||
|
||||
* changed and unified all output to Unicode
|
||||
|
||||
* corrected Longitude to General Standard (-180...0° West, 0...180° East) [LookupLib]
|
||||
|
||||
* improved callsign decoding alogrithm [CallInfo]
|
||||
|
||||
* added special case to decode location of VK9 callsigns [CallInfo]
|
||||
|
||||
* added ValueError when LOTW data from file contains too many errors [qsl]
|
||||
|
||||
* added handling of special callsigns which can't be decoded properly inside a separate
|
||||
callsign exception file (e.g. 7QAA)
|
||||
|
||||
PyHamTools 0.4.2
|
||||
================
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import pytz
|
|||
|
||||
from pyhamtools.consts import LookupConventions as const
|
||||
|
||||
from pyhamtools.callsign_exceptions import callsign_exceptions
|
||||
|
||||
UTC = pytz.UTC
|
||||
timestamp_now = datetime.utcnow().replace(tzinfo=UTC)
|
||||
|
|
@ -80,6 +81,10 @@ class Callinfo(object):
|
|||
def _iterate_prefix(self, callsign, timestamp=timestamp_now):
|
||||
"""truncate call until it corresponds to a Prefix in the database"""
|
||||
prefix = callsign
|
||||
|
||||
if re.search('(VK|AX|VI)9[A-Z]{3}', callsign): #special rule for VK9 calls
|
||||
if timestamp > datetime(2006,1,1, tzinfo=UTC):
|
||||
prefix = callsign[0:3]+callsign[4:5]
|
||||
|
||||
while len(prefix) > 0:
|
||||
try:
|
||||
|
|
@ -139,7 +144,7 @@ class Callinfo(object):
|
|||
appendix = re.search('/[A-Z0-9]{2,4}$', callsign)
|
||||
appendix = re.sub('/', '', appendix.group(0))
|
||||
self._logger.debug("appendix: " + appendix)
|
||||
|
||||
|
||||
if appendix == 'MM': # special case Martime Mobile
|
||||
#self._mm = True
|
||||
return {
|
||||
|
|
@ -173,6 +178,10 @@ class Callinfo(object):
|
|||
elif appendix == "LH": # Filter all Lighthouses
|
||||
callsign = re.sub('/LH', '', callsign)
|
||||
return self._iterate_prefix(callsign, timestamp)
|
||||
elif re.search('[A-Z]{3}', appendix): #case of US county(?) contest N3HBX/UAL
|
||||
callsign = re.sub('/[A-Z]{3}$', '', callsign)
|
||||
return self._iterate_prefix(callsign, timestamp)
|
||||
|
||||
else:
|
||||
# check if the appendix is a valid country prefix
|
||||
return self._iterate_prefix(re.sub('/', '', appendix), timestamp)
|
||||
|
|
@ -205,10 +214,17 @@ class Callinfo(object):
|
|||
elif re.search('^[A-Z0-9]{1,4}/', entire_callsign):
|
||||
pfx = re.search('^[A-Z0-9]{1,4}/', entire_callsign)
|
||||
pfx = re.sub('/', '', pfx.group(0))
|
||||
return self._iterate_prefix(pfx)
|
||||
#make sure that the remaining part is actually a callsign (avoid: OZ/JO81)
|
||||
rest = re.search('/[A-Z0-9]+', entire_callsign)
|
||||
rest = re.sub('/', '', rest.group(0))
|
||||
if re.match('^[\d]{0,1}[A-Z]{1,2}\d([A-Z]{1,4}|\d{3,3}|\d{1,3}[A-Z])[A-Z]{0,5}$', rest):
|
||||
return self._iterate_prefix(pfx)
|
||||
|
||||
if entire_callsign in callsign_exceptions:
|
||||
return self._iterate_prefix(callsign_exceptions[entire_callsign])
|
||||
|
||||
self._logger.debug("Could not decode " + callsign)
|
||||
raise KeyError
|
||||
raise KeyError("Callsign could not be decoded")
|
||||
|
||||
def _lookup_callsign(self, callsign, timestamp=timestamp_now):
|
||||
|
||||
|
|
@ -241,7 +257,7 @@ class Callinfo(object):
|
|||
'longitude': 0.0
|
||||
}
|
||||
|
||||
# Check if a dedicated entry exists for the callsign
|
||||
# Check if a dedicated entry/exception exists for the callsign
|
||||
try:
|
||||
data = self._lookuplib.lookup_callsign(callsign, timestamp).copy()
|
||||
if self.check_if_beacon(callsign):
|
||||
|
|
|
|||
6
pyhamtools/callsign_exceptions.py
Normal file
6
pyhamtools/callsign_exceptions.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
|
||||
callsign_exceptions={
|
||||
'7QAA' : '7Q',
|
||||
'2SZ' : 'G0'
|
||||
}
|
||||
|
|
@ -4,69 +4,110 @@ class LookupConventions:
|
|||
""" This class defines the constants used within the pyhamtools package """
|
||||
|
||||
# Mostly specific to Clublog XML File
|
||||
CALLSIGN = "callsign"
|
||||
COUNTRY = "country"
|
||||
PREFIX = "prefix"
|
||||
ADIF = "adif"
|
||||
CQZ = "cqz"
|
||||
ITUZ = "ituz"
|
||||
CONTINENT = "continent"
|
||||
LATITUDE = "latitude"
|
||||
LONGITUDE = "longitude"
|
||||
START = "start"
|
||||
END = "end"
|
||||
WHITELIST = "whitelist"
|
||||
WHITELIST_START = "whitelist_start"
|
||||
WHITELIST_END = "whitelist_end"
|
||||
DELETED = "deleted"
|
||||
MARITIME_MOBILE = "mm"
|
||||
AIRCRAFT_MOBILE = "am"
|
||||
LOCATOR = "locator"
|
||||
BEACON = "beacon"
|
||||
CALLSIGN = u"callsign"
|
||||
COUNTRY = u"country"
|
||||
PREFIX = u"prefix"
|
||||
ADIF = u"adif"
|
||||
CQZ = u"cqz"
|
||||
ITUZ = u"ituz"
|
||||
CONTINENT = u"continent"
|
||||
LATITUDE = u"latitude"
|
||||
LONGITUDE = u"longitude"
|
||||
START = u"start"
|
||||
END = u"end"
|
||||
WHITELIST = u"whitelist"
|
||||
WHITELIST_START = u"whitelist_start"
|
||||
WHITELIST_END = u"whitelist_end"
|
||||
DELETED = u"deleted"
|
||||
MARITIME_MOBILE = u"mm"
|
||||
AIRCRAFT_MOBILE = u"am"
|
||||
LOCATOR = u"locator"
|
||||
BEACON = u"beacon"
|
||||
|
||||
#CQ / DIGITAL Skimmer specific
|
||||
|
||||
SKIMMER = "skimmer"
|
||||
FS = "fs" #fieldstrength
|
||||
WPM = "wpm" #words / bytes per second
|
||||
CQ = "cq"
|
||||
NCDXF = "ncdxf"
|
||||
SKIMMER = u"skimmer"
|
||||
FS = u"fs" #fieldstrength
|
||||
WPM = u"wpm" #words / bytes per second
|
||||
CQ = u"cq"
|
||||
NCDXF = u"ncdxf"
|
||||
|
||||
|
||||
# Modes
|
||||
CW = "CW"
|
||||
USB = "USB"
|
||||
LSB = "LSB"
|
||||
DIGITAL = "DIGITAL"
|
||||
FM = "FM"
|
||||
CW = u"CW"
|
||||
USB = u"USB"
|
||||
LSB = u"LSB"
|
||||
DIGITAL = u"DIGITAL"
|
||||
FM = u"FM"
|
||||
|
||||
#DX Spot
|
||||
SPOTTER = "spotter"
|
||||
DX = "dx"
|
||||
FREQUENCY = "frequency"
|
||||
COMMENT = "comment"
|
||||
TIME = "time"
|
||||
BAND = "band"
|
||||
MODE = "mode"
|
||||
SPOTTER = u"spotter"
|
||||
DX = u"dx"
|
||||
FREQUENCY = u"frequency"
|
||||
COMMENT = u"comment"
|
||||
TIME = u"time"
|
||||
BAND = u"band"
|
||||
MODE = u"mode"
|
||||
|
||||
#DX Spider specific
|
||||
ORIGIN_NODE = "node"
|
||||
HOPS = "hops"
|
||||
RAW_SPOT = "raw"
|
||||
IP = "ip"
|
||||
ROUTE = "route"
|
||||
TEXT = "text"
|
||||
SYSOP_FLAG = "sysop_flag"
|
||||
WX_FLAG = "wx_flag"
|
||||
ORIGIN_NODE = u"node"
|
||||
HOPS = u"hops"
|
||||
RAW_SPOT = u"raw"
|
||||
IP = u"ip"
|
||||
ROUTE = u"route"
|
||||
TEXT = u"text"
|
||||
SYSOP_FLAG = u"sysop_flag"
|
||||
WX_FLAG = u"wx_flag"
|
||||
|
||||
#WWV & WCY
|
||||
STATION = "station"
|
||||
R = "r"
|
||||
K = "k"
|
||||
EXPK = "expk"
|
||||
SFI = "sfi"
|
||||
A = "a"
|
||||
AURORA = "aurora"
|
||||
SA = "sa"
|
||||
GMF = "gmf"
|
||||
FORECAST = "forecast"
|
||||
STATION = u"station"
|
||||
R = u"r"
|
||||
K = u"k"
|
||||
EXPK = u"expk"
|
||||
SFI = u"sfi"
|
||||
A = u"a"
|
||||
AURORA = u"aurora"
|
||||
SA = u"sa"
|
||||
GMF = u"gmf"
|
||||
FORECAST = u"forecast"
|
||||
|
||||
#QRZ.com
|
||||
XREF = u"xref"
|
||||
ALIASES = u"aliases"
|
||||
FNAME = u"fname"
|
||||
NAME = u"name"
|
||||
ADDR1 = u"addr1"
|
||||
ADDR2 = u"addr2"
|
||||
STATE = u"state"
|
||||
ZIPCODE = u"zipcode"
|
||||
CCODE = u"ccode"
|
||||
COUNTY = u"county"
|
||||
FIPS = u"fips"
|
||||
LAND = u"land"
|
||||
EFDATE = u"efdate"
|
||||
EXPDATE = u"expdate"
|
||||
P_CALL = u"p_call"
|
||||
LICENSE_CLASS = u"license_class"
|
||||
CODES = u"codes"
|
||||
QSLMGR = u"qslmgr"
|
||||
EMAIL = u"email"
|
||||
URL = u"url"
|
||||
U_VIEWS = u"u_views"
|
||||
BIO = u"bio"
|
||||
BIODATE = u"biodate"
|
||||
IMAGE = u"image"
|
||||
IMAGE_INFO = u"imageinfo"
|
||||
SERIAL = u"serial"
|
||||
MODDATE = u"moddate"
|
||||
MSA = "msa"
|
||||
AREACODE = "areacode"
|
||||
TIMEZONE = "timezone"
|
||||
GMTOFFSET = "gmtoffset"
|
||||
DST = "dst"
|
||||
EQSL = "eqsl"
|
||||
MQSL = "mqsl"
|
||||
LOTW = "lotw"
|
||||
BORN = "born"
|
||||
USER_MGR = "user"
|
||||
IOTA = "iota"
|
||||
GEOLOC = "geoloc"
|
||||
|
|
|
|||
38
pyhamtools/logparser.py
Normal file
38
pyhamtools/logparser.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
def import_cabrillo(filename):
|
||||
log = None;
|
||||
log_import = None
|
||||
with open(filename, 'r') as f:
|
||||
log_import = f.read()
|
||||
log = []
|
||||
log_import = log_import.split("\r\n")
|
||||
|
||||
for qso in log_import:
|
||||
|
||||
if re.match("^QSO", qso):
|
||||
freq = int(qso[4:11])
|
||||
mode = qso[11:13]
|
||||
time = datetime.strptime(qso[14:29], "%Y-%m-%d %H%M")
|
||||
frm = qso[30:44].strip()
|
||||
sent_rst = int(qso[44:47])
|
||||
sent_exchange = qso[48:55].strip()
|
||||
qso_partner = qso[55:68].strip()
|
||||
rcvd_rst = int(qso[69:72])
|
||||
rcvd_exchange = qso[73:79].strip()
|
||||
station = int(qso[80])
|
||||
log.append({
|
||||
"freq": freq,
|
||||
"mode":mode,
|
||||
"time":time,
|
||||
"from": frm,
|
||||
"sent_rst":sent_rst,
|
||||
"sent_exchange": sent_exchange,
|
||||
"qso_partner": qso_partner,
|
||||
"rcvd_rst": rcvd_rst,
|
||||
"rcvd_exchange": rcvd_exchange,
|
||||
"station": station
|
||||
})
|
||||
return log
|
||||
|
|
@ -9,12 +9,14 @@ import urllib
|
|||
import json
|
||||
import copy
|
||||
import sys
|
||||
import unicodedata
|
||||
|
||||
import requests
|
||||
from requests.exceptions import ConnectionError, HTTPError, Timeout
|
||||
from bs4 import BeautifulSoup
|
||||
import pytz
|
||||
|
||||
|
||||
import version
|
||||
from consts import LookupConventions as const
|
||||
from exceptions import APIKeyMissingError
|
||||
|
||||
|
|
@ -54,6 +56,9 @@ class LookupLib(object):
|
|||
Args:
|
||||
lookuptype (str) : "clublogxml" or "clublogapi" or "countryfile" or "redis"
|
||||
apikey (str): Clublog API Key
|
||||
username (str): QRZ.com username
|
||||
pwd (str): QRZ.com password
|
||||
apiv (str, optional): QRZ.com API Version
|
||||
filename (str, optional): Filename for Clublog XML or Country-files.com cty.plist file. When a local file is
|
||||
used, no Internet connection not API Key is necessary.
|
||||
logger (logging.getLogger(__name__), optional): Python logger
|
||||
|
|
@ -62,7 +67,7 @@ class LookupLib(object):
|
|||
|
||||
|
||||
"""
|
||||
def __init__(self, lookuptype = "countryfile", apikey=None, filename=None, logger=None, redis_instance=None, redis_prefix=None):
|
||||
def __init__(self, lookuptype = "countryfile", apikey=None, apiv="1.3.3", filename=None, logger=None, username=None, pwd=None, redis_instance=None, redis_prefix=None):
|
||||
|
||||
self._logger = None
|
||||
if logger:
|
||||
|
|
@ -75,10 +80,13 @@ class LookupLib(object):
|
|||
self._logger.addHandler(logging.NullHandler())
|
||||
|
||||
self._apikey = apikey
|
||||
self._apiv = apiv
|
||||
self._download = True
|
||||
self._lib_filename = filename
|
||||
self._redis = redis_instance
|
||||
self._redis_prefix = redis_prefix
|
||||
self._username = username
|
||||
self._pwd = pwd
|
||||
|
||||
if self._lib_filename:
|
||||
self._download = False
|
||||
|
|
@ -101,8 +109,36 @@ class LookupLib(object):
|
|||
pass
|
||||
elif self._lookuptype == "redis":
|
||||
import redis
|
||||
elif self._lookuptype == "qrz":
|
||||
self._apikey = self._get_qrz_session_key(self._username, self._pwd)
|
||||
else:
|
||||
raise AttributeError("Lookup type missing")
|
||||
|
||||
def _get_qrz_session_key(self, username, pwd):
|
||||
|
||||
qrz_api_version = "1.3.3"
|
||||
url = "https://xmldata.qrz.com/xml/" + qrz_api_version + "/"
|
||||
agent = "PyHT"+version.__version__
|
||||
|
||||
params = {"username" : username,
|
||||
"password" : pwd,
|
||||
"agent" : agent
|
||||
}
|
||||
|
||||
encodeurl = url + "?" + urllib.urlencode(params)
|
||||
response = requests.get(encodeurl, timeout=5)
|
||||
doc = BeautifulSoup(response.text)
|
||||
session_key = None
|
||||
if doc.session.key:
|
||||
session_key = doc.session.key.text
|
||||
else:
|
||||
if doc.session.error:
|
||||
raise ValueError(doc.session.error.text)
|
||||
else:
|
||||
raise ValueError("Could not retrieve Session Key from QRZ.com")
|
||||
|
||||
return session_key
|
||||
|
||||
|
||||
def copy_data_in_redis(self, redis_prefix, redis_instance):
|
||||
"""
|
||||
|
|
@ -135,8 +171,8 @@ class LookupLib(object):
|
|||
>>> my_lookuplib.lookup_callsign("3D2RI")
|
||||
{
|
||||
u'adif': 460,
|
||||
u'continent': 'OC',
|
||||
u'country': 'Rotuma Island',
|
||||
u'continent': u'OC',
|
||||
u'country': u'Rotuma Island',
|
||||
u'cqz': 32,
|
||||
u'ituz': 56,
|
||||
u'latitude': -12.48,
|
||||
|
|
@ -217,12 +253,12 @@ class LookupLib(object):
|
|||
>>> print my_lookuplib.lookup_entity(273)
|
||||
{
|
||||
'deleted': False,
|
||||
'country': 'TURKMENISTAN',
|
||||
'country': u'TURKMENISTAN',
|
||||
'longitude': -58.4,
|
||||
'cqz': 17,
|
||||
'prefix': 'EZ',
|
||||
'prefix': u'EZ',
|
||||
'latitude': 38.0,
|
||||
'continent': 'AS'
|
||||
'continent': u'AS'
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -241,16 +277,18 @@ class LookupLib(object):
|
|||
raise KeyError
|
||||
|
||||
elif self._lookuptype == "redis":
|
||||
|
||||
if self._redis_prefix is None:
|
||||
raise KeyError ("redis_prefix is missing")
|
||||
|
||||
#entity = str(entity)
|
||||
json_data = self._redis.get(self._redis_prefix + "_entity_" + str(entity))
|
||||
if json_data is not None:
|
||||
my_dict = self._deserialize_data(json_data)
|
||||
return self._strip_metadata(my_dict)
|
||||
|
||||
elif self._lookuptype == "qrz":
|
||||
result = self._lookup_qrz_dxcc(entity, self._apikey)
|
||||
return result
|
||||
|
||||
# no matching case
|
||||
raise KeyError
|
||||
|
||||
|
|
@ -297,12 +335,12 @@ class LookupLib(object):
|
|||
>>> timestamp = datetime(year=1962, month=7, day=7, tzinfo=pytz.UTC)
|
||||
>>> print my_lookuplib.lookup_callsign("VK9XO", timestamp)
|
||||
{
|
||||
'country': 'CHRISTMAS ISLAND',
|
||||
'country': u'CHRISTMAS ISLAND',
|
||||
'longitude': -105.7,
|
||||
'cqz': 29,
|
||||
'adif': 35,
|
||||
'latitude': -10.5,
|
||||
'continent': 'OC'
|
||||
'continent': u'OC'
|
||||
}
|
||||
|
||||
Note:
|
||||
|
|
@ -311,8 +349,10 @@ class LookupLib(object):
|
|||
- clublogxml
|
||||
- clublogapi
|
||||
- countryfile
|
||||
- qrz.com
|
||||
- redis
|
||||
|
||||
|
||||
"""
|
||||
callsign = callsign.strip().upper()
|
||||
|
||||
|
|
@ -333,7 +373,10 @@ class LookupLib(object):
|
|||
return self._check_data_for_date(callsign, timestamp, data_dict, index)
|
||||
|
||||
# no matching case
|
||||
raise KeyError
|
||||
elif self._lookuptype == "qrz":
|
||||
return self._lookup_qrz_callsign(callsign, self._apikey, self._apiv)
|
||||
|
||||
raise KeyError("unknown Callsign")
|
||||
|
||||
def _get_dicts_from_redis(self, name, index_name, redis_prefix, item):
|
||||
"""
|
||||
|
|
@ -454,12 +497,12 @@ class LookupLib(object):
|
|||
>>> print myLookupLib.lookup_prefix("DH")
|
||||
{
|
||||
'adif': 230,
|
||||
'country': 'Fed. Rep. of Germany',
|
||||
'country': u'Fed. Rep. of Germany',
|
||||
'longitude': -10.0,
|
||||
'cqz': 14,
|
||||
'ituz': 28,
|
||||
'latitude': 51.0,
|
||||
'continent': 'EU'
|
||||
'continent': u'EU'
|
||||
}
|
||||
|
||||
Note:
|
||||
|
|
@ -644,17 +687,243 @@ class LookupLib(object):
|
|||
lookup = {}
|
||||
|
||||
for item in jsonLookup:
|
||||
if item == "Name": lookup[const.COUNTRY] = str(jsonLookup["Name"])
|
||||
if item == "Name": lookup[const.COUNTRY] = jsonLookup["Name"]
|
||||
elif item == "DXCC": lookup[const.ADIF] = int(jsonLookup["DXCC"])
|
||||
elif item == "Lon": lookup[const.LONGITUDE] = float(jsonLookup["Lon"])
|
||||
elif item == "Lat": lookup[const.LATITUDE] = float(jsonLookup["Lat"])
|
||||
elif item == "CQZ": lookup[const.CQZ] = int(jsonLookup["CQZ"])
|
||||
elif item == "Continent": lookup[const.CONTINENT] = str(jsonLookup["Continent"])
|
||||
|
||||
elif item == "Continent": lookup[const.CONTINENT] = jsonLookup["Continent"]
|
||||
|
||||
if lookup[const.ADIF] == 0:
|
||||
raise KeyError
|
||||
else:
|
||||
return lookup
|
||||
|
||||
def _request_callsign_info_from_qrz(self, callsign, apikey, apiv="1.3.3"):
|
||||
qrz_api_version = apiv
|
||||
url = "https://xmldata.qrz.com/xml/" + qrz_api_version + "/"
|
||||
|
||||
params = {
|
||||
"s": apikey,
|
||||
"callsign" : callsign,
|
||||
}
|
||||
|
||||
encodeurl = url + "?" + urllib.urlencode(params)
|
||||
response = requests.get(encodeurl, timeout=5)
|
||||
return response
|
||||
|
||||
def _request_dxcc_info_from_qrz(self, dxcc_or_callsign, apikey, apiv="1.3.3"):
|
||||
qrz_api_version = apiv
|
||||
url = "https://xmldata.qrz.com/xml/" + qrz_api_version + "/"
|
||||
|
||||
params = {
|
||||
"s": apikey,
|
||||
"dxcc" : str(dxcc_or_callsign),
|
||||
}
|
||||
|
||||
encodeurl = url + "?" + urllib.urlencode(params)
|
||||
response = requests.get(encodeurl, timeout=5)
|
||||
return response
|
||||
|
||||
def _lookup_qrz_dxcc(self, dxcc_or_callsign, apikey, apiv="1.3.3"):
|
||||
""" Performs the dxcc lookup against the QRZ.com XML API:
|
||||
"""
|
||||
|
||||
response = self._request_dxcc_info_from_qrz(dxcc_or_callsign, apikey, apiv=apiv)
|
||||
|
||||
root = BeautifulSoup(response.text)
|
||||
lookup = {}
|
||||
|
||||
if root.error: #try to get a new session key and try to request again
|
||||
|
||||
if re.search('No DXCC Information for', root.error.text, re.I): #No data available for callsign
|
||||
raise KeyError(root.error.text)
|
||||
elif re.search('Session Timeout', root.error.text, re.I): # Get new session key
|
||||
self._apikey = apikey = self._get_qrz_session_key(self._username, self._pwd)
|
||||
response = self._request_dxcc_info_from_qrz(dxcc_or_callsign, apikey)
|
||||
root = BeautifulSoup(response.text)
|
||||
else:
|
||||
raise AttributeError("Session Key Missing") #most likely session key missing or invalid
|
||||
|
||||
if root.dxcc is None:
|
||||
raise ValueError
|
||||
|
||||
if root.dxcc.dxcc:
|
||||
lookup[const.ADIF] = int(root.dxcc.dxcc.text)
|
||||
if root.dxcc.cc:
|
||||
lookup['cc'] = root.dxcc.cc.text
|
||||
if root.dxcc.cc:
|
||||
lookup['ccc'] = root.dxcc.ccc.text
|
||||
if root.find('name'):
|
||||
lookup[const.COUNTRY] = root.find('name').get_text()
|
||||
if root.dxcc.continent:
|
||||
lookup[const.CONTINENT] = root.dxcc.continent.text
|
||||
if root.dxcc.ituzone:
|
||||
lookup[const.ITUZ] = int(root.dxcc.ituzone.text)
|
||||
if root.dxcc.cqzone:
|
||||
lookup[const.CQZ] = int(root.dxcc.cqzone.text)
|
||||
if root.dxcc.timezone:
|
||||
lookup['timezone'] = float(root.dxcc.timezone.text)
|
||||
if root.dxcc.lat:
|
||||
lookup[const.LATITUDE] = float(root.dxcc.lat.text)
|
||||
if root.dxcc.lon:
|
||||
lookup[const.LONGITUDE] = float(root.dxcc.lon.text)
|
||||
|
||||
return lookup
|
||||
|
||||
|
||||
def _lookup_qrz_callsign(self, callsign=None, apikey=None, apiv="1.3.3"):
|
||||
""" Performs the callsign lookup against the QRZ.com XML API:
|
||||
"""
|
||||
|
||||
if apikey is None:
|
||||
raise AttributeError("Session Key Missing")
|
||||
|
||||
callsign = callsign.upper()
|
||||
|
||||
response = self._request_callsign_info_from_qrz(callsign, apikey, apiv)
|
||||
|
||||
root = BeautifulSoup(response.text)
|
||||
lookup = {}
|
||||
|
||||
if root.error: #try to get a new session key and try to request again
|
||||
|
||||
if re.search('Not found', root.error.text, re.I): #No data available for callsign
|
||||
raise KeyError(root.error.text)
|
||||
elif re.search('Session Timeout', root.error.text, re.I): # Get new session key
|
||||
self._apikey = apikey = self._get_qrz_session_key(self._username, self._pwd)
|
||||
response = self._request_callsign_info_from_qrz(callsign, apikey)
|
||||
root = BeautifulSoup(response.text)
|
||||
else:
|
||||
raise AttributeError(root.error.text) #most likely session key missing or invalid
|
||||
|
||||
if root.callsign is None:
|
||||
raise ValueError
|
||||
|
||||
if root.callsign.call:
|
||||
lookup[const.CALLSIGN] = root.callsign.call.text
|
||||
if root.callsign.xref:
|
||||
lookup[const.XREF] = root.callsign.xref.text
|
||||
if root.callsign.aliases:
|
||||
lookup[const.ALIASES] = root.callsign.aliases.text.split(',')
|
||||
if root.callsign.dxcc:
|
||||
lookup[const.ADIF] = int(root.callsign.dxcc.text)
|
||||
if root.callsign.fname:
|
||||
lookup[const.FNAME] = root.callsign.fname.text
|
||||
if root.callsign.find("name"):
|
||||
lookup[const.NAME] = root.callsign.find('name').get_text()
|
||||
if root.callsign.addr1:
|
||||
lookup[const.ADDR1] = root.callsign.addr1.text
|
||||
if root.callsign.addr2:
|
||||
lookup[const.ADDR2] = root.callsign.addr2.text
|
||||
if root.callsign.state:
|
||||
lookup[const.STATE] = root.callsign.state.text
|
||||
if root.callsign.zip:
|
||||
lookup[const.ZIPCODE] = root.callsign.zip.text
|
||||
if root.callsign.country:
|
||||
lookup[const.COUNTRY] = root.callsign.country.text
|
||||
if root.callsign.ccode:
|
||||
lookup[const.CCODE] = int(root.callsign.ccode.text)
|
||||
if root.callsign.lat:
|
||||
lookup[const.LATITUDE] = float(root.callsign.lat.text)
|
||||
if root.callsign.lon:
|
||||
lookup[const.LONGITUDE] = float(root.callsign.lon.text)
|
||||
if root.callsign.grid:
|
||||
lookup[const.LOCATOR] = root.callsign.grid.text
|
||||
if root.callsign.county:
|
||||
lookup[const.COUNTY] = root.callsign.county.text
|
||||
if root.callsign.fips:
|
||||
lookup[const.FIPS] = int(root.callsign.fips.text) # check type
|
||||
if root.callsign.land:
|
||||
lookup[const.LAND] = root.callsign.land.text
|
||||
if root.callsign.efdate:
|
||||
try:
|
||||
lookup[const.EFDATE] = datetime.strptime(root.callsign.efdate.text, '%Y-%m-%d').replace(tzinfo=UTC)
|
||||
except ValueError:
|
||||
self._logger.debug("[QRZ.com] efdate: Invalid DateTime; " + callsign + " " + root.callsign.efdate.text)
|
||||
if root.callsign.expdate:
|
||||
try:
|
||||
lookup[const.EXPDATE] = datetime.strptime(root.callsign.expdate.text, '%Y-%m-%d').replace(tzinfo=UTC)
|
||||
except ValueError:
|
||||
self._logger.debug("[QRZ.com] expdate: Invalid DateTime; " + callsign + " " + root.callsign.expdate.text)
|
||||
if root.callsign.p_call:
|
||||
lookup[const.P_CALL] = root.callsign.p_call.text
|
||||
if root.callsign.find('class'):
|
||||
lookup[const.LICENSE_CLASS] = root.callsign.find('class').get_text()
|
||||
if root.callsign.codes:
|
||||
lookup[const.CODES] = root.callsign.codes.text
|
||||
if root.callsign.qslmgr:
|
||||
lookup[const.QSLMGR] = root.callsign.qslmgr.text
|
||||
if root.callsign.email:
|
||||
lookup[const.EMAIL] = root.callsign.email.text
|
||||
if root.callsign.url:
|
||||
lookup[const.URL] = root.callsign.url.text
|
||||
if root.callsign.u_views:
|
||||
lookup[const.U_VIEWS] = int(root.callsign.u_views.text)
|
||||
if root.callsign.bio:
|
||||
lookup[const.BIO] = root.callsign.bio.text
|
||||
if root.callsign.biodate:
|
||||
try:
|
||||
lookup[const.BIODATE] = datetime.strptime(root.callsign.biodate.text, '%Y-%m-%d %H:%M:%S').replace(tzinfo=UTC)
|
||||
except ValueError:
|
||||
self._logger.warning("[QRZ.com] biodate: Invalid DateTime; " + callsign)
|
||||
if root.callsign.image:
|
||||
lookup[const.IMAGE] = root.callsign.image.text
|
||||
if root.callsign.imageinfo:
|
||||
lookup[const.IMAGE_INFO] = root.callsign.imageinfo.text
|
||||
if root.callsign.serial:
|
||||
lookup[const.SERIAL] = long(root.callsign.serial.text)
|
||||
if root.callsign.moddate:
|
||||
try:
|
||||
lookup[const.MODDATE] = datetime.strptime(root.callsign.moddate.text, '%Y-%m-%d %H:%M:%S').replace(tzinfo=UTC)
|
||||
except ValueError:
|
||||
self._logger.warning("[QRZ.com] moddate: Invalid DateTime; " + callsign)
|
||||
if root.callsign.MSA:
|
||||
lookup[const.MSA] = int(root.callsign.MSA.text)
|
||||
if root.callsign.AreaCode:
|
||||
lookup[const.AREACODE] = int(root.callsign.AreaCode.text)
|
||||
if root.callsign.TimeZone:
|
||||
lookup[const.TIMEZONE] = int(root.callsign.TimeZone.text)
|
||||
if root.callsign.GMTOffset:
|
||||
lookup[const.GMTOFFSET] = float(root.callsign.GMTOffset.text)
|
||||
if root.callsign.DST:
|
||||
if root.callsign.DST.text == "Y":
|
||||
lookup[const.DST] = True
|
||||
else:
|
||||
lookup[const.DST] = False
|
||||
if root.callsign.eqsl:
|
||||
if root.callsign.eqsl.text == "1":
|
||||
lookup[const.EQSL] = True
|
||||
else:
|
||||
lookup[const.EQSL] = False
|
||||
if root.callsign.mqsl:
|
||||
if root.callsign.mqsl.text == "1":
|
||||
lookup[const.MQSL] = True
|
||||
else:
|
||||
lookup[const.MQSL] = False
|
||||
if root.callsign.cqzone:
|
||||
lookup[const.CQZ] = int(root.callsign.cqzone.text)
|
||||
if root.callsign.ituzone:
|
||||
lookup[const.ITUZ] = int(root.callsign.ituzone.text)
|
||||
if root.callsign.born:
|
||||
lookup[const.BORN] = int(root.callsign.born.text)
|
||||
if root.callsign.user:
|
||||
lookup[const.USER_MGR] = root.callsign.user.text
|
||||
if root.callsign.lotw:
|
||||
if root.callsign.lotw.text == "1":
|
||||
lookup[const.LOTW] = True
|
||||
else:
|
||||
lookup[const.LOTW] = False
|
||||
if root.callsign.iota:
|
||||
lookup[const.IOTA] = root.callsign.iota.text
|
||||
if root.callsign.geoloc:
|
||||
lookup[const.GEOLOC] = root.callsign.geoloc.text
|
||||
|
||||
# if sys.version_info >= (2,):
|
||||
# for item in lookup:
|
||||
# if isinstance(lookup[item], unicode):
|
||||
# print item, repr(lookup[item])
|
||||
return lookup
|
||||
|
||||
def _load_clublogXML(self,
|
||||
url="https://secure.clublog.org/cty.php",
|
||||
|
|
@ -866,44 +1135,49 @@ class LookupLib(object):
|
|||
|
||||
#retrieve ADIF Country Entities
|
||||
cty_entities = cty_tree.find("entities")
|
||||
self._logger.debug("total entities: " + str(len(cty_entities)))
|
||||
if len(cty_entities) > 1:
|
||||
for cty_entity in cty_entities:
|
||||
entity = {}
|
||||
for item in cty_entity:
|
||||
if item.tag == "name":
|
||||
entity[const.COUNTRY] = str(item.text)
|
||||
elif item.tag == "prefix":
|
||||
entity[const.PREFIX] = str(item.text)
|
||||
elif item.tag == "deleted":
|
||||
if item.text == "TRUE":
|
||||
entity[const.DELETED] = True
|
||||
else:
|
||||
entity[const.DELETED] = False
|
||||
elif item.tag == "cqz":
|
||||
entity[const.CQZ] = int(item.text)
|
||||
elif item.tag == "cont":
|
||||
entity[const.CONTINENT] = str(item.text)
|
||||
elif item.tag == "long":
|
||||
entity[const.LONGITUDE] = float(item.text)*(-1)
|
||||
elif item.tag == "lat":
|
||||
entity[const.LATITUDE] = float(item.text)
|
||||
elif item.tag == "start":
|
||||
dt = datetime.strptime(item.text[:19], '%Y-%m-%dT%H:%M:%S')
|
||||
entity[const.START] = dt.replace(tzinfo=UTC)
|
||||
elif item.tag == "end":
|
||||
dt = datetime.strptime(item.text[:19], '%Y-%m-%dT%H:%M:%S')
|
||||
entity[const.END] = dt.replace(tzinfo=UTC)
|
||||
elif item.tag == "whitelist":
|
||||
if item.text == "TRUE":
|
||||
entity[const.WHITELIST] = True
|
||||
else:
|
||||
entity[const.WHITELIST] = False
|
||||
elif item.tag == "whitelist_start":
|
||||
dt = datetime.strptime(item.text[:19], '%Y-%m-%dT%H:%M:%S')
|
||||
entity[const.WHITELIST_START] = dt.replace(tzinfo=UTC)
|
||||
elif item.tag == "whitelist_end":
|
||||
dt = datetime.strptime(item.text[:19], '%Y-%m-%dT%H:%M:%S')
|
||||
entity[const.WHITELIST_END] = dt.replace(tzinfo=UTC)
|
||||
try:
|
||||
entity = {}
|
||||
for item in cty_entity:
|
||||
if item.tag == "name":
|
||||
entity[const.COUNTRY] = unicode(item.text)
|
||||
self._logger.debug(unicode(item.text))
|
||||
elif item.tag == "prefix":
|
||||
entity[const.PREFIX] = unicode(item.text)
|
||||
elif item.tag == "deleted":
|
||||
if item.text == "TRUE":
|
||||
entity[const.DELETED] = True
|
||||
else:
|
||||
entity[const.DELETED] = False
|
||||
elif item.tag == "cqz":
|
||||
entity[const.CQZ] = int(item.text)
|
||||
elif item.tag == "cont":
|
||||
entity[const.CONTINENT] = unicode(item.text)
|
||||
elif item.tag == "long":
|
||||
entity[const.LONGITUDE] = float(item.text)*(-1)
|
||||
elif item.tag == "lat":
|
||||
entity[const.LATITUDE] = float(item.text)
|
||||
elif item.tag == "start":
|
||||
dt = datetime.strptime(item.text[:19], '%Y-%m-%dT%H:%M:%S')
|
||||
entity[const.START] = dt.replace(tzinfo=UTC)
|
||||
elif item.tag == "end":
|
||||
dt = datetime.strptime(item.text[:19], '%Y-%m-%dT%H:%M:%S')
|
||||
entity[const.END] = dt.replace(tzinfo=UTC)
|
||||
elif item.tag == "whitelist":
|
||||
if item.text == "TRUE":
|
||||
entity[const.WHITELIST] = True
|
||||
else:
|
||||
entity[const.WHITELIST] = False
|
||||
elif item.tag == "whitelist_start":
|
||||
dt = datetime.strptime(item.text[:19], '%Y-%m-%dT%H:%M:%S')
|
||||
entity[const.WHITELIST_START] = dt.replace(tzinfo=UTC)
|
||||
elif item.tag == "whitelist_end":
|
||||
dt = datetime.strptime(item.text[:19], '%Y-%m-%dT%H:%M:%S')
|
||||
entity[const.WHITELIST_END] = dt.replace(tzinfo=UTC)
|
||||
except AttributeError:
|
||||
self._logger.error("Error while processing: ")
|
||||
entities[int(cty_entity[0].text)] = entity
|
||||
self._logger.debug(str(len(entities))+" Entities added")
|
||||
else:
|
||||
|
|
@ -922,13 +1196,13 @@ class LookupLib(object):
|
|||
else:
|
||||
call_exceptions_index[call] = [int(cty_exception.attrib["record"])]
|
||||
elif item.tag == "entity":
|
||||
call_exception[const.COUNTRY] = str(item.text)
|
||||
call_exception[const.COUNTRY] = unicode(item.text)
|
||||
elif item.tag == "adif":
|
||||
call_exception[const.ADIF] = int(item.text)
|
||||
elif item.tag == "cqz":
|
||||
call_exception[const.CQZ] = int(item.text)
|
||||
elif item.tag == "cont":
|
||||
call_exception[const.CONTINENT] = str(item.text)
|
||||
call_exception[const.CONTINENT] = unicode(item.text)
|
||||
elif item.tag == "long":
|
||||
call_exception[const.LONGITUDE] = float(item.text)*(-1)
|
||||
elif item.tag == "lat":
|
||||
|
|
@ -963,13 +1237,13 @@ class LookupLib(object):
|
|||
else:
|
||||
prefixes_index[call] = [int(cty_prefix.attrib["record"])]
|
||||
if item.tag == "entity":
|
||||
prefix[const.COUNTRY] = str(item.text)
|
||||
prefix[const.COUNTRY] = unicode(item.text)
|
||||
elif item.tag == "adif":
|
||||
prefix[const.ADIF] = int(item.text)
|
||||
elif item.tag == "cqz":
|
||||
prefix[const.CQZ] = int(item.text)
|
||||
elif item.tag == "cont":
|
||||
prefix[const.CONTINENT] = str(item.text)
|
||||
prefix[const.CONTINENT] = unicode(item.text)
|
||||
elif item.tag == "long":
|
||||
prefix[const.LONGITUDE] = float(item.text)*(-1)
|
||||
elif item.tag == "lat":
|
||||
|
|
@ -1086,12 +1360,12 @@ class LookupLib(object):
|
|||
for item in cty_list:
|
||||
entry = {}
|
||||
call = str(item)
|
||||
entry[const.COUNTRY] = str(cty_list[item]["Country"])
|
||||
entry[const.COUNTRY] = unicode(cty_list[item]["Country"])
|
||||
if mapping:
|
||||
entry[const.ADIF] = int(mapping[cty_list[item]["Country"]])
|
||||
entry[const.CQZ] = int(cty_list[item]["CQZone"])
|
||||
entry[const.ITUZ] = int(cty_list[item]["ITUZone"])
|
||||
entry[const.CONTINENT] = str(cty_list[item]["Continent"])
|
||||
entry[const.CONTINENT] = unicode(cty_list[item]["Continent"])
|
||||
entry[const.LATITUDE] = float(cty_list[item]["Latitude"])
|
||||
entry[const.LONGITUDE] = float(cty_list[item]["Longitude"])
|
||||
|
||||
|
|
@ -1193,7 +1467,7 @@ class LookupLib(object):
|
|||
elif item == const.WHITELIST:
|
||||
my_dict[item] = self._str_to_bool(my_dict[item])
|
||||
else:
|
||||
my_dict[item] = str(my_dict[item])
|
||||
my_dict[item] = unicode(my_dict[item])
|
||||
|
||||
return my_dict
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import requests
|
|||
import redis
|
||||
from requests.exceptions import ConnectionError, HTTPError, Timeout
|
||||
|
||||
|
||||
def get_lotw_users(**kwargs):
|
||||
"""Download the latest inoffical list of `ARRL Logbook of the World (LOTW)`__ users which is provided on a weekly basis by HB9BZA_. Dates of the users last upload is added by WD5EAE_.
|
||||
|
||||
|
|
@ -17,6 +16,7 @@ def get_lotw_users(**kwargs):
|
|||
|
||||
Raises:
|
||||
IOError: When network is unavailable, file can't be downloaded or processed
|
||||
ValueError: Raised when data from file can't be read
|
||||
|
||||
Example:
|
||||
The following example downloads the LOTW user list and check when DH1TW has made his last LOTW upload:
|
||||
|
|
@ -30,7 +30,9 @@ def get_lotw_users(**kwargs):
|
|||
.. _HB9BZA: http://www.hb9bza.net/lotw-users-list
|
||||
.. _WD5EAE: http://www.wd5eae.org/HB9BZA_LoTWUsersList.html
|
||||
__ ARRL_
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
url = ""
|
||||
|
||||
lotw = {}
|
||||
|
|
@ -46,14 +48,21 @@ def get_lotw_users(**kwargs):
|
|||
except (ConnectionError, HTTPError, Timeout) as e:
|
||||
raise IOError(e)
|
||||
|
||||
error_count = 0
|
||||
|
||||
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
|
||||
try:
|
||||
lotw[data[0]] = datetime.strptime(data[1], '%Y-%m-%d')
|
||||
except ValueError as e:
|
||||
error_count += 1
|
||||
if error_count > 10:
|
||||
raise ValueError("more than 10 wrongly formatted datasets " + str(e))
|
||||
|
||||
else:
|
||||
raise IOError("HTTP Error: " + str(result.status_code))
|
||||
|
||||
|
||||
return lotw
|
||||
|
||||
def get_eqsl_users(**kwargs):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#VERSION = (0, 5, 0, 'dev')
|
||||
VERSION = (0, 4, 2)
|
||||
VERSION = (0, 5, 0)
|
||||
__release__ = ''.join(['-.'[type(x) == int]+str(x) for x in VERSION])[1:]
|
||||
__version__ = '.'.join((str(VERSION[0]), str(VERSION[1])))
|
||||
|
|
|
|||
58
test/fixtures/lotw_data_with_errors.html
vendored
Normal file
58
test/fixtures/lotw_data_with_errors.html
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
1A0C,20-07-29
|
||||
1A0KM,20-02-08
|
||||
1A3A,20-09-12
|
||||
1A4A,20-09-16
|
||||
2A/DJ6AU,20-01-04
|
||||
2A0APF,20-11-23
|
||||
2A0APF/P,20-11-23
|
||||
2A0BQI,0000-10-03
|
||||
2A0BQI/P,20-10-03
|
||||
2A0BSM,20-12-31
|
||||
2A0MAV,20-11-23
|
||||
2C0TKX,20-05-15
|
||||
2C3SFC,2014-06-26
|
||||
2D0EBV/P,2006-10-26
|
||||
2D0YLX,2014-07-27
|
||||
2E0ADK,2014-02-18
|
||||
2E0ATS,2004-02-25
|
||||
2E0BBA,2010-08-19
|
||||
2E0BPP,2014-09-30
|
||||
2E0BXD,2011-12-29
|
||||
2E0BXO,2012-07-09
|
||||
2E0CAX,2006-07-11
|
||||
2E0CAX/P,2006-07-07
|
||||
2E0CHS,2008-12-05
|
||||
2E0CMD,2012-11-25
|
||||
2E0CMD/P,2012-11-25
|
||||
2E0CPJ,2013-03-22
|
||||
2E0CPT,2011-04-19
|
||||
2E0CQB,2014-06-14
|
||||
2E0CRY,2013-06-10
|
||||
2E0CXF,2014-05-24
|
||||
2E0DDG,2012-04-15
|
||||
2E0EBM,2014-07-21
|
||||
2E0EBV,2008-02-10
|
||||
2E0EBV/P,2006-07-03
|
||||
2E0EDL,2014-09-28
|
||||
2E0EET,2013-01-14
|
||||
2E0ETN,2012-06-06
|
||||
2E0ETT,2011-04-23
|
||||
2E0FAS,2014-08-31
|
||||
2E0FFQ,2008-12-10
|
||||
2E0FNG,2011-12-14
|
||||
2E0FSM,2014-09-19
|
||||
2E0GBC,2013-10-28
|
||||
2E0GBK,2014-07-31
|
||||
2E0GOL,2013-01-08
|
||||
2E0GSW,2013-12-28
|
||||
2E0GYC,2011-12-11
|
||||
2E0HEF,2014-08-26
|
||||
2E0HYE,2013-10-03
|
||||
2E0IAF,2014-09-28
|
||||
2E0IAF/P,2011-06-12
|
||||
2E0IFC,2014-09-28
|
||||
2E0IKW,2010-02-28
|
||||
2E0INV,2014-09-25
|
||||
2E0JAX,2013-05-01
|
||||
2E0JCA,2010-04-09
|
||||
2E0JCQ,2013-10-15
|
||||
|
|
@ -47,7 +47,65 @@ response_prefix_C6A_countryfile = {
|
|||
'ituz': 11
|
||||
}
|
||||
|
||||
response_prefix_VK9NDX_countryfile = {
|
||||
u'adif': 189,
|
||||
u'continent': u'OC',
|
||||
u'country': u'Norfolk Island',
|
||||
u'cqz': 32,
|
||||
u'ituz': 60,
|
||||
u'latitude': -29.03,
|
||||
u'longitude': -167.93
|
||||
}
|
||||
|
||||
response_prefix_VK9DNX_clublog = {
|
||||
u'adif': 189,
|
||||
u'continent': u'OC',
|
||||
u'country': u'NORFOLK ISLAND',
|
||||
u'cqz': 32,
|
||||
u'latitude': -29.0,
|
||||
u'longitude': -168.0
|
||||
}
|
||||
|
||||
response_prefix_VK9DWX_clublog = {
|
||||
u'adif': 303,
|
||||
u'continent': u'OC',
|
||||
u'country': u'WILLIS ISLAND',
|
||||
u'cqz': 30,
|
||||
u'latitude': -16.2,
|
||||
u'longitude': -150.0
|
||||
}
|
||||
|
||||
response_prefix_VK9DLX_clublog = {
|
||||
u'adif': 147,
|
||||
u'continent': u'OC',
|
||||
u'country': u'LORD HOWE ISLAND',
|
||||
u'cqz': 30,
|
||||
u'latitude': -31.6,
|
||||
u'longitude': -159.1
|
||||
}
|
||||
|
||||
response_prefix_VK9DLX_countryfile = {
|
||||
u'adif': 147,
|
||||
u'continent': u'OC',
|
||||
u'country': u'Lord Howe Island',
|
||||
u'cqz': 30,
|
||||
u'ituz': 60,
|
||||
u'latitude': -31.55,
|
||||
u'longitude': -159.08
|
||||
}
|
||||
|
||||
response_prefix_VK9GMW_clublog = {
|
||||
u'adif': 171,
|
||||
u'continent': u'OC',
|
||||
u'country': u'MELLISH REEF',
|
||||
u'cqz': 30,
|
||||
u'latitude': -17.6,
|
||||
u'longitude': -155.8
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
response_Exception_VK9XO_with_start_date = {
|
||||
'adif': 35,
|
||||
'country': 'CHRISTMAS ISLAND',
|
||||
|
|
@ -89,6 +147,18 @@ response_aircraft_mobile = {
|
|||
'longitude': 0.0
|
||||
}
|
||||
|
||||
response_callsign_exceptions_7QAA_clublog = {
|
||||
u'adif': 440,
|
||||
u'continent': u'AF',
|
||||
u'country': u'MALAWI',
|
||||
u'cqz': 37,
|
||||
u'latitude': -14.9,
|
||||
u'longitude': -34.4
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class Test_callinfo_methods:
|
||||
|
||||
def test_callinfo_iterate_prefix(self, fix_callinfo):
|
||||
|
|
@ -126,7 +196,7 @@ class Test_callinfo_methods:
|
|||
def test_dismantle_callsign(self, fix_callinfo):
|
||||
|
||||
if fix_callinfo._lookuplib._lookuptype == "clublogxml":
|
||||
#assert fix_callinfo._dismantle_callsign("DH1TW/BCN")[const.BEACON]
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/BCN")[const.BEACON]
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/QRP") == response_prefix_DH_clublog
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/QRPP") == response_prefix_DH_clublog
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/LH") == response_prefix_DH_clublog
|
||||
|
|
@ -134,28 +204,51 @@ class Test_callinfo_methods:
|
|||
assert fix_callinfo._dismantle_callsign("DH1TW/P") == response_prefix_DH_clublog
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/5") == response_prefix_DH_clublog
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/M") == response_prefix_DH_clublog
|
||||
#assert fix_callinfo._dismantle_callsign("DH1TW/B")[const.BEACON]
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/B")[const.BEACON]
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW") == response_prefix_DH_clublog
|
||||
assert fix_callinfo._dismantle_callsign("DL/HC2AO") == response_prefix_DH_clublog
|
||||
assert fix_callinfo._dismantle_callsign("9H5A/C6A") == response_prefix_C6A_clublog
|
||||
assert fix_callinfo._dismantle_callsign("C6A/9H5A") == response_prefix_C6A_clublog
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/UNI") == response_prefix_DH_clublog
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/BUX") == response_prefix_DH_clublog
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/NOT") == response_prefix_DH_clublog
|
||||
assert fix_callinfo._dismantle_callsign("VK9DLX/NOT") == response_prefix_VK9DLX_clublog
|
||||
assert fix_callinfo._dismantle_callsign("7QAA") == response_callsign_exceptions_7QAA_clublog
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
fix_callinfo._dismantle_callsign("OZ/JO85")
|
||||
|
||||
if fix_callinfo._lookuplib._lookuptype == "countryfile":
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/QRP") == response_prefix_DH_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/QRPP") == response_prefix_DH_countryfile
|
||||
#assert fix_callinfo._dismantle_callsign("DH1TW/BCN")[const.BEACON]
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/BCN")[const.BEACON]
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/LH") == response_prefix_DH_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("HC2AO/DL") == response_prefix_DH_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/P") == response_prefix_DH_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/5") == response_prefix_DH_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/M") == response_prefix_DH_countryfile
|
||||
#assert fix_callinfo._dismantle_callsign("DH1TW/B")[const.BEACON]
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/B")[const.BEACON]
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW") == response_prefix_DH_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("DL/HC2AO") == response_prefix_DH_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("9H5A/C6A") == response_prefix_C6A_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("C6A/9H5A") == response_prefix_C6A_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("DH1TW/NOT") == response_prefix_DH_countryfile
|
||||
assert fix_callinfo._dismantle_callsign("VK9DLX/NOT") == response_prefix_VK9DLX_countryfile
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
fix_callinfo._dismantle_callsign("OZ/JO85")
|
||||
|
||||
|
||||
def test_dismantle_callsign_with_VK9_special_suffixes(self, fix_callinfo):
|
||||
|
||||
if fix_callinfo._lookuplib._lookuptype == "clublog":
|
||||
assert fix_callinfo._dismantle_callsign("VK9DNX") == response_prefix_VK9DNX_clublog
|
||||
assert fix_callinfo._dismantle_callsign("VK9DLX") == response_prefix_VK9DLX_clublog
|
||||
assert fix_callinfo._dismantle_callsign("VK9GMX") == response_prefix_VK9GMW_clublog
|
||||
assert fix_callinfo._dismantle_callsign("VK9DWX") == response_prefix_VK9DWX_clublog
|
||||
|
||||
|
||||
def test_lookup_callsign(selfself, fix_callinfo):
|
||||
def test_lookup_callsign(self, fix_callinfo):
|
||||
|
||||
assert fix_callinfo._lookup_callsign("DH1TW/MM") == response_maritime_mobile
|
||||
assert fix_callinfo._lookup_callsign("DH1TW/AM") == response_aircraft_mobile
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ 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'})
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ from pyhamtools.exceptions import APIKeyMissingError
|
|||
|
||||
response_Exception_DH1TW = {
|
||||
'adif': 230,
|
||||
'country': 'FEDERAL REPUBLIC OF GERMANY',
|
||||
'continent': 'EU',
|
||||
'country': u'FEDERAL REPUBLIC OF GERMANY',
|
||||
'continent': u'EU',
|
||||
'latitude': 51.0,
|
||||
'longitude': -10.0,
|
||||
'cqz': 14
|
||||
|
|
@ -19,8 +19,8 @@ response_Exception_DH1TW = {
|
|||
|
||||
response_Exception_VU9KV = {
|
||||
'adif': 324,
|
||||
'country': 'INDIA',
|
||||
'continent': 'AS',
|
||||
'country': u'INDIA',
|
||||
'continent': u'AS',
|
||||
'latitude': 22.0,
|
||||
'longitude': -80.0,
|
||||
'cqz': 22
|
||||
|
|
@ -29,8 +29,8 @@ response_Exception_VU9KV = {
|
|||
|
||||
response_Exception_VU9KV_with_Date = {
|
||||
'adif': 11,
|
||||
'country': 'ANDAMAN & NICOBAR ISLANDS',
|
||||
'continent': 'AS',
|
||||
'country': u'ANDAMAN & NICOBAR ISLANDS',
|
||||
'continent': u'AS',
|
||||
'latitude': 11.70,
|
||||
'longitude': -92.80,
|
||||
'cqz': 26
|
||||
|
|
@ -39,8 +39,8 @@ response_Exception_VU9KV_with_Date = {
|
|||
|
||||
response_Exception_DH1TW_MM = {
|
||||
'adif': 999,
|
||||
'country': 'MARITIME MOBILE',
|
||||
'continent': '',
|
||||
'country': u'MARITIME MOBILE',
|
||||
'continent': u'',
|
||||
'latitude': 0.0,
|
||||
'longitude': 0.0,
|
||||
'cqz': 0
|
||||
|
|
@ -48,8 +48,8 @@ response_Exception_DH1TW_MM = {
|
|||
|
||||
response_Exception_DH1TW_AM = {
|
||||
'adif': 998,
|
||||
'country': 'AIRCRAFT MOBILE',
|
||||
'continent': '',
|
||||
'country': u'AIRCRAFT MOBILE',
|
||||
'continent': u'',
|
||||
'longitude': 0.0,
|
||||
'latitude': 0.0,
|
||||
'cqz': 0
|
||||
|
|
|
|||
|
|
@ -15,19 +15,19 @@ UTC = pytz.UTC
|
|||
|
||||
|
||||
response_Entity_230 = {
|
||||
'country': 'FEDERAL REPUBLIC OF GERMANY',
|
||||
'continent': 'EU',
|
||||
'country': u'FEDERAL REPUBLIC OF GERMANY',
|
||||
'continent': u'EU',
|
||||
'latitude': 51.0,
|
||||
'longitude': -10.0,
|
||||
'cqz': 14,
|
||||
'prefix' : 'DL',
|
||||
'prefix' : u'DL',
|
||||
'deleted' : False,
|
||||
}
|
||||
|
||||
response_Exception_KC6MM_1990 = {
|
||||
'adif': 22,
|
||||
'country': 'PALAU',
|
||||
'continent': 'OC',
|
||||
'country': u'PALAU',
|
||||
'continent': u'OC',
|
||||
'latitude': 9.50,
|
||||
'longitude': -138.20,
|
||||
'cqz': 27,
|
||||
|
|
@ -35,8 +35,8 @@ response_Exception_KC6MM_1990 = {
|
|||
|
||||
response_Exception_KC6MM_1992 = {
|
||||
'adif': 22,
|
||||
'country': 'PALAU',
|
||||
'continent': 'OC',
|
||||
'country': u'PALAU',
|
||||
'continent': u'OC',
|
||||
'latitude': 9.50,
|
||||
'longitude': -138.20,
|
||||
'cqz': 27,
|
||||
|
|
@ -45,8 +45,8 @@ response_Exception_KC6MM_1992 = {
|
|||
|
||||
response_Exception_VK9XX_with_end_date = {
|
||||
'adif': 35,
|
||||
'country': 'CHRISTMAS ISLAND',
|
||||
'continent': 'OC',
|
||||
'country': u'CHRISTMAS ISLAND',
|
||||
'continent': u'OC',
|
||||
'latitude': -10.50,
|
||||
'longitude': -105.70,
|
||||
'cqz': 29,
|
||||
|
|
@ -54,8 +54,8 @@ response_Exception_VK9XX_with_end_date = {
|
|||
|
||||
response_Exception_VK9XO_with_start_date = {
|
||||
'adif': 35,
|
||||
'country': 'CHRISTMAS ISLAND',
|
||||
'continent': 'OC',
|
||||
'country': u'CHRISTMAS ISLAND',
|
||||
'continent': u'OC',
|
||||
'latitude': -10.50,
|
||||
'longitude': -105.70,
|
||||
'cqz': 29,
|
||||
|
|
@ -63,44 +63,44 @@ response_Exception_VK9XO_with_start_date = {
|
|||
|
||||
response_Exception_AX9NYG = {
|
||||
'adif': 38,
|
||||
'country': 'COCOS (KEELING) ISLAND',
|
||||
'continent': 'OC',
|
||||
'country': u'COCOS (KEELING) ISLAND',
|
||||
'continent': u'OC',
|
||||
'latitude': -12.20,
|
||||
'longitude': -96.80,
|
||||
'cqz': 29,
|
||||
}
|
||||
|
||||
response_Prefix_DH = {
|
||||
'country': 'FEDERAL REPUBLIC OF GERMANY',
|
||||
'country': u'FEDERAL REPUBLIC OF GERMANY',
|
||||
'adif' : 230,
|
||||
'continent': 'EU',
|
||||
'continent': u'EU',
|
||||
'latitude': 51.0,
|
||||
'longitude': -10.0,
|
||||
'cqz': 14,
|
||||
}
|
||||
|
||||
response_Prefix_VK9_until_1975 = {
|
||||
'country': 'PAPUA TERR',
|
||||
'country': u'PAPUA TERR',
|
||||
'adif' : 198,
|
||||
'continent': 'OC',
|
||||
'continent': u'OC',
|
||||
'latitude': -9.40,
|
||||
'longitude': -147.10,
|
||||
'cqz': 28,
|
||||
}
|
||||
|
||||
response_Prefix_VK9_starting_1976 = {
|
||||
'country': 'NORFOLK ISLAND',
|
||||
'country': u'NORFOLK ISLAND',
|
||||
'adif' : 189,
|
||||
'continent': 'OC',
|
||||
'continent': u'OC',
|
||||
'latitude': -29.00,
|
||||
'longitude': -168.00,
|
||||
'cqz': 32,
|
||||
}
|
||||
|
||||
response_Prefix_ZD5_1964_to_1971 = {
|
||||
'country': 'SWAZILAND',
|
||||
'country': u'SWAZILAND',
|
||||
'adif' : 468,
|
||||
'continent': 'AF',
|
||||
'continent': u'AF',
|
||||
'latitude': -26.30,
|
||||
'longitude': -31.10,
|
||||
'cqz': 38,
|
||||
|
|
|
|||
|
|
@ -53,13 +53,13 @@ class Test_Getter_Setter_Api_Types_for_all_sources:
|
|||
count = 0
|
||||
for attr in entity:
|
||||
if attr == "country":
|
||||
assert type(entity[attr] is str)
|
||||
assert type(entity[attr] is unicode)
|
||||
count +=1
|
||||
if attr == "continent":
|
||||
assert type(entity[attr] is str)
|
||||
assert type(entity[attr] is unicode)
|
||||
count +=1
|
||||
if attr == "prefix":
|
||||
assert type(entity[attr] is str)
|
||||
assert type(entity[attr] is unicode)
|
||||
count +=1
|
||||
if attr == "deleted":
|
||||
assert type(entity[attr] is bool)
|
||||
|
|
@ -109,10 +109,10 @@ class Test_Getter_Setter_Api_Types_for_all_sources:
|
|||
assert type(ex[attr]) is float
|
||||
count +=1
|
||||
elif attr == "country":
|
||||
assert type(ex[attr]) is str
|
||||
assert type(ex[attr]) is unicode
|
||||
count +=1
|
||||
elif attr == "continent":
|
||||
assert type(ex[attr]) is str
|
||||
assert type(ex[attr]) is unicode
|
||||
count +=1
|
||||
elif attr == "cqz":
|
||||
assert type(ex[attr]) is int
|
||||
|
|
@ -145,7 +145,7 @@ class Test_Getter_Setter_Api_Types_for_all_sources:
|
|||
count = 0
|
||||
for attr in prefix:
|
||||
if attr == "country":
|
||||
assert type(prefix[attr]) is str
|
||||
assert type(prefix[attr]) is unicode
|
||||
count +=1
|
||||
elif attr == "adif":
|
||||
assert type(prefix[attr]) is int
|
||||
|
|
@ -157,7 +157,7 @@ class Test_Getter_Setter_Api_Types_for_all_sources:
|
|||
assert type(prefix[attr]) is int
|
||||
count +=1
|
||||
elif attr == "continent":
|
||||
assert type(prefix[attr]) is str
|
||||
assert type(prefix[attr]) is unicode
|
||||
count +=1
|
||||
elif attr == "latitude":
|
||||
assert type(prefix[attr]) is float
|
||||
|
|
|
|||
242
test/test_lookuplib_qrz.py
Normal file
242
test/test_lookuplib_qrz.py
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
import pytest
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
from apikey import QRZ_USERNAME, QRZ_PWD
|
||||
from pyhamtools.lookuplib import LookupLib
|
||||
from pyhamtools.exceptions import APIKeyMissingError
|
||||
from pyhamtools.consts import LookupConventions as const
|
||||
|
||||
import pytz
|
||||
UTC = pytz.UTC
|
||||
|
||||
#Fixtures
|
||||
#===========================================================
|
||||
|
||||
response_XX1XX = {
|
||||
# 'u_views': u'17495',
|
||||
u'biodate': datetime(2015, 2, 4, 17, 50, 32, tzinfo=UTC),
|
||||
u'image': u'http://files.qrz.com/x/xx1xx/DSC_0094.png',
|
||||
u'locator': u'KF05nx',
|
||||
u'addr2': u'TEST CALLSIGN CITY',
|
||||
u'addr1': u'DO NOT QSL',
|
||||
u'aliases': [u'YY1YY'],
|
||||
u'codes': u'TPS',
|
||||
u'zipcode': u'010101',
|
||||
u'lotw': True,
|
||||
u'state': u'JC',
|
||||
u'callsign': u'XX1XX',
|
||||
u'fname': u'James W.',
|
||||
u'latitude': -34.010735,
|
||||
u'longitude': 21.164476,
|
||||
u'email': u'trucker2345@easymail.com',
|
||||
u'qslmgr': u'NO QSL - TEST CALLSIGN',
|
||||
u'bio': u'10415',
|
||||
u'ccode': 120,
|
||||
u'geoloc': u'user',
|
||||
u'eqsl': True,
|
||||
u'mqsl': True,
|
||||
u'adif': 134,
|
||||
u'moddate': datetime(2015, 2, 4, 17, 53, 2, tzinfo=UTC),
|
||||
u'license_class': u'z',
|
||||
u'land': u'Kingman Reef',
|
||||
u'imageinfo': u'425:640:425545',
|
||||
u'name': 'Smith',
|
||||
u'born': 2002,
|
||||
u'country': u'Iceland',
|
||||
u'user': u'XX1XX'
|
||||
}
|
||||
|
||||
|
||||
response_XX2XX = {
|
||||
u'bio': u'93',
|
||||
u'land': u'NON-DXCC',
|
||||
u'adif': 0,
|
||||
u'zipcode': u'23232',
|
||||
u'country': u'Anguilla',
|
||||
u'user': u'XX2XX',
|
||||
u'moddate': datetime(2015, 3, 20, 23, 20, 37, tzinfo=UTC),
|
||||
u'lotw': False,
|
||||
u'ccode': 9,
|
||||
u'geoloc': u'dxcc',
|
||||
u'state': u'GA',
|
||||
u'eqsl': False,
|
||||
u'addr2': u'Las Vegas',
|
||||
# 'u_views': u'23',
|
||||
u'fname': u'NO',
|
||||
u'addr1': u'123 Main Stod\u00DFer',
|
||||
u'callsign': u'XX2XX',
|
||||
u'mqsl': False,
|
||||
u'biodate': datetime(2015, 2, 19, 22, 30, 2, tzinfo=UTC),
|
||||
u'image': u'http://files.qrz.com/x/xx2xx/oval_bumper_sticker4.png',
|
||||
u'imageinfo': u'285:500:44218'
|
||||
}
|
||||
|
||||
response_XX3XX = {
|
||||
# 'u_views': u'4698',
|
||||
u'biodate': datetime(2014, 8, 13, 15, 34, 57, tzinfo=UTC),
|
||||
u'image': u'http://files.qrz.com/x/xx3xx/IMG_8813.JPG',
|
||||
u'locator': u'FO51sj',
|
||||
u'addr2': u'Shady Circle Roads',
|
||||
u'addr1': u'1234 Main St.3',
|
||||
u'aliases': [u'XX3XX/W7'],
|
||||
u'zipcode': u'00033',
|
||||
u'lotw': False,
|
||||
u'state': u'JJ',
|
||||
u'callsign': u'XX3XX',
|
||||
u'fname': u'TEST\xc3\x9c\xc3\x9f\xc3\xb8x',
|
||||
u'latitude': 51.396953,
|
||||
u'email': u'fred@qrz.com',
|
||||
u'qslmgr': u'Via BURO or AA7BQ',
|
||||
u'bio': u'2420',
|
||||
u'ccode': 130,
|
||||
u'geoloc': u'user',
|
||||
u'eqsl': False,
|
||||
u'user': u'KF7WIS',
|
||||
u'adif': 79,
|
||||
u'moddate': datetime(2014, 6, 6, 23, 0, 45, tzinfo=UTC),
|
||||
u'license_class': u'3',
|
||||
u'land': u'Guadeloupe',
|
||||
u'imageinfo': u'540:799:101014',
|
||||
u'name': u'CALLSIGN3',
|
||||
u'born': 2010,
|
||||
u'country': u'Jamaica',
|
||||
u'longitude': -68.41959,
|
||||
u'mqsl': False
|
||||
}
|
||||
|
||||
response_XX4XX = {
|
||||
# 'u_views': u'7980',
|
||||
u'biodate': datetime(2014, 9, 17, 19, 46, 54, tzinfo=UTC),
|
||||
u'image': u'http://files.qrz.com/x/xx4xx/IMG_0032.JPG',
|
||||
u'locator': u'DM79mp',
|
||||
u'addr2': u'Getamap and Findit',
|
||||
u'addr1': u'Test Callsign for QRZ',
|
||||
u'imageinfo': u'1200:1600:397936',
|
||||
u'lotw': False,
|
||||
u'state': u'ZZ',
|
||||
u'callsign': u'XX4XX',
|
||||
u'fname': u'Arthur',
|
||||
u'latitude': 39.645,
|
||||
u'iota': u'NA-075',
|
||||
u'qslmgr': u'NO QSL - TEST CALLSIGN',
|
||||
u'bio': u'785',
|
||||
u'ccode': 34,
|
||||
u'geoloc': u'user',
|
||||
u'eqsl': False,
|
||||
u'user': u'XX2XX',
|
||||
u'adif': 64,
|
||||
u'moddate': datetime(2014, 3, 28, 20, 29, 42, tzinfo=UTC),
|
||||
u'name': u'Fay',
|
||||
u'land': u'Bermuda',
|
||||
u'zipcode': u'12345',
|
||||
u'country': u'Bermuda',
|
||||
u'longitude': -104.96,
|
||||
u'mqsl': False
|
||||
}
|
||||
|
||||
response_333 = {
|
||||
const.COUNTRY: u'Iraq',
|
||||
u'cc': u'IQ',
|
||||
const.LONGITUDE: 44.362793,
|
||||
const.CQZ: 21,
|
||||
const.ITUZ: 39,
|
||||
const.LATITUDE: 33.358062,
|
||||
u'timezone': 3.0,
|
||||
const.ADIF: 333,
|
||||
const.CONTINENT: u'AS',
|
||||
u'ccc': u'IRQ'
|
||||
}
|
||||
|
||||
#TESTS
|
||||
#===========================================================
|
||||
|
||||
|
||||
class TestQrzConstructur:
|
||||
|
||||
def test_get_session_key(self):
|
||||
lib = LookupLib(lookuptype="qrz", username=QRZ_USERNAME, pwd=QRZ_PWD)
|
||||
assert len(lib._apikey) == 32
|
||||
|
||||
def test_get_session_key_with_invalid_username(self):
|
||||
with pytest.raises(ValueError):
|
||||
lib = LookupLib(lookuptype="qrz", username="hello", pwd=QRZ_PWD)
|
||||
|
||||
def test_get_session_key_with_invalid_password(self):
|
||||
with pytest.raises(ValueError):
|
||||
lib = LookupLib(lookuptype="qrz", username=QRZ_USERNAME, pwd="hello")
|
||||
|
||||
def test_get_session_key_with_empty_username_and_password(self):
|
||||
with pytest.raises(ValueError):
|
||||
lib = LookupLib(lookuptype="qrz", username="", pwd="")
|
||||
|
||||
|
||||
class TestQrz_Callsign_Lookup:
|
||||
|
||||
def test_lookup_callsign(self, fix_qrz):
|
||||
data = fix_qrz._lookup_qrz_callsign("xx1xx", fix_qrz._apikey)
|
||||
data.pop('u_views', None)
|
||||
assert data == response_XX1XX #check content
|
||||
assert len(data) == len(response_XX1XX) #ensure all fields are included
|
||||
|
||||
data = fix_qrz._lookup_qrz_callsign("XX1XX", fix_qrz._apikey)
|
||||
data.pop('u_views', None)
|
||||
assert data == response_XX1XX
|
||||
|
||||
data = fix_qrz._lookup_qrz_callsign("XX2XX", fix_qrz._apikey)
|
||||
data.pop('u_views', None)
|
||||
assert data == response_XX2XX
|
||||
assert len(data) == len(response_XX2XX)
|
||||
|
||||
data = fix_qrz._lookup_qrz_callsign("XX3XX", fix_qrz._apikey)
|
||||
data.pop('u_views', None)
|
||||
assert data == response_XX3XX
|
||||
assert len(data) == len(response_XX3XX)
|
||||
|
||||
data = fix_qrz._lookup_qrz_callsign("XX4XX", fix_qrz._apikey)
|
||||
data.pop('u_views', None)
|
||||
assert data == response_XX4XX
|
||||
assert len(data) == len(response_XX4XX)
|
||||
|
||||
def test_lookup_callsign_with_unicode_escaping(self, fix_qrz):
|
||||
data = fix_qrz._lookup_qrz_callsign("XX2XX", fix_qrz._apikey)
|
||||
data.pop('u_views', None)
|
||||
assert data == response_XX2XX
|
||||
|
||||
def test_lookup_callsign_does_not_exist(self, fix_qrz):
|
||||
with pytest.raises(KeyError):
|
||||
fix_qrz._lookup_qrz_callsign("XX8XX", fix_qrz._apikey)
|
||||
|
||||
def test_lookup_callsign_with_empty_input(self, fix_qrz):
|
||||
with pytest.raises(ValueError):
|
||||
fix_qrz._lookup_qrz_callsign("", fix_qrz._apikey)
|
||||
|
||||
def test_lookup_callsign_with_invalid_input(self, fix_qrz):
|
||||
with pytest.raises(AttributeError):
|
||||
fix_qrz._lookup_qrz_callsign(3, fix_qrz._apikey)
|
||||
|
||||
|
||||
class TestQrz_DXCC_Lookup:
|
||||
|
||||
def test_lookup_dxcc_with_int(self, fix_qrz):
|
||||
data = fix_qrz._lookup_qrz_dxcc(333, fix_qrz._apikey)
|
||||
assert data == response_333 #check content
|
||||
assert len(data) == len(response_333) #ensure all fields are included
|
||||
|
||||
def test_lookup_dxcc_with_string(self, fix_qrz):
|
||||
data = fix_qrz._lookup_qrz_dxcc("333", fix_qrz._apikey)
|
||||
assert data == response_333 #check content
|
||||
assert len(data) == len(response_333) #ensure all fields are included
|
||||
|
||||
def test_lookup_dxcc_does_not_exist(self, fix_qrz):
|
||||
with pytest.raises(KeyError):
|
||||
fix_qrz._lookup_qrz_dxcc('854', fix_qrz._apikey)
|
||||
|
||||
def test_lookup_dxcc_wrong_input(self, fix_qrz):
|
||||
with pytest.raises(ValueError):
|
||||
fix_qrz._lookup_qrz_dxcc('', fix_qrz._apikey)
|
||||
|
||||
def test_lookup_dxcc(self, fix_qrz):
|
||||
data = fix_qrz.lookup_entity(333)
|
||||
assert data == response_333 #check content
|
||||
|
||||
|
|
@ -26,4 +26,11 @@ class Test_lotw_methods:
|
|||
with pytest.raises(IOError):
|
||||
get_lotw_users(url="http://wd5eae.org/LoTW_Data_XXXXX.txt")
|
||||
|
||||
def test_with_more_than_10_invalid_dates(self, httpserver):
|
||||
httpserver.serve_content(open('./fixtures/lotw_data_with_errors.html').read())
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
get_lotw_users(url=httpserver.url)
|
||||
|
||||
|
||||
|
||||
1
tox.ini
1
tox.ini
|
|
@ -7,6 +7,7 @@
|
|||
envlist = py26,py27,pypy
|
||||
|
||||
[testenv]
|
||||
#deps=-rtox_requirements.txt
|
||||
deps=pytest
|
||||
commands =
|
||||
py.test \
|
||||
|
|
|
|||
5
tox_requirements.txt
Normal file
5
tox_requirements.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
pyephem (3.7.5.3)
|
||||
Pygments (1.6)
|
||||
pytz (2014.2)
|
||||
redis (2.10.3)
|
||||
requests (2.2.1)
|
||||
Loading…
Reference in a new issue