Skip to content

Python SWIG bindings and problems updating hashTableObj #5582

@geographika

Description

@geographika

As noted in the discussions at #5572 - in the Python SWIG bindings, the C hashTableObj is converted to a Python dictionary - (see pymodule.i).
This allows for easy access to values using keys, for example at test_mapio.py

headers = mapscript.msIO_getAndStripStdoutBufferMimeHeaders()
ct = headers['Content-Type']
cc = headers['Cache-Control']

It is now much easier to read any METADATA values, for example in a LAYER:

l = mapscript.fromstring("LAYER TYPE POINT METADATA KEY1 VAL1 END END")
print(l.metadata) # {'KEY1': 'VAL1'}

However setting values is now harder. This dictionary is "disconnected" from its associated object - any edits to it won't be set on the original hashTableObj.
The following attempts to set a METADATA value will fail:

l = mapscript.fromstring("LAYER TYPE POINT METADATA KEY1 VAL1 END END")
l.metadata["KEY2"] = "VAL2" #  this can be set but will have no effect on the layerObj's metadata
l.metadata = {"k1": "v1", "k2": "v2"} # AttributeError: can't set attribute

The "new" get/set API as described at http://mapserver.org/mapscript/mapfile.html#metadata won't work, as these objects are now Python dicts:

l.metadata.get('KEY1') # AttributeError: 'dict' object has no attribute 'set'
l.metadata.set("KEY1", "VAL2") # AttributeError: 'dict' object has no attribute 'set'

The old deprecated methods however still work (http://mapserver.org/mapscript/mapfile.html#backwards-compatibility-for-metadata)

print(l.setMetaData ("KEY3", "VAL3"))
print(l.getMetaData ("KEY3")) # VAL3

There appear to be 3 solutions:

  1. Update the docs to describe the above and leave the code as-is.
  2. Roll back the typemap conversion of hashTableObj to dict, and revert to the get/set API.
  3. Update pymodule.i to allow dicts to be passed into Mapscript and converted to hashTableObj using %typemap(in). This could be similar to the GDAL bindings - see typemaps_python.i however porting this code is complicated by several GDAL helper functions, and allowing
    character sequences as well as dicts so my initial attempts have failed. Input from anyone with SWIG expertise welcomed.

There may also be memory issues relating to setting a hashTableObj - see #1803 (although it looks like @szekerest may have fixed this).

Option 1 is the easiest. Option 3 may give the nicest API as I believe it could allow an API such as:

md = hashTableObj()
md["key1"] = ["val1"]
l.metadata = md

And possibly direct access to the hashTableObj (although I'm unsure on this one):

l.metadata["key1"] = "val1"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions