<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;
mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
p
{mso-style-priority:99;
mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
font-size:12.0pt;
font-family:"Times New Roman",serif;}
code
{mso-style-priority:99;
font-family:"Courier New";}
pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0cm;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New";}
span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:"Courier New";}
p.msonormal0, li.msonormal0, div.msonormal0
{mso-style-name:msonormal;
mso-style-priority:99;
mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
font-size:12.0pt;
font-family:"Times New Roman",serif;}
span.EmailStyle22
{mso-style-type:personal;
font-family:"Calibri",sans-serif;
color:windowtext;}
span.EmailStyle23
{mso-style-type:personal;
font-family:"Calibri",sans-serif;
color:#1F497D;}
span.EmailStyle24
{mso-style-type:personal-reply;
font-family:"Calibri",sans-serif;
color:#1F497D;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-CA" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><i><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA">Here is the path I'm following in trying to deconstruct
</span></i><i><span style="color:#1F497D">GDALArgumentParser.</span></i><i><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA"><o:p></o:p></span></i></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA">With
</span><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">file = pc2rgb.py</span><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA">:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> r = subprocess.run([sys.executable,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> file],<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> shell=True,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> capture_output=True,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> text=True,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> )<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> if debug:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> print(f'returncode: {r.returncode}')<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA">I get:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">returncode: 2<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA">Digging in to pct2rgb.py I see main() calling PCT2RGB class, calling pct2rgb function,
which should error out with an exception.:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">def main(argv=sys.argv):<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return PCT2RGB().main(argv)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> def doit(self, **kwargs):<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return pct2rgb(**kwargs)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">def doit(**kwargs):<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> try:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> ds = pct2rgb(**kwargs)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return ds, 0<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> except:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return None, 1<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">def pct2rgb(src_filename: PathLikeOrStr, pct_filename: Optional[PathLikeOrStr], dst_filename: PathLikeOrStr,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> band_number: int = 1, out_bands: int = 3, driver_name: Optional[str] = None):<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> # Open source file<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> src_ds = open_ds(src_filename)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> if src_ds is None:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> raise Exception(f'Unable to open {src_filename} ')<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> ...<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA">So I'm thinking that while PCT2RGB class is invoking GDALArgumentParser it's exiting
early somehow with this 2 return code.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">def get_parser(self, argv) -> GDALArgumentParser:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> ...<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return parser<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA">I look at
</span><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">auxillary/gdal_argparse.py</span><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA">:
</span><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">class GDALArgumentParser(argparse.ArgumentParser)</span><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA"> and I see... well
a bunch of stuff I only apprehend the shadowy outlines of. Looking at the </span>
<span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">return</span><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA"> statements doesn't add light. (It doesn't help that I don't understand
how classes work. There's this thing called </span><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">super()</span><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA"> but it's not
defined anywhere. Shouldn't that cause an error? Oh it's from stdlib builtins.pyi. What the heck is a pyi?
<i>"...It is pitch black. You are likely to be eaten by a grue."</i>)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">» findstr "return" ..\auxiliary\gdal_argparse.py<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return super().parse_args(args=args, **kwargs)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return shlex.split(arg_line, comments=True)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return self._parser<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return kwargs<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return kwargs<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return 0<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return 1<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA"> return epilog or None<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA">So my question is: where is
</span><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">returncode: 2</span><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:EN-CA"> coming from?
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<div>
<p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;color:#1F497D;mso-fareast-language:EN-CA">-Matt</span><i><span style="font-size:10.0pt;color:#1F497D;mso-fareast-language:EN-CA"><o:p></o:p></span></i></p>
</div>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><span lang="EN-US" style="mso-fareast-language:EN-CA">From:</span></b><span lang="EN-US" style="mso-fareast-language:EN-CA"> Matt.Wilkie
<br>
<b>Sent:</b> April 26, 2022 1:03 PM<br>
<b>To:</b> 'gdal-dev@lists.osgeo.org' <gdal-dev@lists.osgeo.org><br>
<b>Subject:</b> RE: Standardize gdal-utils scripts return code for "no arguments"<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="color:#1F497D">Hi Folks,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">I've converted all the scripts that were using -1 to 1. However when I started looking at the ones returning 2 it became less clear what to do. Excepting
<i>gdal2tiles</i> all of them are using GDALArgumentParser and I don't see where the return value is being set. Thinking this might mean the mainline utils might be using 2 for no args I checked
<i>gdal_translate</i> and <i>gdalwarp</i>, but no, both of those use 1.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">The scripts that return 2 are:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal" style="margin-left:36.0pt"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">osgeo_utils\gdal2xyz.py<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:36.0pt"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">osgeo_utils\gdal_calc.py<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:36.0pt"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">osgeo_utils\gdal_fillnodata.py<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:36.0pt"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">osgeo_utils\gdal_polygonize.py<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:36.0pt"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">osgeo_utils\pct2rgb.py<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:36.0pt"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">osgeo_utils\rgb2pct.py<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:36.0pt"><span style="font-size:10.0pt;font-family:"Courier New";mso-fareast-language:EN-CA">osgeo_utils\samples\gdallocationinfo.py<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">I haven’t been able to figure out the GDALArgumentParser parser class so I embarked on making everything else use 2 instead of 1. I'm questioning the wisdom of that at the moment since so many files are touched.
However the process has forced me to look more closely at the many scripts and start to internalize the various patterns they use. This has been worthwhile even if the approach might get abandoned. The “make everything return 2” effort is in branch
<a href="https://github.com/maphew/gdal/tree/patch-5561-ret2">patch-5561-ret2</a>.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">The next message will have more details on how I’ve tried and failed to understand GDALArgumentParser.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<div>
<p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;color:#1F497D;mso-fareast-language:EN-CA">-Matt</span><i><span style="font-size:10.0pt;color:#1F497D;mso-fareast-language:EN-CA"><o:p></o:p></span></i></p>
</div>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><span lang="EN-US" style="mso-fareast-language:EN-CA">From:</span></b><span lang="EN-US" style="mso-fareast-language:EN-CA"> gdal-dev <<a href="mailto:gdal-dev-bounces@lists.osgeo.org">gdal-dev-bounces@lists.osgeo.org</a>>
<b>On Behalf Of </b><a href="mailto:Matt.Wilkie@yukon.ca">Matt.Wilkie@yukon.ca</a><br>
<b>Sent:</b> April 4, 2022 4:07 PM<br>
<b>To:</b> <a href="mailto:gdal-dev@lists.osgeo.org">gdal-dev@lists.osgeo.org</a><br>
<b>Subject:</b> [gdal-dev] Standardize gdal-utils scripts return code for "no arguments"<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal">Hi folks,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I’m working on “Standardize gdal-utils scripts return codes #5561” for all the scripts in swig/python/gdal-utils. Currently the scripts do not return the same status code for "was run without arguments".
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">It would be good for the same code meant the same thing across all the scripts in the package. Given that most of the scripts use `1` now, and that this is in line with sys,exit() docs I think it makes sense to make 1 the new standard.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">At present we have (return_code, num scripts with that code):<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">0: 30<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">1: 56<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">2: 8<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">-1: 9<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">-1 is a special case. In the script code it’s written as `return -1` but subprocess.run() captures it as `<span style="color:black;mso-fareast-language:EN-CA">4294967295`. Another special case is `gdal_auth.py` sample which with no arguments
spawns a web authentication page in browser.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:black;mso-fareast-language:EN-CA"><o:p> </o:p></span></p>
<p class="MsoNormal">Changing the return code will mean anyone who is relying on those in their own scripts or programs will need to adjust. This seems to be a small price for the gain in harmonization across the utilities, to me. Your thoughts?<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">[0]: <a href="https://can01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FOSGeo%2Fgdal%2Fissues%2F5561&data=04%7C01%7Cmatt.wilkie%40yukon.ca%7Cc3e8dba890e54a879a4808da168fdceb%7C98f515313973490abb70195aa264a2bc%7C0%7C0%7C637847105002756645%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=cJaW4TxL68DJMI8KTEjVjQCIzsN1Oa9ShUtILmy1%2B2g%3D&reserved=0">
https://github.com/OSGeo/gdal/issues/5561</a><o:p></o:p></p>
<p class="MsoNormal">[1]: <a href="https://can01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.python.org%2F3%2Flibrary%2Fsys.html%23sys.exit&data=04%7C01%7Cmatt.wilkie%40yukon.ca%7Cc3e8dba890e54a879a4808da168fdceb%7C98f515313973490abb70195aa264a2bc%7C0%7C0%7C637847105002756645%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=pHA7JH0IS7tjePzMXO1MzvO6svuPVHVR9uQgPqxOtMY%3D&reserved=0">
https://docs.python.org/3/library/sys.html#sys.exit</a>, “Unix programs generally use 2 for command line syntax errors and 1 for all other kind of errors”<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-top:4.0pt;line-height:115%;text-autospace:none;vertical-align:middle">
<b><span lang="EN-US" style="font-size:10.0pt;line-height:115%;mso-fareast-language:EN-CA">Matt Wilkie</span></b><span lang="EN-US" style="font-size:10.0pt;line-height:115%;mso-fareast-language:EN-CA"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-fareast-language:EN-CA">Geomatics Developer & Administrator<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-fareast-language:EN-CA">Environment
<span style="color:#2E74B5">|</span> Technology, Innovation and Mapping<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:10.0pt;mso-fareast-language:EN-CA">T 867-667-8133
<span style="color:#2E74B5">|</span> </span><u><span style="font-size:10.0pt;mso-fareast-language:EN-CA"><a href="https://can01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fyukon.ca%2F&data=04%7C01%7Cmatt.wilkie%40yukon.ca%7Cc3e8dba890e54a879a4808da168fdceb%7C98f515313973490abb70195aa264a2bc%7C0%7C0%7C637847105002756645%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=S08L%2BQsPMBZOc2%2Bb3wnWS8W08a0ejZpHRC1QAMfFEyk%3D&reserved=0"><span lang="EN-US" style="color:windowtext">Yukon.ca</span></a><o:p></o:p></span></u></p>
<p class="MsoNormal"><i><span style="font-size:10.0pt;mso-fareast-language:EN-CA">Hours: 08:30-16:30, Mon-Wed: Office, Thu: Remote, Fri: Away.<o:p></o:p></span></i></p>
</div>
</div>
</body>
</html>