diff --git a/autotest/utilities/test_gdalalg_raster_astype.py b/autotest/utilities/test_gdalalg_raster_astype.py index 02fd0e45ad70..6a96a54b30a8 100755 --- a/autotest/utilities/test_gdalalg_raster_astype.py +++ b/autotest/utilities/test_gdalalg_raster_astype.py @@ -15,9 +15,7 @@ def get_astype_alg(): - reg = gdal.GetGlobalAlgorithmRegistry() - raster = reg.InstantiateAlg("raster") - return raster.InstantiateSubAlgorithm("astype") + return gdal.GetGlobalAlgorithmRegistry()["raster"]["astype"] def test_gdalalg_raster_astype(tmp_vsimem): @@ -25,13 +23,24 @@ def test_gdalalg_raster_astype(tmp_vsimem): out_filename = str(tmp_vsimem / "out.tif") alg = get_astype_alg() - assert alg.ParseRunAndFinalize( - [ - "--datatype=UInt16", - "../gcore/data/rgbsmall.tif", - out_filename, - ], - ) + alg["datatype"] = "UInt16" + alg["input"] = "../gcore/data/rgbsmall.tif" + alg["output"] = out_filename + assert alg.Run() and alg.Finalize() + + with gdal.OpenEx(out_filename) as ds: + assert ds.GetRasterBand(1).DataType == gdal.GDT_UInt16 + + +def test_gdalalg_raster_astype_as_gdt(tmp_vsimem): + + out_filename = str(tmp_vsimem / "out.tif") + + alg = get_astype_alg() + alg["datatype"] = gdal.GDT_UInt16 + alg["input"] = "../gcore/data/rgbsmall.tif" + alg["output"] = out_filename + assert alg.Run() and alg.Finalize() with gdal.OpenEx(out_filename) as ds: assert ds.GetRasterBand(1).DataType == gdal.GDT_UInt16 diff --git a/gcore/gdalalgorithm.cpp b/gcore/gdalalgorithm.cpp index 3f76fa15ea3c..528f8f83260f 100644 --- a/gcore/gdalalgorithm.cpp +++ b/gcore/gdalalgorithm.cpp @@ -2914,13 +2914,15 @@ GDALInConstructionAlgorithmArg & GDALAlgorithm::AddOutputDataTypeArg(std::string *pValue, const char *helpMessage) { - auto &arg = AddArg(GDAL_ARG_NAME_OUTPUT_DATA_TYPE, 0, - MsgOrDefault(helpMessage, _("Output data type")), pValue) - .AddAlias("ot") - .AddAlias("datatype") - .SetChoices("Byte", "Int8", "UInt16", "Int16", "UInt32", - "Int32", "UInt64", "Int64", "CInt16", "CInt32", - "Float32", "Float64", "CFloat32", "CFloat64"); + auto &arg = + AddArg(GDAL_ARG_NAME_OUTPUT_DATA_TYPE, 0, + MsgOrDefault(helpMessage, _("Output data type")), pValue) + .AddAlias("ot") + .AddAlias("datatype") + .AddMetadataItem("type", {"GDALDataType"}) + .SetChoices("Byte", "Int8", "UInt16", "Int16", "UInt32", "Int32", + "UInt64", "Int64", "CInt16", "CInt32", "Float16", + "Float32", "Float64", "CFloat32", "CFloat64"); return arg; } @@ -4911,6 +4913,28 @@ char **GDALAlgorithmArgGetChoices(GDALAlgorithmArgH hArg) return CPLStringList(hArg->ptr->GetChoices()).StealList(); } +/************************************************************************/ +/* GDALAlgorithmArgGetMetadataItem() */ +/************************************************************************/ + +/** Return the values of the metadata item of an argument. + * + * @param hArg Handle to an argument. Must NOT be null. + * @param pszItem Name of the item. Must NOT be null. + * @return a NULL terminated list of values, which must be destroyed with + * CSLDestroy() + + * @since 3.11 + */ +char **GDALAlgorithmArgGetMetadataItem(GDALAlgorithmArgH hArg, + const char *pszItem) +{ + VALIDATE_POINTER1(hArg, __func__, nullptr); + VALIDATE_POINTER1(pszItem, __func__, nullptr); + const auto pVecOfStrings = hArg->ptr->GetMetadataItem(pszItem); + return pVecOfStrings ? CPLStringList(*pVecOfStrings).StealList() : nullptr; +} + /************************************************************************/ /* GDALAlgorithmArgIsExplicitlySet() */ /************************************************************************/ diff --git a/gcore/gdalalgorithm.h b/gcore/gdalalgorithm.h index cfcefa154913..a6140280e0be 100644 --- a/gcore/gdalalgorithm.h +++ b/gcore/gdalalgorithm.h @@ -152,6 +152,8 @@ bool CPL_DLL GDALAlgorithmArgGetRepeatedArgAllowed(GDALAlgorithmArgH); char CPL_DLL **GDALAlgorithmArgGetChoices(GDALAlgorithmArgH); +char CPL_DLL **GDALAlgorithmArgGetMetadataItem(GDALAlgorithmArgH, const char *); + bool CPL_DLL GDALAlgorithmArgIsExplicitlySet(GDALAlgorithmArgH); bool CPL_DLL GDALAlgorithmArgHasDefaultValue(GDALAlgorithmArgH); diff --git a/swig/include/Algorithm.i b/swig/include/Algorithm.i index da869b0c130f..f29ff6d9a9c5 100644 --- a/swig/include/Algorithm.i +++ b/swig/include/Algorithm.i @@ -118,6 +118,12 @@ public: } %clear char **; +%apply (char **CSL) {char **}; + char **GetMetadataItem(const char* item) { + return GDALAlgorithmArgGetMetadataItem( self, item ); + } +%clear char **; + bool IsExplicitlySet() { return GDALAlgorithmArgIsExplicitlySet(self); } diff --git a/swig/include/python/gdal_python.i b/swig/include/python/gdal_python.i index 000611944b3f..d3eb797bc548 100644 --- a/swig/include/python/gdal_python.i +++ b/swig/include/python/gdal_python.i @@ -5557,7 +5557,12 @@ class VSIFile(BytesIO): if type == GAAT_BOOLEAN: return self.SetAsBoolean(value) if type == GAAT_STRING: - if isinstance(value, str) or isinstance(value, int) or isinstance(value, float): + if isinstance(value, int): + if "GDALDataType" in self.GetMetadataItem("type") and value >= GDT_Byte and value < GDT_TypeCount: + return self.SetAsString(GetDataTypeName(value)) + else: + return self.SetAsString(str(value)) + elif isinstance(value, str) or isinstance(value, float): return self.SetAsString(str(value)) else: raise "Unexpected value type %s for an argument of type String" % str(type(value))