Package: cabrillo
cabrilloA Python library to parse Cabrillo-format amateur radio contest logs, with no external dependencies.Getting StartedBasic Parsing>>>fromcabrillo.parserimportparse_log_file>>>cab=parse_log_file('tests/CQWPX.log')>>>cab.callsign'AA1ZZZ'>>>cab.qso[<cabrillo.qso.QSOobjectat0x10cb09f28>,<cabrillo.qso.QSOobjectat0x10cbc8860>]>>>cab.text()'START-OF-LOG: 3.0\nCREATED-BY: WriteLog V10.72C\nCALLSIGN: AA1ZZZ\n[...snip...]END-OF-LOG:\n'You can also write to a file:withopen('out.cbr','w')aso:cab.write(o)The same works for text-file-like objects.Finally, if you desire to parse Cabrillo data already present as a Python string,
you can do so with, e.g.,fromcabrillo.parserimportparse_log_textcabrillo_text="""START-OF-LOG: 3.0END-OF-LOG:"""cab=parse_log_text(cabrillo_text)Construct a LogFor an up-to-date list of attributes to use in constructing objects
manually, seecabrillo/cabrillo.pyandcabrillo/qso.py. This is helpful if your software maintains QSOs in a different database format and you are just exporting logs in the very end. For example:>>>fromcabrilloimportQSO,Cabrillo>>>fromdatetimeimportdatetime# >>> help(QSO)# >>> help(Cabrillo)>>>qso1=QSO('14313','PH',datetime.strptime('May 30 2018 10:15PM','%b%d%Y %I:%M%p'),'KX0XXX','KX9XXX',de_exch=['59','10','CO'],dx_exch=['44','20','IN'],t=None)>>>cab=Cabrillo(callsign='KX0XXX',email='kx0xxx@example.com',soapbox=['Son of a gun!'])>>>print(cab.text())START-OF-LOG:3.0CALLSIGN:KX0XXXEMAIL:kx0xxx@example.comCREATED-BY:cabrillo(Python)SOAPBOX:Sonofagun!END-OF-LOG:Matching Two QSOs in Contest Scoring>>># We start off with a pair with complementary data.>>>fromcabrilloimportQSO>>>fromdatetimeimportdatetime>>>qso1=QSO('14313','PH',datetime.strptime('May 30 2018 10:15PM','%b%d%Y %I:%M%p'),'KX0XXX','KX9XXX',de_exch=['59','10','CO'],dx_exch=['44','20','IN'],t=None)>>>qso2=QSO('14313','PH',datetime.strptime('May 30 2018 10:10PM','%b%d%Y %I:%M%p'),'KX9XXX','KX0XXX',de_exch=['44','20','IN'],dx_exch=['59','10','CO'],t=None)>>>qso1.match_against(qso2)True>>>qso1.freq='14000'# Same band, still will match.>>>qso1.match_against(qso2)True>>>qso1.match_against(qso2,max_time_delta=1)# Make time checking less lenient.False>>># All flags.>>>qso1.match_against(qso2,max_time_delta=30,check_exch=True,check_band=True)TipsIgnoring MalorderCabrillo logs must be time-sorted. If you want to read files that are
not so sorted, but other than that are Cabrillo files, you can do so by
adding a keyword argumentignore_order=Falseto eitherparse_log_fileorparse_log_text. If you do that, the resulting Cabrillo object
will refuse to generate (potentially non-)Cabrillo output.ContributingPull requests are appreciated! Please test your changes usingpytest.# Activate a virtual environment using your favorite tool.$pip-rrequirements_test.txt
$pytest--cov-reportterm-missing--cov
*snip*
----------coverage:platformlinux,python3.12.1-final-0-----------
NameStmtsMissCoverMissing
--------------------------------------------------------
cabrillo/__init__.py40100%
cabrillo/cabrillo.py600100%
cabrillo/data.py440100%
cabrillo/errors.py30100%
cabrillo/parser.py620100%
cabrillo/qso.py590100%
tests/path_helper.py60100%
tests/test_cabrillo.py620100%
tests/test_parser_log.py890100%
tests/test_parser_qso.py510100%
tests/test_qso.py1000100%
--------------------------------------------------------
TOTAL5400100%======================================================================24passedin0.21s=======================================================================