From 085592de6ac9add0915a8d54f185f52b63eccb06 Mon Sep 17 00:00:00 2001 From: Karim Bahgat Date: Tue, 4 Aug 2015 16:10:43 +0200 Subject: [PATCH] Parsing unknown wkt parsing now works (though only very basic detection method), and better error handling in tester --- pycrs/loader.py | 2 +- pycrs/loader.pyc | Bin 1700 -> 1911 bytes pycrs/parser.py | 60 ++++++++++++++++++++++++++++++++------------ pycrs/parser.pyc | Bin 12483 -> 15345 bytes pycrs/webscrape.pyc | Bin 2334 -> 2357 bytes tester.py | 12 ++++----- 6 files changed, 51 insertions(+), 23 deletions(-) diff --git a/pycrs/loader.py b/pycrs/loader.py index 725cebf..f161271 100644 --- a/pycrs/loader.py +++ b/pycrs/loader.py @@ -16,7 +16,7 @@ def from_url(url, format=None): Arguments: - *url*: The url where the crs string is to be read from. - - *format*: Which format to parse the crs string as. One of "ogcwkt", "esriwkt", or "proj4", but also several others... + - *format*: Which format to parse the crs string as. One of "ogc wkt", "esri wkt", or "proj4". Returns: - CRS object. diff --git a/pycrs/loader.pyc b/pycrs/loader.pyc index 62905009a6dad0f7b9236c16c3104faa811daeac..3b408f52d9ce7cba1062e1072aedd3f705655fbe 100644 GIT binary patch delta 254 zcmZ3&`<;)S`7vVUW8V4V0rt6q>GN=-~rNGrnTpQfOcpPsBxo?W7(qo9;pT$BlA z=NBm`6%^%XnJ7V>9F$s8T9gNOuyatbLVi+KYI2F*=1fK*Mn;~^HB8yej2e?)u6 diff --git a/pycrs/parser.py b/pycrs/parser.py index 87ded17..b94176e 100644 --- a/pycrs/parser.py +++ b/pycrs/parser.py @@ -95,14 +95,30 @@ def from_esri_wkt(string, strict=False): # parse arguments into components # use args to create crs return _from_wkt(string, "esri", strict) - + +def from_unknown_wkt(string, strict=False): + """ + Given an unknown wkt string, detect if uses ogc or esri flavor, and parse the crs accordingly. + + Arguments: + - *string*: The unknown WKT representation as a string. + - *strict* (optional): When True, the parser is strict about names having to match + exactly with upper and lowercases. Default is not strict (False). + + Returns: + - CRS object. + """ + # parse arguments into components + # use args to create crs + return _from_wkt(string, None, strict) + def _from_wkt(string, wkttype, strict=False): """ Internal method for parsing wkt, with minor differences depending on ogc or esri style. Arguments: - *string*: The OGC or ESRI WKT representation as a string. - - *wkttype*: How to parse the WKT string, as either 'ogc' or 'esri'. + - *wkttype* (optional): How to parse the WKT string, as either 'ogc', 'esri', or None. If None, tries to autodetect the wkt type before parsing (default). - *strict* (optional): When True, the parser is strict about names having to match exactly with upper and lowercases. Default is not strict (False). @@ -114,8 +130,8 @@ def _from_wkt(string, wkttype, strict=False): # - Maybe verify elem arg name # make sure valid wkttype - wkttype = wkttype.lower() - assert wkttype in ("ogc","esri") + if wkttype: wkttype = wkttype.lower() + assert wkttype in ("ogc","esri",None) # remove newlines and multi spaces string = " ".join(string.split()) @@ -212,7 +228,7 @@ def _from_wkt(string, wkttype, strict=False): consumed = _clean_value(consumed) items.append(consumed) return items - + # load into nested tuples and arglists crstuples = [] chars = (char for char in string) @@ -222,6 +238,24 @@ def _from_wkt(string, wkttype, strict=False): crstuples.append((header, content)) char = next(chars, None) + # autodetect wkttype if not specified + if not wkttype: + topheader,topcontent = crstuples[0] + if topheader == "PROJCS": + geogcsheader,geogcscontent = topcontent[1] + elif topheader == "GEOGCS": + geogcsheader,geogcscontent = topheader,topcontent + + # datum elem should be second under geogcs + datumheader, datumcontent = geogcscontent[1] + datumname = datumcontent[0].upper().strip('"') + + # esri wkt datums all use "D_" before the datum name + if datumname.startswith("D_"): + wkttype = "esri" + else: + wkttype = "ogc" + # parse into actual crs objects def _parse_top(header, content): "procedure for parsing the toplevel crs element and all its children" @@ -396,12 +430,6 @@ def _from_wkt(string, wkttype, strict=False): # use args to create crs return crs -##def from_unknown_wkt(string, strict=False): -## # detect if ogc wkt or esri wkt -## # TIPS: esri wkt datums all use "D_" before the datum name -## # then load with appropriate function -## pass - def from_proj4(string, strict=False): """ Parse crs as proj4 formatted string and return the resulting crs object. @@ -717,23 +745,23 @@ def from_unknown_text(text, strict=False): Detect crs string format and parse into crs object with appropriate function. Arguments: - - *string*: The crs text representation of unknown type. + - *string*: The crs text representation of unknown type. - *strict* (optional): When True, the parser is strict about names having to match exactly with upper and lowercases. Default is not strict (False). Returns: - CRS object. """ - - if string.startswith("urn:"): - from_ogc_urn(string, strict) - elif string.startswith("+"): + if string.startswith("+"): from_proj4(string, strict) elif string.startswith(("PROJCS[","GEOGCS[")): from_unknown_wkt(string, strict) + #elif string.startswith("urn:"): + # from_ogc_urn(string, strict) + elif string.startswith("EPSG:"): from_epsg_code(string.split(":")[1]) diff --git a/pycrs/parser.pyc b/pycrs/parser.pyc index e4a9cf522c9a99a7716f5b2b347464ced68c5986..eb1c1cfc77835604fcb116dc52ab8104fe20d171 100644 GIT binary patch delta 4756 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 delta 1979 zcmZuyTTGl)5T5fd`|l0Pt>x0?QYe+xMG6IKp{*_DrnG_0S(@6`mg4RYWm$HY|37pa zvjkI&;De21Vtg=O5*uG^O_Z7#AJjyB@}ZBKn0kvzAFPR&7d0kz=4=-db^o02pMP#= z&di+IU$dW11zo?F_@6O9IT?fdKZD*!X*nOP2j3};Z-Zw6&XhvD6r!QB^*f)50lY4T zF=u=(+$h{p{oQ~!T_LoJ)&o1))Jp()=@4nxqwNl3$XqXP*^(BE9imv^U2mH)0r-b0 zG3vb zz!d>;7bFbG0VG_QESX*|f?N@-2v~B%<$lPy!M+V^E@l$FV!)FIESa$6fgBmSA!kC) z1JeeZ2&IkVC9FsG3$Mbd)go9mVU<)|5ck7#6a^^}9e~NtFm^HGks@o}aA1ErG~EdSd_djX84Qx?`$tco$bR&lGVhFKv_lMFJ{5rkMz)-yB^ zC?CPXVp>_Ti&M62#9w-b@or_MIQQQ68^UA{vKBXXL_~uYjaF?FSMYRIy_xrjxvH?4 z_l7sB_KGIFT@`b;k=Yy$RsSs3Ho9uw7A6-|ZhBaLkv?_#Opv?PFW3#L+Fxv8= zcha}qM=%!R8tS7clc=do#!AKWr*gBTl40v;%$rr#ydxWl${TmEirK`t8^5dW$0OBl zaTSY#iGRfyxK29vW8AnG{IaM*?-`NfqXW@dl2J_f!>-o@nmsZ!J~9x+NM|>G*wiN4 z@lI2BSt}_i4ni$vl9ueoaPxrZ#dLGKsKeKqkD4L&@*w`$ye`5Umv&zgW|BBJ0e@?G zIjr~48F2X6>6w_rrL!D+b}YnI)2@^0tYzc-ds@eIJ-Ugn6C%0liVX*3G{koxpPhN8 zwzG^~#B4{$=4@q6-Vf^91G`#uvhulNGp?%S2<5{J>_yJw8~#J(vV!PGX*p~SzG8f& zwSFVfn)DbF@T>L+?(OIo)ws}cTD0I79dWUS9i1SSKjBQzRl$pmF z^o8K7A^8NV6llzJm5XllcmLEf!2Cf5n;^8CDcxrJ^b`Df5^H;oU6^F@0>czToWWw4 zCeRzl($@5}BQF-dtz>dG<4CTvq=5v=OE7P#`NgD~m1mhf$1u(i!FPKq>z^i4pECVa zLO#L#(+p=A&f_`rc$rSv3}wjqie*-C;w1gAVlg*#+{f;Ci2G?m2Kb~W2=MrU6K(qPEZV6)het;^W2X~` z9S@QD8-3Q{i#imEj`Yb(_)YIf&E}m^OgU=GR!(+SUBpOV)ge_zylFc|upDo#GY79#CflwO*fnpaY6#ialQx(Zs!`6;O-l?AC< qljYcDHS~~$wX76EGEx;lD&XR2`9-;jC0d(f*=-mZIVaEJXaN9$Zyoah delta 83 zcmdlgG*5_~`7^s;Pxh5ZA3*pjLNX}15EvYO>ovhC;tHh-M1Q0PRg^-L? Zuq;$CEx#x?v1D@zyA2~F$K;J1EdcIV7tsI! diff --git a/tester.py b/tester.py index d0c4402..66ad539 100644 --- a/tester.py +++ b/tester.py @@ -1,5 +1,5 @@ import pycrs - +import traceback @@ -84,15 +84,15 @@ def sourcestrings(format): def testoutputs(crs): print("To:\n") try: result = crs.to_ogc_wkt() - except: result = "Fail" + except: result = traceback.format_exc() print("ogc_wkt: %s \n" % result) try: result = crs.to_esri_wkt() - except: result = "Fail" + except: result = traceback.format_exc() print("esri_wkt: %s \n" % result) try: result = crs.to_proj4() - except: result = "Fail" + except: result = traceback.format_exc() print("proj4: %s \n" % result) @@ -129,8 +129,8 @@ for wkt in sourcestrings("ogcwkt"): # test outputs testoutputs(crs) - except Exception as err: - print(err) + except: + print(traceback.format_exc()+"\n") #render_world(crs)