<div dir="ltr"><br><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature"><div dir="ltr"><a href="http://www.keittlab.org/" target="_blank">http://www.keittlab.org/</a></div></div></div>
<br><div class="gmail_quote">On Tue, Sep 1, 2015 at 8:34 AM, Even Rouault <span dir="ltr"><<a href="mailto:even.rouault@spatialys.com" target="_blank">even.rouault@spatialys.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Folks,<br>
<br>
I'd wish we can find a solution that satisfy all parties. Here's another iteration for a possible proposition.<br>
<br>
* C API:<br>
<br>
Principles :<br>
- dataset objects can be passed<br>
- the option structure is opaque (should address Frank's concern about exposing too much internal stuff)<br>
- the option structure is parsed from an array of strings (with the current syntax of utilities)<br>
- a few setters can be added, for example, to set a progress function. Or possibly auxiliary objects,<br>
  like the cutline layer for gdalwarp.<br>
- not sure if we need the *pbUsageError flag. I removed it. If there's a conflict of options only found after<br>
  parsing time (eg due to characteristics of the datasets), then a CPLError() message should be enough.<br>
<br>
Example with GDALTranslate:<br>
<br>
char** papszArgv = CSLParseCommandLine(const char* pszCommandLine);<br>
GDALTranslateOptionsParse* psOptions = GDALTranslateOptionsNew(char** papszArgv);<br>
GDALTranslateOptionsSetProgress(options, pfnProgress, pProgressData);<br>
hOutDS = GDALTranslate(const char *pszDest, GDALDatasetH hSrcDataset, GDALTranslateOptions *psOptions)<br>
GDALTranslateOptionsDestroy(GDALTranslateOptionsParse* psOptions);<br>
CSLDestroy(papszArgV);<br>
<br>
<br>
* Python API<br>
<br>
Principles :<br>
- use the above C API from SWIG, but mostly for internal use of the upper levels explained below that<br>
  would be only Python code (no SWIG).<br>
- pubic API offers access to (hopefully nicely named) dedicated arguments and builds the string from them<br>
- public API offers access to the string representation as well<br>
- use Python dynamic typing to offer sugar candy, e.g pass a SRS either as an osr.SpatialReference()<br>
object or a string (the object being serialized to string, but this is a lossless operation)<br>
<br>
<br>
Examples:<br>
<br>
1) Use case with repeatable options<br>
options = gdal.TranslateOptions()<br>
options.bands = [ 1, 2, 3 ]<br>
options.format = 'MEM'<br>
options.progress = my_progress_method<br>
mem_ds = gdal.Translate('', src_ds, options = options)<br>
<br>
2)  Variant of 1). With some Python magic on **kwargs it can be automated to redirect on 1)<br>
mem_ds = gdal.Translate('', src_ds, bands = [1,2,3], format = 'MEM', progress = my_progress_method)<br>
<br>
3) String oriented.<br>
options = gdal.TranslateOptions('-b 1 -b 2 -b 3 -of MEM')<br>
mem_ds = gdal.Translate('', src_ds, options = options, progress = my_progress_method)<br>
<br>
4) Variant of 4)<br>
mem_ds = gdal.Translate('', src_ds, options = '-b 1 -b 2 -b 3 -of MEM', progress = my_progress_method)<br>
<br>
5) For the nostalgics, a wrapper of the above :<br>
gdal.Translate('in.tif out.tif -b 1 -b 2 -b 3 -of MEM', progress = my_progress_method')<br>
<br>
That's maybe too many different possibilities, although some build upon others, so not necessarily<br>
a lot of code involved (easier to say when it is not coded ahah!)<br>
<br>
* Other binding languages.<br>
<br>
Would probably only fallback on wrapping C API with SWIG in a first step.<br>
And find most appropriate solutions for each language.<br>
<br>
- Java for sure doesn't have a keyword approach for method arguments<br>
(well with what I remember from Java 1.6. might have changed). Builder approach<br>
would be a possibility (<a href="http://stackoverflow.com/questions/1988016/named-parameter-idiom-in-java" rel="noreferrer" target="_blank">http://stackoverflow.com/questions/1988016/named-parameter-idiom-in-java</a>)<br>
- C#: being a clone of Java, probably not.<br>
- Perl: apparently possible<br>
<br>
<br>
Opinions ?<br></blockquote><div><br></div><div>In an ideal world, I would prefer a nice clean algorithms library that is orthogonal to the command line and parsing. The utilities then simply consist of parsing and calling this library. I would also prefer the library to be broken down in to a set of orthogonal lower-level primitives and the higher-level algorithms built from these. But I cannot contribute significantly to that effort so I think its up to those than can to decide the course.</div><div><br></div><div>THK</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Even<br>
<br>
<br>
> Hi Frank,<br>
><br>
> I was one of the original people who argued against the "array of strings"<br>
> approach...<br>
><br>
> On 27 August 2015 at 02:26, Frank Warmerdam <<a href="mailto:warmerdam@pobox.com">warmerdam@pobox.com</a>> wrote:<br>
> > I clearly should have been commenting sooner.<br>
><br>
> Several months ago :p<br>
><br>
> > I am concerned that having messy structures of options for each<br>
> > program is going to complicate maintaining the actually commandline<br>
> > programs, and that it will still be a fragile and complicated point of<br>
> > entry as commandline arguments evolve over time.<br>
><br>
> The commandline tools eventually become string-parsing and wrapping of the<br>
> corresponding library tool - I'm not sure that makes it fragile &<br>
> complicated? Means that the library-ified apps are *at least as*<br>
> flexible/expressive/powerful<br>
> as the command-line tools.<br>
><br>
> > I'd prefer if the approach had just been to embed the main()'s in a<br>
> > library and to still pass the exact same vector of arguments (in the<br>
> > char **argv format) to these functions instead of shelling out a<br>
> > program.<br>
><br>
> That kinda defeats the whole point - a huge array of complex string-ified<br>
> arguments is what we're all doing at the moment, wrapped in an subprocess<br>
> call. Some options take multiple arguments in multiple strings, others take<br>
> multiple arguments in single strings, it's massively confusing. And we all<br>
> have big pipelines of chained gdalwarp/gdal_translate/etc code...<br>
><br>
> What we were striving for was to make it distinctly *better*:<br>
><br>
>    - progress/logging/error handling<br>
>    - options that accept geometries or SRS or in-memory datasets without<br>
>    having to re-serialize them and/or utilise tempfiles<br>
>    - easily applying the same operations over multiple datasets<br>
>    - configuration option defaults<br>
><br>
> > I would love to be able to replace many places where I shell out to<br>
> > run gdal command line programs with a library call with essentially<br>
> > the same arguments.<br>
><br>
> Sure, so it should be straightforward to do that *as well*, though besides<br>
> in-memory data (as you mention) you're getting very little benefit.<br>
><br>
> Rob :)<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Spatialys - Geospatial professional services<br>
<a href="http://www.spatialys.com" rel="noreferrer" target="_blank">http://www.spatialys.com</a><br>
_______________________________________________<br>
gdal-dev mailing list<br>
<a href="mailto:gdal-dev@lists.osgeo.org">gdal-dev@lists.osgeo.org</a><br>
<a href="http://lists.osgeo.org/mailman/listinfo/gdal-dev" rel="noreferrer" target="_blank">http://lists.osgeo.org/mailman/listinfo/gdal-dev</a><br>
</font></span></blockquote></div><br></div></div>