diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle index 33de1d1..37dca23 100644 Binary files a/docs/build/doctrees/environment.pickle and b/docs/build/doctrees/environment.pickle differ diff --git a/docs/build/doctrees/license.doctree b/docs/build/doctrees/license.doctree index 968c26b..7742cce 100644 Binary files a/docs/build/doctrees/license.doctree and b/docs/build/doctrees/license.doctree differ diff --git a/docs/build/doctrees/lookuplib.doctree b/docs/build/doctrees/lookuplib.doctree index 9abe054..93713fe 100644 Binary files a/docs/build/doctrees/lookuplib.doctree and b/docs/build/doctrees/lookuplib.doctree differ diff --git a/docs/build/html/_sources/license.txt b/docs/build/html/_sources/license.txt index 02cd983..ac4a7bc 100644 --- a/docs/build/html/_sources/license.txt +++ b/docs/build/html/_sources/license.txt @@ -1,10 +1,27 @@ license ======= - The MIT License (MIT) -bla bla bla +Copyright (c) 2014 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 +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. Contact: ======== -Contact DH1TW +Contact Tobias@dh1tw.de diff --git a/docs/build/html/license.html b/docs/build/html/license.html index b2fbddb..8d85e49 100644 --- a/docs/build/html/license.html +++ b/docs/build/html/license.html @@ -32,9 +32,6 @@
The MIT License (MIT)
-bla bla bla
+Copyright (c) 2014 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 +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.
This class provides a homogeneous interface to three different Amateur Radio Callsign lookup sources:
+class pyhamtools.lookuplib.LookupLib(lookuptype='countryfile', apikey=None, filename=None, logger=None)¶ +This class is a wrapper for the following three Amateur Radio databases:
The class provides getters to access the data in a structured way. Even the interface is the same -for all lookup sources, the returning data can be different. The documentation of the various -methods provide more detail.
+It’s aim is to provide a homogeneous interface to different data sources.
+Typically it is injected as a dependency in the Callinfo class, but can also be used directly.
+Even the interface is the same for all lookup sources, the returning data can be different. +The documentation of the various methods provide more detail.
By default, LookupLib requires an Internet connection to download the libraries or perform the lookup against the Clublog API.
Returns True if an operations is known as invalid
| Raises: |
|
|---|
Example
+The following code checks the Clublog XML database if the operation is valid for two dates.
+>>> from pyhamtools import LookupLib
+>>> from datetime import datetime
+>>> import pytz
+>>> my_lookuplib = LookupLib(lookuptype="clublogxml", apikey="myapikey")
+>>> print my_lookuplib.is_invalid_operation("5W1CFN")
+True
+>>> try:
+>>> timestamp = datetime(year=2012, month=1, day=31).replace(tzinfo=pytz.UTC)
+>>> my_lookuplib.is_invalid_operation("5W1CFN", timestamp)
+>>> except KeyError:
+>>> print "Seems to be invalid operation before 31.1.2012"
+Seems to be an invalid operation before 31.1.2012
+Note
This method is available for
@@ -123,7 +140,7 @@ API Key for Clublog missing or incorrectReturns lookup data if an exception exists for a callsign
| Raises: |
|
|---|
Example
+The following code queries the the online Clublog API for the callsign “VK9XO” on a specific date.
+>>> from pyhamtools import LookupLib
+>>> from datetime import datetime
+>>> import pytz
+>>> my_lookuplib = LookupLib(lookuptype="clublogapi", apikey="myapikey")
+>>> timestamp = datetime(year=1962, month=7, day=7, tzinfo=pytz.UTC)
+>>> print my_lookuplib.lookup_callsign("VK9XO", timestamp)
+{
+ 'country': 'CHRISTMAS ISLAND',
+ 'longitude': -105.7,
+ 'cqz': 29,
+ 'adif': 35,
+ 'latitude': -10.5,
+ 'continent': 'OC'
+}
+Note
This method is available for
@@ -176,11 +211,28 @@ API Key for Clublog missing or incorrectExample
+The following code queries the the Clublog XML database for the ADIF entity Turkmenistan, which has +the id 273.
+>>> from pyhamtools import LookupLib
+>>> my_lookuplib = LookupLib(lookuptype="clublogapi", apikey="myapikey")
+>>> print my_lookuplib.lookup_entity(273)
+{
+ 'deleted': False,
+ 'country': 'TURKMENISTAN',
+ 'longitude': -58.4,
+ 'cqz': 17,
+ 'prefix': 'EZ',
+ 'latitude': 38.0,
+ 'continent': 'AS'
+}
+Note
This method is available for the following lookup type
@@ -192,7 +244,7 @@ No matching entity foundReturns lookup data of a Prefix
| Raises: |
|
|---|
Example
+The following code shows how to obtain the information for the prefix “DH” from the countryfile.com +database (default database).
+>>> from pyhamtools import LookupLib
+>>> myLookupLib = LookupLib()
+>>> print myLookupLib.lookup_prefix("DH")
+{
+ 'adif': 230,
+ 'country': 'Fed. Rep. of Germany',
+ 'longitude': -10.0,
+ 'cqz': 14,
+ 'ituz': 28,
+ 'latitude': 51.0,
+ 'continent': 'EU'
+}
+Note
This method is available for
@@ -232,7 +301,7 @@ API Key for Clublog missing or incorrectReturns a CQ Zone if an exception exists for the given callsign
Args: callsign (string): Amateur radio callsign @@ -248,7 +317,7 @@ timestamp (datetime, optional): datetime in UTC (tzinfo=pytz.UTC)
Example
+The following code checks the Clublog XML database if a CQ Zone exception exists for the callsign DP0GVN.
+>>> from pyhamtools import LookupLib
+>>> my_lookuplib = LookupLib(lookuptype="clublogxml", apikey="myapikey")
+>>> print my_lookuplib.lookup_zone_exception("DP0GVN")
+38
+The prefix “DP” It is assigned to Germany, but the station is located in Antarctica, and therefore +in CQ Zone 38
Note
This method is available for
diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js index 603cdb9..d96d428 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({envversion:42,terms:{all:3,code:0,identifi:3,text:[],prefix:3,radio:[0,3],same:3,follow:[0,3],entiti:3,xml:3,current:0,clublogxml:3,zone:3,explain:[],except:3,dict:3,tzinfo:3,bool:3,logger:3,match:3,applic:0,lookup_ent:3,sourc:3,"return":3,string:3,variou:3,utc:3,python:[0,3],timestamp:3,veri:[],requir:3,infrequ:3,like:0,specif:3,bla:2,"default":3,stuff:[],necessari:0,contain:[0,3],found:3,readthedoc:0,page:0,some:0,see:0,callsign:[0,3],connect:3,arg:3,download:3,librari:[0,3],even:3,index:0,lookuptyp:3,lookup_prefix:3,lookup_zone_except:3,content:[],version:0,internet:3,print:[],irc:0,complic:[],method:3,kei:3,differ:3,dictionari:3,org:[0,3],come:0,lookup_callsign:3,valu:3,search:0,cty:3,against:3,datetim:3,countri:3,dh1tw:[0,1,2],com:[0,3],frequent:0,oper:3,apikeymissingerror:3,modul:[],filenam:3,api:3,"__name__":3,noresult:3,miss:3,given:3,log:3,wai:3,three:3,avail:3,interfac:3,paramet:3,type:3,more:3,amateur:[0,3],option:3,is_invalid_oper:3,pytz:3,pars:0,known:3,getter:3,"true":3,countryfil:3,none:3,provid:3,access:3,structur:3,record:3,apikei:3,can:3,str:3,webirc:0,creat:0,"int":3,clublogapi:3,exist:3,file:[0,3],deltaxrai:0,plist:3,incorrect:3,perform:3,detail:3,invalid:3,note:[],lookup:3,which:[0,3],you:0,mit:2,lookuplib:[],updat:3,http:[0,3],clublog:3,rais:3,adif:3,bsd:0,data:3,"class":[0,3],homogen:3,github:0,faster:0,descript:[],issu:0,hamtest:0,contact:[],getlogg:3,thi:3,time:3,hello:[],daili:3},objtypes:{"0":"py:module","1":"py:method","2":"py:class"},objnames:{"0":["py","module","Python module"],"1":["py","method","Python method"],"2":["py","class","Python class"]},filenames:["index","help","license","LookupLib"],titles:["PyHamTools","help","license","LookupLib"],objects:{pyhamtools:{lookuplib:[3,0,0,"-"]},"pyhamtools.lookuplib":{LookupLib:[3,2,1,""]},"pyhamtools.lookuplib.LookupLib":{lookup_prefix:[3,1,1,""],lookup_entity:[3,1,1,""],lookup_zone_exception:[3,1,1,""],lookup_callsign:[3,1,1,""],is_invalid_operation:[3,1,1,""]}},titleterms:{help:1,anoth:[],licens:2,clase:0,indic:0,content:[],header:[],contact:2,tabl:0,pyhamtool:0,document:[],simpl:[],modul:0,lookuplib:3,welcom:[]}}) \ No newline at end of file +Search.setIndex({envversion:42,terms:{all:[3,2],code:[0,3],identifi:3,show:3,illustr:[],text:[],clublog:3,obtain:[3,2],myapikei:3,prefix:3,radio:[0,3],same:3,permiss:2,follow:[0,3,2],data:3,bsd:0,entiti:3,xml:3,current:0,clublogxml:3,depend:3,copyright:2,how:3,holder:2,explain:[],tobia:2,except:3,should:[],tort:2,valid:3,dict:3,ituz:3,queri:3,tzinfo:3,aris:2,logger:3,therefor:3,match:3,merchant:2,applic:0,lookup_ent:3,sourc:3,"return":3,string:3,variou:3,utc:3,python:[0,3],timestamp:3,express:2,kind:2,softwar:2,whether:2,condit:2,veri:[],liabl:2,month:3,charg:2,requir:3,infrequ:3,warranti:2,like:0,specif:3,bla:[],"try":3,provid:[3,2],stuff:[],necessari:0,contain:[0,3],found:3,readthedoc:0,page:0,impli:2,right:2,deal:2,replac:3,some:0,see:0,callsign:[0,3],connect:[3,2],arg:3,download:3,http:[0,3],event:2,librari:[0,3],out:2,even:3,index:0,lookuptyp:3,turkmenistan:3,lookup_prefix:3,databas:3,rep:3,publish:2,lookup_zone_except:3,content:[],delet:3,written:[],version:0,inject:3,action:2,internet:3,print:3,"import":3,irc:0,complic:[],method:3,abov:2,kei:3,differ:3,free:2,dictionari:3,locat:3,come:0,lookup_callsign:3,valu:3,log:3,search:0,fit:2,island:3,cty:3,against:3,datetim:3,person:2,doctest:[],permit:2,fals:3,countri:3,typic:3,dh1tw:[0,1,2],com:[0,3],assign:3,frequent:0,oper:3,apikeymissingerror:3,directli:3,merg:2,modul:[],two:3,restrict:2,filenam:3,api:3,org:[0,3],noresult:[],bool:3,miss:3,damag:2,liabil:2,given:3,from:[3,2],christma:3,wai:[],whom:2,modifi:2,three:3,wrapper:3,avail:3,cqz:3,station:3,interfac:3,includ:2,paramet:3,type:3,more:3,"function":[],amateur:[0,3],option:3,copi:2,keyerror:3,notic:2,is_invalid_oper:3,pytz:3,pars:0,callinfo:3,particular:2,known:3,getter:[],herebi:2,"true":3,countryfil:3,none:3,sell:2,"default":3,access:[],structur:[],exampl:3,aim:3,record:3,contin:3,limit:2,can:3,str:3,webirc:0,otherwis:2,purpos:2,latitud:3,claim:2,substanti:2,creat:0,"int":3,clublogapi:3,year:3,my_lookuplib:3,ani:2,dp0gvn:3,antarctica:3,inform:3,exist:3,contract:2,file:[0,3,2],onlin:3,seem:3,deltaxrai:0,plist:3,incorrect:3,issu:0,mylookuplib:3,author:2,perform:3,apikei:3,detail:3,invalid:3,check:3,note:[],also:3,other:2,lookup:3,which:[0,3],you:0,subject:2,mit:2,lookuplib:[],updat:3,furnish:2,example_gener:[],"5w1cfn":3,germani:3,distribut:2,shall:2,fed:3,dai:3,befor:3,zone:3,rais:3,adif:3,sublicens:2,date:3,associ:2,"class":[0,3],longitud:3,homogen:3,noninfring:2,github:0,faster:0,"__name__":3,grant:2,descript:[],wellnitz:2,without:2,vk9xo:3,hamtest:0,portion:2,contact:[],getlogg:3,thi:[3,2],time:3,format:[],hello:[],daili:3},objtypes:{"0":"py:module","1":"py:method","2":"py:class"},objnames:{"0":["py","module","Python module"],"1":["py","method","Python method"],"2":["py","class","Python class"]},filenames:["index","help","license","LookupLib"],titles:["PyHamTools","help","license","LookupLib"],objects:{pyhamtools:{lookuplib:[3,0,0,"-"]},"pyhamtools.lookuplib":{LookupLib:[3,2,1,""]},"pyhamtools.lookuplib.LookupLib":{lookup_prefix:[3,1,1,""],lookup_entity:[3,1,1,""],lookup_zone_exception:[3,1,1,""],lookup_callsign:[3,1,1,""],is_invalid_operation:[3,1,1,""]}},titleterms:{help:1,anoth:[],licens:2,clase:0,indic:0,content:[],header:[],contact:2,tabl:0,pyhamtool:0,document:[],simpl:[],modul:0,lookuplib:3,welcom:[]}}) \ No newline at end of file diff --git a/docs/source/license.rst b/docs/source/license.rst index 02cd983..ac4a7bc 100644 --- a/docs/source/license.rst +++ b/docs/source/license.rst @@ -1,10 +1,27 @@ license ======= - The MIT License (MIT) -bla bla bla +Copyright (c) 2014 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 +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. Contact: ======== -Contact DH1TW +Contact Tobias@dh1tw.de diff --git a/pyhamtools/__init__.py b/pyhamtools/__init__.py index 8b13789..dacdf8d 100644 --- a/pyhamtools/__init__.py +++ b/pyhamtools/__init__.py @@ -1 +1,3 @@ +from pyhamtools.lookuplib import LookupLib + diff --git a/pyhamtools/exceptions.py b/pyhamtools/exceptions.py index 9b01420..922746d 100644 --- a/pyhamtools/exceptions.py +++ b/pyhamtools/exceptions.py @@ -1,14 +1,6 @@ # !/usr/bin/python # Filename: exceptions.py -class LookupError(KeyError): - """ Error while accessing the class """ - pass - -class NoResult(KeyError): - """ No matching result found """ - pass - class APIKeyMissingError(AttributeError): """ API Key is Missing """ pass \ No newline at end of file diff --git a/pyhamtools/lookuplib.py b/pyhamtools/lookuplib.py index 7462158..26694d5 100644 --- a/pyhamtools/lookuplib.py +++ b/pyhamtools/lookuplib.py @@ -15,7 +15,7 @@ import pytz from consts import LookupConventions as const -from exceptions import LookupError, APIKeyMissingError, NoResult +from exceptions import APIKeyMissingError UTC = pytz.UTC timestamp_now = datetime.utcnow().replace(tzinfo=UTC) @@ -24,15 +24,18 @@ timestamp_now = datetime.utcnow().replace(tzinfo=UTC) class LookupLib(object): """ - This class provides a homogeneous interface to three different Amateur Radio Callsign lookup sources: + This class is a wrapper for the following three Amateur Radio databases: 1. Clublog.org (daily updated XML File) 2. Clublog.org (HTTPS lookup) 3. Country-files.com (infrequently updated PLIST File) - The class provides getters to access the data in a structured way. Even the interface is the same - for all lookup sources, the returning data can be different. The documentation of the various - methods provide more detail. + It's aim is to provide a homogeneous interface to different data sources. + + Typically it is injected as a dependency in the Callinfo class, but can also be used directly. + + Even the interface is the same for all lookup sources, the returning data can be different. + The documentation of the various methods provide more detail. By default, LookupLib requires an Internet connection to download the libraries or perform the lookup against the Clublog API. @@ -44,7 +47,7 @@ class LookupLib(object): logger (logging.getLogger(__name__), optional): Python logger """ - def __init__(self, lookuptype = "clublogxml", apikey=None, filename=None, logger=None): + def __init__(self, lookuptype = "countryfile", apikey=None, filename=None, logger=None): self._logger = None if logger: @@ -70,12 +73,10 @@ class LookupLib(object): self._zone_exceptions = {} self._lookuptype = lookuptype - - if self._lookuptype == "clublogxml": self._load_clublogXML(apikey=self._apikey, cty_file=self._lib_filename) elif self._lookuptype == "countryfile": - self._load_countryfile() + self._load_countryfile(cty_file=self._lib_filename) elif self._lookuptype == "clublogapi": pass else: @@ -91,7 +92,25 @@ class LookupLib(object): dict: Dictionary containing the country specific data Raises: - NoResult: No matching entity found + KeyError: No matching entity found + + Example: + The following code queries the the Clublog XML database for the ADIF entity Turkmenistan, which has + the id 273. + + >>> from pyhamtools import LookupLib + >>> my_lookuplib = LookupLib(lookuptype="clublogapi", apikey="myapikey") + >>> print my_lookuplib.lookup_entity(273) + { + 'deleted': False, + 'country': 'TURKMENISTAN', + 'longitude': -58.4, + 'cqz': 17, + 'prefix': 'EZ', + 'latitude': 38.0, + 'continent': 'AS' + } + Note: This method is available for the following lookup type @@ -100,18 +119,14 @@ class LookupLib(object): """ - - if entity is None: - raise LookupError - try: entity = int(entity) if entity in self._entities: return self._entities[entity] else: - raise NoResult + raise KeyError except: - raise NoResult + raise KeyError def lookup_callsign(self, callsign=None, timestamp=timestamp_now): """ @@ -125,9 +140,27 @@ class LookupLib(object): dict: Dictionary containing the country specific data of the callsign Raises: - NoResult: No matching callsign found + KeyError: No matching callsign found APIKeyMissingError: API Key for Clublog missing or incorrect + Example: + The following code queries the the online Clublog API for the callsign "VK9XO" on a specific date. + + >>> from pyhamtools import LookupLib + >>> from datetime import datetime + >>> import pytz + >>> my_lookuplib = LookupLib(lookuptype="clublogapi", apikey="myapikey") + >>> timestamp = datetime(year=1962, month=7, day=7, tzinfo=pytz.UTC) + >>> print my_lookuplib.lookup_callsign("VK9XO", timestamp) + { + 'country': 'CHRISTMAS ISLAND', + 'longitude': -105.7, + 'cqz': 29, + 'adif': 35, + 'latitude': -10.5, + 'continent': 'OC' + } + Note: This method is available for @@ -170,7 +203,7 @@ class LookupLib(object): return self._callsign_exceptions[item] # no matching case - raise NoResult + raise KeyError def lookup_prefix(self, prefix, timestamp=timestamp_now): """ @@ -184,9 +217,26 @@ class LookupLib(object): dict: Dictionary containing the country specific data of the Prefix Raises: - NoResult: No matching Prefix found + KeyError: No matching Prefix found APIKeyMissingError: API Key for Clublog missing or incorrect + Example: + The following code shows how to obtain the information for the prefix "DH" from the countryfile.com + database (default database). + + >>> from pyhamtools import LookupLib + >>> myLookupLib = LookupLib() + >>> print myLookupLib.lookup_prefix("DH") + { + 'adif': 230, + 'country': 'Fed. Rep. of Germany', + 'longitude': -10.0, + 'cqz': 14, + 'ituz': 28, + 'latitude': 51.0, + 'continent': 'EU' + } + Note: This method is available for @@ -221,7 +271,7 @@ class LookupLib(object): else: return self._prefixes[item] - raise NoResult + raise KeyError def is_invalid_operation(self, callsign, timestamp=datetime.utcnow().replace(tzinfo=UTC)): """ @@ -235,9 +285,25 @@ class LookupLib(object): bool: True if a record exists for this callsign (at the given time) Raises: - NoResult: No matching callsign found + KeyError: No matching callsign found APIKeyMissingError: API Key for Clublog missing or incorrect + Example: + The following code checks the Clublog XML database if the operation is valid for two dates. + + >>> from pyhamtools import LookupLib + >>> from datetime import datetime + >>> import pytz + >>> my_lookuplib = LookupLib(lookuptype="clublogxml", apikey="myapikey") + >>> print my_lookuplib.is_invalid_operation("5W1CFN") + True + >>> try: + >>> timestamp = datetime(year=2012, month=1, day=31).replace(tzinfo=pytz.UTC) + >>> my_lookuplib.is_invalid_operation("5W1CFN", timestamp) + >>> except KeyError: + >>> print "Seems to be invalid operation before 31.1.2012" + Seems to be an invalid operation before 31.1.2012 + Note: This method is available for @@ -275,7 +341,7 @@ class LookupLib(object): return True #no matching case - raise NoResult + raise KeyError def lookup_zone_exception(self, callsign, timestamp=datetime.utcnow().replace(tzinfo=UTC)): @@ -290,9 +356,20 @@ class LookupLib(object): int: Value of the the CQ Zone exception which exists for this callsign (at the given time) Raises: - NoResult: No matching callsign found + KeyError: No matching callsign found APIKeyMissingError: API Key for Clublog missing or incorrect + Example: + The following code checks the Clublog XML database if a CQ Zone exception exists for the callsign DP0GVN. + + >>> from pyhamtools import LookupLib + >>> my_lookuplib = LookupLib(lookuptype="clublogxml", apikey="myapikey") + >>> print my_lookuplib.lookup_zone_exception("DP0GVN") + 38 + + The prefix "DP" It is assigned to Germany, but the station is located in Antarctica, and therefore + in CQ Zone 38 + Note: This method is available for @@ -328,7 +405,7 @@ class LookupLib(object): return self._zone_exceptions[item][const.CQZ] #no matching case - raise NoResult + raise KeyError def _lookup_clublogAPI(self, callsign=None, timestamp=timestamp_now, url="https://secure.clublog.org/dxcc", apikey=None): """ Set up the Lookup object for Clublog Online API @@ -362,7 +439,7 @@ class LookupLib(object): elif item == "Continent": lookup[const.CONTINENT] = str(jsonLookup["Continent"]) if lookup[const.ADIF] == 0: - raise NoResult + raise KeyError else: return lookup @@ -407,10 +484,6 @@ class LookupLib(object): cwdFile = os.path.abspath(os.path.join(os.getcwd(), country_mapping_filename)) pkgFile = os.path.abspath(os.path.join(os.path.dirname(__file__), country_mapping_filename)) - print cwdFile - print pkgFile - - # from cwd if os.path.exists(cwdFile): country_mapping_filename = cwdFile @@ -851,8 +924,9 @@ class LookupLib(object): if response.status_code == requests.codes.ok: return True else: - self._logger.error("HTTP Repsonse: " + str(response.text)) + err_str = "HTTP Status Code: " + str(response.status_code) + " HTTP Response: " + str(response.text) + self._logger.error(err_str) if response.text.strip() == error1 or response.text.strip() == error2: raise APIKeyMissingError else: - raise LookupError \ No newline at end of file + raise LookupError(err_str) \ No newline at end of file diff --git a/test/conftest.py b/test/conftest.py index 7d382d5..f735cc8 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,6 +1,9 @@ import pytest import tempfile import os + + +from apikey import APIKEY # # @pytest.fixture() # def cleandir(): @@ -44,10 +47,10 @@ def fixNone(request): -API_KEY = "" + @pytest.fixture(scope="session") def fixApiKey(request): - return(API_KEY) + return(APIKEY) @pytest.fixture(scope="module", params=["clublogapi", "clublogxml", "countryfile"]) def fixGeneralApi(request, fixApiKey): diff --git a/pyhamtools/cty.plist b/test/fixtures/cty.plist similarity index 100% rename from pyhamtools/cty.plist rename to test/fixtures/cty.plist diff --git a/pyhamtools/cty.xml b/test/fixtures/cty.xml similarity index 100% rename from pyhamtools/cty.xml rename to test/fixtures/cty.xml diff --git a/test/test_lookuplib.py b/test/test_lookuplib.py index 3c7211e..5b6c451 100644 --- a/test/test_lookuplib.py +++ b/test/test_lookuplib.py @@ -10,12 +10,8 @@ def fixAnyValue(request): class TestlookupLib: - - def test_construction_without_kwargs(self): - """Load with non without any args & kwargs""" - with pytest.raises(APIKeyMissingError): - LookupLib() - + + def test_construction_with_invalid_kwargs(self, fixAnyValue): """Load with non without any args & kwargs""" with pytest.raises(AttributeError): diff --git a/test/test_lookuplib_clublogapi.py b/test/test_lookuplib_clublogapi.py index 7d6c34f..c16d6ad 100644 --- a/test/test_lookuplib_clublogapi.py +++ b/test/test_lookuplib_clublogapi.py @@ -3,7 +3,7 @@ from datetime import datetime from pyhamtools.lookuplib import LookupLib -from pyhamtools.exceptions import APIKeyMissingError, LookupError, NoResult +from pyhamtools.exceptions import APIKeyMissingError #Fixtures #=========================================================== @@ -93,27 +93,27 @@ class TestclublogApi_Getters: assert fixClublogApi.lookup_callsign("DH1TW/MM") == response_Exception_DH1TW_MM assert fixClublogApi.lookup_callsign("DH1TW/AM") == response_Exception_DH1TW_AM - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogApi.lookup_callsign("QRM") - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogApi.lookup_callsign("") #lookup_prefix(prefix, [date]) #=============================== def test_lookup_callsign(self, fixClublogApi): - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogApi.lookup_prefix("DH") #is_invalid_operation(callsign, [date]) #=============================== def test_is_invalid_operation(self, fixClublogApi): - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogApi.is_invalid_operation("5W1CFN") #lookup_zone_exception(callsign, [date]) #==================================== def test_lookup_zone_exception(self, fixClublogApi): - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogApi.lookup_zone_exception("dp0gvn") diff --git a/test/test_lookuplib_clublogxml.py b/test/test_lookuplib_clublogxml.py index 4d23863..d8ee2bd 100644 --- a/test/test_lookuplib_clublogxml.py +++ b/test/test_lookuplib_clublogxml.py @@ -1,9 +1,10 @@ import pytest from datetime import datetime import pytz +import os from pyhamtools.lookuplib import LookupLib -from pyhamtools.exceptions import APIKeyMissingError, LookupError, NoResult +from pyhamtools.exceptions import APIKeyMissingError UTC = pytz.UTC @@ -117,8 +118,11 @@ response_Prefix_ZD5_1964_to_1971 = { } @pytest.fixture(scope="function") -def fixCtyXmlFile(request): - return "/Users/user/projects/pyhamtools/pyhamtools/cty.xml" +def fix_cty_xml_file(request): + dir = os.path.dirname(__file__) + cty_file_rel = "./fixtures/cty.xml" + cty_file_abs = os.path.join(dir, cty_file_rel) + return cty_file_abs #TESTS @@ -128,16 +132,16 @@ class TestClublogXML_Constructor: def test_with_invalid_api_key(self): with pytest.raises(APIKeyMissingError): - lib = LookupLib(apikey="foo") + lib = LookupLib(lookuptype="clublogxml", apikey="foo") lib.lookup_entity(230) def test_with_no_api_key(self): with pytest.raises(APIKeyMissingError): - lib = LookupLib() + lib = LookupLib(lookuptype="clublogxml") lib.lookup_entity(230) - def test_with_file(self, fixCtyXmlFile): - lib = LookupLib(filename=fixCtyXmlFile) + def test_with_file(self, fix_cty_xml_file): + lib = LookupLib(lookuptype="clublogxml", filename=fix_cty_xml_file) assert lib.lookup_entity(230) == response_Entity_230 class TestclublogXML_Getters: @@ -149,13 +153,13 @@ class TestclublogXML_Getters: assert fixClublogXML.lookup_entity(230) == response_Entity_230 assert fixClublogXML.lookup_entity("230") == response_Entity_230 - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_entity("foo") - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_entity(1000) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_entity(999) @@ -177,7 +181,7 @@ class TestclublogXML_Getters: #timestamp < startdate timestamp = datetime(year=1962, month=7, day=5, tzinfo=UTC) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_callsign("vk9xo", timestamp) def test_lookup_callsign_exception_only_with_end_date(self, fixClublogXML): @@ -187,11 +191,11 @@ class TestclublogXML_Getters: assert fixClublogXML.lookup_callsign("vk9xx", timestamp) == response_Exception_VK9XX_with_end_date # timestamp > enddate - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_callsign("vk9xx") timestamp = datetime(year=1975, month=9, day=16, tzinfo=UTC) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_callsign("vk9xx", timestamp) def test_lookup_callsign_exception_no_start_nor_end_date(self, fixClublogXML): @@ -208,10 +212,10 @@ class TestclublogXML_Getters: def test_lookup_prefix(self, fixClublogXML): assert fixClublogXML.lookup_prefix("DH") == response_Prefix_DH - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_prefix("QRM") - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_prefix("") @@ -223,7 +227,7 @@ class TestclublogXML_Getters: #return empty dict - Prefix was not assigned at that time timestamp = datetime(year=1975, month=9, day=16).replace(tzinfo=UTC) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_prefix("VK9", timestamp) #return new entity (Norfolk Island) @@ -233,14 +237,14 @@ class TestclublogXML_Getters: def test_lookup_prefix_with_entities_having_start_and_stop(self, fixClublogXML): timestamp_before = datetime(year=1964, month=11, day=1).replace(tzinfo=UTC) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_prefix("ZD5", timestamp_before) timestamp_valid = datetime(year=1964, month=12, day=2).replace(tzinfo=UTC) assert fixClublogXML.lookup_prefix("ZD5", timestamp_valid) == response_Prefix_ZD5_1964_to_1971 timestamp_after = datetime(year=1971, month=8, day=1).replace(tzinfo=UTC) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_prefix("ZD5", timestamp_after) @@ -251,30 +255,30 @@ class TestclublogXML_Getters: def test_is_invalid_operations(self, fixClublogXML): #No dataset --> default Operation is True - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.is_invalid_operation("dh1tw") #Invalid Operation with start and end date timestamp_before = datetime(year=1993, month=12, day=30).replace(tzinfo=UTC) timestamp = datetime(year=1994, month=12, day=30).replace(tzinfo=UTC) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.is_invalid_operation("vk0mc") assert fixClublogXML.is_invalid_operation("vk0mc", timestamp) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.is_invalid_operation("vk0mc", timestamp_before) #Invalid Operation with start date timestamp_before = datetime(year=2012, month=1, day=31).replace(tzinfo=UTC) assert fixClublogXML.is_invalid_operation("5W1CFN") - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.is_invalid_operation("5W1CFN", timestamp_before) #Invalid Operation with end date timestamp_before = datetime(year=2004, month=04, day=02).replace(tzinfo=UTC) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.is_invalid_operation("T33C") assert fixClublogXML.is_invalid_operation("T33C", timestamp_before) @@ -287,7 +291,7 @@ class TestclublogXML_Getters: def test_lookup_zone_exception(self, fixClublogXML): #No dataset --> default answer: None - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_zone_exception("dh1tw") #zone exception with no date @@ -299,15 +303,15 @@ class TestclublogXML_Getters: timestamp_after = datetime(year=1993, month=03, day=1).replace(tzinfo=UTC) assert fixClublogXML.lookup_zone_exception("dl1kvc/p", timestamp) == 38 - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_zone_exception("dl1kvc/p", timestamp_before) - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_zone_exception("dl1kvc/p", timestamp_after) #zone exception with start date timestamp_before = datetime(year=2013, month=12, day=26).replace(tzinfo=UTC) assert fixClublogXML.lookup_zone_exception("dh1hb/p") - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixClublogXML.lookup_zone_exception("dh1hb/p", timestamp_before) diff --git a/test/test_lookuplib_countryfile.py b/test/test_lookuplib_countryfile.py index 089c7ff..10a5dad 100644 --- a/test/test_lookuplib_countryfile.py +++ b/test/test_lookuplib_countryfile.py @@ -1,8 +1,9 @@ import pytest +import os from datetime import datetime from pyhamtools.lookuplib import LookupLib -from pyhamtools.exceptions import APIKeyMissingError, NoResult, LookupError +from pyhamtools.exceptions import APIKeyMissingError #Fixtures #=========================================================== @@ -29,8 +30,11 @@ response_Exception_3D2RI = { } @pytest.fixture(scope="function") -def fixPlistFile(request): - return "/Users/user/projects/pyhamtools/pyhamtools/cty.plist" +def fix_plist_file(request): + dir = os.path.dirname(__file__) + cty_file_rel = "./fixtures/cty.plist" + cty_file_abs = os.path.join(dir, cty_file_rel) + return cty_file_abs #TESTS @@ -39,25 +43,22 @@ def fixPlistFile(request): #@pytest.mark.skipif(True, reason="slow test") class Test_Countryfile_Constructor: - def test_object_construction_with_invalid_files(self): - with pytest.raises(AttributeError): - LookupLib("countryfile", download=False) - - with pytest.raises(AttributeError): - LookupLib("countryfile", filename="", download=False) - - with pytest.raises(AttributeError): - LookupLib("countryfile", filename="foo bar", download=False) - + def test_constructor_with_file_instead_of_downlad(self, fix_plist_file): + lib = LookupLib("countryfile", filename=fix_plist_file) + assert lib.lookup_callsign("3D2RI") == response_Exception_3D2RI + def test_constructor_with_invalid_file(self): + with pytest.raises(IOError): + lib = LookupLib("countryfile", filename="foo bar") + lib.lookup_callsign("GB0BVL") class Test_countryfile_Getter_Setter: #lookup_entity(adif) #=============================== def test_getException(self, fixCountryFile): - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixCountryFile.lookup_entity(230) @@ -66,10 +67,10 @@ class Test_countryfile_Getter_Setter: def test_getException(self, fixCountryFile): assert fixCountryFile.lookup_callsign("3D2RI") == response_Exception_3D2RI - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixCountryFile.lookup_callsign("QRM") - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixCountryFile.lookup_callsign("") @@ -78,20 +79,20 @@ class Test_countryfile_Getter_Setter: def test_lookup_prefix(self, fixCountryFile): assert fixCountryFile.lookup_prefix("DH") == response_Prefix_DH - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixCountryFile.lookup_prefix("QRM") - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixCountryFile.lookup_prefix("") #is_invalid_operation(callsign, [date]) #=============================== def test_is_invalid_operation(self, fixCountryFile): - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixCountryFile.is_invalid_operation("5W1CFN") #lookup_zone_exception(callsign, [date]) #==================================== def test_lookup_zone_exception(self, fixCountryFile): - with pytest.raises(NoResult): + with pytest.raises(KeyError): fixCountryFile.lookup_zone_exception("dp0gvn") \ No newline at end of file diff --git a/test/test_lookuplib_gettersetter_api.py b/test/test_lookuplib_gettersetter_api.py index 13b2a8f..0610eb6 100644 --- a/test/test_lookuplib_gettersetter_api.py +++ b/test/test_lookuplib_gettersetter_api.py @@ -4,8 +4,6 @@ import os from datetime import datetime -from pyhamtools.exceptions import NoResult - #Fixtures #=========================================================== @@ -91,7 +89,7 @@ class Test_Getter_Setter_Api_Types_for_all_sources: assert type(entity[attr] is datetime) count +=1 assert len(entity) == count - except NoResult: + except KeyError: pass def test_lookup_callsign(self, fixGeneralApi, fixExceptions): @@ -130,7 +128,7 @@ class Test_Getter_Setter_Api_Types_for_all_sources: #all attributes checked? assert len(ex) == count - except NoResult: + except KeyError: pass except AttributeError: pass @@ -172,7 +170,7 @@ class Test_Getter_Setter_Api_Types_for_all_sources: #all attributes checked? assert len(prefix) == count - except NoResult: + except KeyError: pass except AttributeError: pass @@ -182,7 +180,7 @@ class Test_Getter_Setter_Api_Types_for_all_sources: try: invOp = fixGeneralApi.is_invalid_operation(fixInvalidOperations) assert type(invOp) is bool - except NoResult: + except KeyError: pass except AttributeError: pass @@ -191,7 +189,7 @@ class Test_Getter_Setter_Api_Types_for_all_sources: try: zEx = fixGeneralApi.lookup_zone_exception(fixZoneExceptions) assert type(zEx) is int - except NoResult: + except KeyError: pass except AttributeError: pass @@ -201,7 +199,7 @@ class Test_Getter_Setter_Api_Types_for_all_sources: response = fixGeneralApi.setException(fixSetExceptions) assert type(response) is bool assert fixGeneralApi.lookup_callsign(fixSetExceptions.keys()[0]) == fixSetExceptions[fixSetExceptions.keys()[0]] - except NoResult: + except KeyError: pass except AttributeError: pass