mirror of
https://github.com/dh1tw/pyhamtools.git
synced 2026-03-09 23:04:02 +01:00
Compare commits
7 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c15ab8c2c | ||
|
|
8ef752e3ad | ||
|
|
9c61f75c28 | ||
|
|
b51b32e575 | ||
|
|
a12616ceca | ||
|
|
1a79467db1 | ||
|
|
4bdaf8d335 |
77
.github/workflows/test.yml
vendored
77
.github/workflows/test.yml
vendored
|
|
@ -3,61 +3,17 @@ name: Linux
|
|||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test_linux_legacy:
|
||||
# Ubuntu 20.04 is still required for python 3.6; this doesn't work on Ubuntu 22.04 anymore
|
||||
runs-on: "ubuntu-20.04"
|
||||
name: "Ubuntu 20.04 - Python ${{ matrix.python-version }}"
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.6"]
|
||||
redis-version: [6]
|
||||
|
||||
steps:
|
||||
- uses: "actions/checkout@v3"
|
||||
- uses: "actions/setup-python@v4"
|
||||
with:
|
||||
python-version: "${{ matrix.python-version }}"
|
||||
cache: "pip"
|
||||
cache-dependency-path: |
|
||||
**/setup.py
|
||||
**/requirements*.txt
|
||||
|
||||
- name: "Install dependencies"
|
||||
run: |
|
||||
set -xe
|
||||
sudo apt-get install -y libxml2-dev libxslt-dev
|
||||
python -VV
|
||||
python -m pip install --upgrade pip setuptools
|
||||
python -m pip install -e .
|
||||
python -m pip install -r requirements-pytest.txt
|
||||
|
||||
- name: Start Redis
|
||||
uses: supercharge/redis-github-action@1.2.0
|
||||
with:
|
||||
redis-version: ${{ matrix.redis-version }}
|
||||
|
||||
- name: "Run tests for ${{ matrix.python-version }}"
|
||||
env:
|
||||
CLUBLOG_APIKEY: ${{ secrets.CLUBLOG_APIKEY }}
|
||||
QRZ_USERNAME: ${{ secrets.QRZ_USERNAME }}
|
||||
QRZ_PWD: ${{ secrets.QRZ_PWD }}
|
||||
PYTHON_VERSION: ${{ matrix.python-version }}
|
||||
# delay the execution randomly by a couple of seconds to reduce the amount
|
||||
# of concurrent API calls on Clublog and QRZ.com when all CI jobs execute simultaneously
|
||||
run: |
|
||||
sleep $[ ( $RANDOM % 10 ) + 1 ]s
|
||||
pytest ./test
|
||||
|
||||
test_linux:
|
||||
runs-on: "ubuntu-22.04"
|
||||
name: "Ubuntu 22.04 - Python ${{ matrix.python-version }}"
|
||||
runs-on: "ubuntu-24.04"
|
||||
name: "Ubuntu 24.04 - Python ${{ matrix.python-version }}"
|
||||
env:
|
||||
USING_COVERAGE: '3.11'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.8", "pypy3.9", "pypy3.10"]
|
||||
redis-version: [6]
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.8", "pypy3.9", "pypy3.10"]
|
||||
redis-version: [7]
|
||||
|
||||
steps:
|
||||
- uses: "actions/checkout@v3"
|
||||
|
|
@ -93,7 +49,7 @@ jobs:
|
|||
# delay the execution randomly by a couple of seconds to reduce the amount
|
||||
# of concurrent API calls on Clublog and QRZ.com when all CI jobs execute simultaneously
|
||||
run: |
|
||||
sleep $[ ( $RANDOM % 10 ) + 1 ]s
|
||||
sleep $[ ( $RANDOM % 60 ) + 1 ]s
|
||||
if [[ $PYTHON_VERSION == 3.11 ]]
|
||||
then
|
||||
pytest --cov=test/
|
||||
|
|
@ -116,13 +72,12 @@ jobs:
|
|||
|
||||
|
||||
test_macos:
|
||||
# Ubuntu 20.04 is still required for python 3.6; this doesn't work on Ubuntu 22.04 anymore
|
||||
runs-on: "macos-12"
|
||||
name: "MacOS 12 - Python ${{ matrix.python-version }}"
|
||||
runs-on: "macos-15"
|
||||
name: "MacOS 15 - Python ${{ matrix.python-version }}"
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.8", "pypy3.9", "pypy3.10"]
|
||||
redis-version: [6]
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.8", "pypy3.9", "pypy3.10"]
|
||||
redis-version: [7.2]
|
||||
|
||||
steps:
|
||||
- uses: "actions/checkout@v3"
|
||||
|
|
@ -143,7 +98,7 @@ jobs:
|
|||
python -m pip install -r requirements-pytest.txt
|
||||
|
||||
- name: Start Redis
|
||||
uses: shogo82148/actions-setup-redis@v1.31.1
|
||||
uses: shogo82148/actions-setup-redis@v1
|
||||
with:
|
||||
redis-version: ${{ matrix.redis-version }}
|
||||
|
||||
|
|
@ -156,16 +111,16 @@ jobs:
|
|||
# delay the execution randomly by a couple of seconds to reduce the amount
|
||||
# of concurrent API calls on Clublog and QRZ.com when all CI jobs execute simultaneously
|
||||
run: |
|
||||
sleep $[ ( $RANDOM % 10 ) + 1 ]
|
||||
sleep $[ ( $RANDOM % 60 ) + 1 ]
|
||||
pytest ./test
|
||||
|
||||
test_windows:
|
||||
runs-on: "windows-latest"
|
||||
runs-on: "windows-2022"
|
||||
name: "Windows latest - Python ${{ matrix.python-version }}"
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
|
||||
|
||||
steps:
|
||||
- uses: "actions/checkout@v3"
|
||||
|
|
@ -193,8 +148,10 @@ jobs:
|
|||
C:\msys64\usr\bin\wget.exe https://github.com/redis-windows/redis-windows/releases/download/7.0.14/Redis-7.0.14-Windows-x64-msys2-with-Service.zip
|
||||
C:\msys64\usr\bin\pacman.exe -S --noconfirm unzip
|
||||
C:\msys64\usr\bin\unzip.exe Redis-7.0.14-Windows-x64-msys2-with-Service.zip
|
||||
sc.exe create Redis binpath=D:\a\pyhamtools\pyhamtools\Redis-7.0.14-Windows-x64-msys2-with-Service\RedisService.exe start= auto
|
||||
sc.exe create Redis binpath=${{ github.workspace }}\Redis-7.0.14-Windows-x64-msys2-with-Service\RedisService.exe start= auto
|
||||
echo "Redis service created, now starting it"
|
||||
net start Redis
|
||||
echo "Redis service started"
|
||||
|
||||
- name: "Run tests for ${{ matrix.python-version }}"
|
||||
env:
|
||||
|
|
@ -207,5 +164,5 @@ jobs:
|
|||
# amount of concurrent API calls on Clublog and QRZ.com
|
||||
# when all CI jobs execute simultaneously
|
||||
run: |
|
||||
start-sleep -Seconds (5..20 | get-random)
|
||||
start-sleep -Seconds (5..60 | get-random)
|
||||
pytest
|
||||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Tobias Wellnitz
|
||||
Copyright (c) 2025 Tobias Wellnitz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -34,19 +34,21 @@ This Library is used in production at the [DXHeat.com DX Cluster](https://dxheat
|
|||
Pyhamtools is compatible with Python >=3.6.
|
||||
We check compatibility on OSX, Windows, and Linux with the following Python versions:
|
||||
|
||||
* Python 3.6 (will be deprecated in 2024)
|
||||
* Python 3.7 (will be deprecated in 2024)
|
||||
* Python 3.8
|
||||
* Python 3.9
|
||||
* Python 3.10
|
||||
* Python 3.11
|
||||
* Python 3.12
|
||||
* [pypy3.7](https://pypy.org/) (will be deprecated in 2024)
|
||||
* Python 3.13
|
||||
* [pypy3.8](https://pypy.org/)
|
||||
* [pypy3.9](https://pypy.org/)
|
||||
* [pypy3.10](https://pypy.org/)
|
||||
|
||||
The support for Python 2.7 and 3.5 has been deprecated at the end of 2023. The last version which supports Python 2.7 and Python 3.5 is 0.8.7.
|
||||
### depreciated: Python 2.7 & Python 3.5
|
||||
The support for Python 2.7 and 3.5 has been deprecated at the end of 2023. The last version which supports Python 2.7 and Python 3.5 is 0.8.7.
|
||||
|
||||
### depricated: Python 3.6 & Python 3.7
|
||||
Support for Python 3.6 and Python 3.7 has been deprecated in June 2025. The last version which support Python 3.6 and Python 3.7 is 0.11.0.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,18 @@
|
|||
Changelog
|
||||
---------
|
||||
|
||||
PyHamtools 0.12.0
|
||||
================
|
||||
|
||||
09. June 2025
|
||||
|
||||
* deprecated support for Python 3.6
|
||||
* deprecated support for Python 3.7
|
||||
* added support for higher Microwave bands (tnx @sq6emm)
|
||||
* added support for 10 characters Maidenhead locators (tnx @sq6emm)
|
||||
* updated CI pipeline
|
||||
|
||||
|
||||
PyHamtools 0.11.0
|
||||
================
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ from pyhamtools.version import __version__, __release__
|
|||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinx_rtd_dark_mode',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
|
|
@ -95,7 +96,9 @@ pygments_style = 'sphinx'
|
|||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
# html_theme = 'default'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
# html_theme = 'sphinx_material'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ def freq_to_band(freq):
|
|||
elif ((freq >= 1200000) and (freq <= 1300000)):
|
||||
band = 0.23 #23cm
|
||||
mode = None
|
||||
elif ((freq >= 2390000) and (freq <= 2450000)):
|
||||
elif ((freq >= 2300000) and (freq <= 2450000)):
|
||||
band = 0.13 #13cm
|
||||
mode = None
|
||||
elif ((freq >= 3300000) and (freq <= 3500000)):
|
||||
|
|
@ -200,7 +200,19 @@ def freq_to_band(freq):
|
|||
elif ((freq >= 47000000) and (freq <= 47200000)):
|
||||
band = 0.0063 #6,3mm
|
||||
mode = None
|
||||
elif ((freq >= 75500000) and (freq <= 81500000)):
|
||||
band = 0.004 #4mm
|
||||
mode = None
|
||||
elif ((freq >= 122250000) and (freq <= 123000000)):
|
||||
band = 0.0025 #2.5mm
|
||||
mode = None
|
||||
elif ((freq >= 134000000) and (freq <= 141000000)):
|
||||
band = 0.002 #2mm
|
||||
mode = None
|
||||
elif ((freq >= 241000000) and (freq <= 250000000)):
|
||||
band = 0.001 #1mm
|
||||
mode = None
|
||||
else:
|
||||
raise KeyError
|
||||
|
||||
return {"band": band, "mode": mode}
|
||||
return {"band": band, "mode": mode}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ def latlong_to_locator (latitude, longitude, precision=6):
|
|||
Args:
|
||||
latitude (float): Latitude
|
||||
longitude (float): Longitude
|
||||
precision (int): 4,6,8 chars (default 6)
|
||||
precision (int): 4,6,8,10 chars (default 6)
|
||||
|
||||
Returns:
|
||||
string: Maidenhead locator
|
||||
|
|
@ -33,7 +33,7 @@ def latlong_to_locator (latitude, longitude, precision=6):
|
|||
|
||||
"""
|
||||
|
||||
if precision < 4 or precision ==5 or precision == 7 or precision > 8:
|
||||
if precision < 4 or precision == 5 or precision == 7 or precision == 9 or precision > 10:
|
||||
return ValueError
|
||||
|
||||
if longitude >= 180 or longitude <= -180:
|
||||
|
|
@ -99,7 +99,7 @@ def locator_to_latlong (locator, center=True):
|
|||
|
||||
locator = locator.upper()
|
||||
|
||||
if len(locator) < 4 or len(locator) == 5 or len(locator) == 7:
|
||||
if len(locator) < 4 or len(locator) == 5 or len(locator) == 7 or len(locator) == 9:
|
||||
raise ValueError
|
||||
|
||||
if ord(locator[0]) > ord('R') or ord(locator[0]) < ord('A'):
|
||||
|
|
@ -126,6 +126,12 @@ def locator_to_latlong (locator, center=True):
|
|||
if ord (locator[7]) > ord('9') or ord(locator[7]) < ord('0'):
|
||||
raise ValueError
|
||||
|
||||
if len(locator) == 10:
|
||||
if ord(locator[8]) > ord('X') or ord(locator[8]) < ord('A'):
|
||||
raise ValueError
|
||||
if ord (locator[9]) > ord('X') or ord(locator[9]) < ord('A'):
|
||||
raise ValueError
|
||||
|
||||
longitude = (ord(locator[0]) - ord('A')) * 20 - 180
|
||||
latitude = (ord(locator[1]) - ord('A')) * 10 - 90
|
||||
longitude += (ord(locator[2]) - ord('0')) * 2
|
||||
|
|
@ -156,6 +162,20 @@ def locator_to_latlong (locator, center=True):
|
|||
longitude += 5.0 / 600 / 2
|
||||
latitude += 2.5 / 600 / 2
|
||||
|
||||
elif len(locator) == 10:
|
||||
longitude += (ord(locator[4]) - ord('A')) * 5.0 / 60
|
||||
latitude += (ord(locator[5]) - ord('A')) * 2.5 / 60
|
||||
|
||||
longitude += int(locator[6]) * 5.0 / 600
|
||||
latitude += int(locator[7]) * 2.5 / 600
|
||||
|
||||
longitude += (ord(locator[8]) - ord('A')) * 1.0 / 2880
|
||||
latitude += (ord(locator[9]) - ord('A')) * 1.0 / 5760
|
||||
|
||||
if center:
|
||||
longitude += 1.0 / 2880 / 2
|
||||
latitude += 1.0 / 5760 / 2
|
||||
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
VERSION = (0, 11, 0)
|
||||
VERSION = (0, 12, 0)
|
||||
__release__ = ''.join(['-.'[type(x) == int]+str(x) for x in VERSION])[1:]
|
||||
__version__ = '.'.join((str(VERSION[0]), str(VERSION[1])))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
sphinx>=1.8.5
|
||||
sphinxcontrib-napoleon>=0.7
|
||||
beautifulsoup4>=4.7.1
|
||||
beautifulsoup4>=4.7.1
|
||||
sphinx_rtd_theme>=0.5.2
|
||||
sphinx_rtd_dark_mode>=0.1.2
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
pytest>=7.0.0; python_version>='3.7'
|
||||
pytest==4.6.11; python_version=='3.6'
|
||||
pytest>=7.0.0
|
||||
pytest-blockage>=0.2.2
|
||||
pytest-localserver>=0.5
|
||||
pytest-cov>=2.12
|
||||
maidenhead==1.6.0
|
||||
maidenhead==1.6.0
|
||||
requests>=2.32.4
|
||||
beautifulsoup4==4.13.4
|
||||
redis==5.2.1
|
||||
ephem==4.2
|
||||
|
|
@ -23,6 +23,10 @@ class Test_latlong_to_locator():
|
|||
assert latlong_to_locator(48.51760, 9.40345, precision=8) == "JN48QM84"
|
||||
assert latlong_to_locator(39.222916, -86.45416, 8) == "EM69SF53"
|
||||
|
||||
def test_latlong_to_locator_10chars_precision(self):
|
||||
assert latlong_to_locator(45.835677, 68.525173, precision=10) == "MN45GU30AN"
|
||||
assert latlong_to_locator(51.124913, 16.941840, 10) == "JO81LC39AX"
|
||||
|
||||
def test_latlong_to_locator_invalid_characters(self):
|
||||
|
||||
# throws ValueError in Python2 and TypeError in Python3
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ class Test_locator_to_latlong():
|
|||
assert abs(latitude - 48.52083) < 0.00001
|
||||
assert abs(longitude - 9.37500) < 0.00001
|
||||
|
||||
def test_locator_to_latlong_8chars(self):
|
||||
|
||||
def test_locator_to_latlong_8chars_precision(self):
|
||||
latitude, longitude = locator_to_latlong("JN48QM84")
|
||||
assert abs(latitude - 48.51875) < 0.00001
|
||||
assert abs(longitude - 9.40416) < 0.00001
|
||||
|
|
@ -40,6 +39,15 @@ class Test_locator_to_latlong():
|
|||
assert abs(latitude - 39.222916) < 0.00001
|
||||
assert abs(longitude + 86.45416) < 0.00001
|
||||
|
||||
def test_locator_to_latlong_10chars_precision(self):
|
||||
latitude, longitude = locator_to_latlong("JO81LC39AX")
|
||||
assert abs(latitude - 51.124913) < 0.000001
|
||||
assert abs(longitude - 16.941840) < 0.000001
|
||||
|
||||
latitude, longitude = locator_to_latlong("MN45GU30AN")
|
||||
assert abs(latitude - 45.835677) < 0.000001
|
||||
assert abs(longitude - 68.525173) < 0.000001
|
||||
|
||||
def test_locator_to_latlong_consistency_checks_6chars_lower_left_corner(self):
|
||||
|
||||
latitude_4, longitude_4 = locator_to_latlong("JN48", center=False)
|
||||
|
|
@ -97,6 +105,9 @@ class Test_locator_to_latlong():
|
|||
with pytest.raises(ValueError):
|
||||
latitude, longitude = locator_to_latlong("JN8QM1")
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
latitude, longitude = locator_to_latlong("JN8QM1AA")
|
||||
|
||||
def test_locator_to_latlong_invalid_characters(self):
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ class Test_utils_freq_to_band():
|
|||
assert freq_to_band(1200000) == {"band" : 0.23, "mode":None}
|
||||
|
||||
def test_shf_frequencies(self):
|
||||
assert freq_to_band(2320200) == {"band" : 0.13, "mode":None}
|
||||
assert freq_to_band(2390000) == {"band" : 0.13, "mode":None}
|
||||
|
||||
assert freq_to_band(3300000) == {"band" : 0.09, "mode":None}
|
||||
|
|
|
|||
Loading…
Reference in a new issue