dlite icon indicating copy to clipboard operation
dlite copied to clipboard

Support native Python types in the class dlite.Options

Open terence-coudert opened this issue 2 years ago • 1 comments

The class dlite.Options could be improved to support also value types: bool, int and float (and also string value containing a ";" or "&"). Don't need to write a complex parser. Below an example of use:

options = Options("mode=r;database=test;collection=testc")
options.update(directConnection=False, maxPoolSize=200)
storage = dlite.Storage("mongodb", "localhost", str(options))

The magic is in the following methods of the Options class:

  • the method __init__ accepts a json encoded dictionary
  • the method __str__ return json encoded dictionary if needed.

Below an implementation of the class:

class Options(dict):

    def __init__(self, options, defaults=None):
        dict.__init__(self)
        if isinstance(defaults, str):
            defaults = Options(defaults)
        if defaults:
            self.update(defaults)
        if isinstance(options, str):
            if options.startswith("{"):
                self.update(json.loads(options))
            else:
                # strip hash and everything following
                options = options.split("#")[0]
                if ";" in options:
                    tokens = options.split(";")
                elif "&" in options:
                    tokens = options.split("&")
                else:
                    tokens = [options]
                if tokens and tokens != [""]:
                    self.update([t.split("=", 1) for t in tokens])

    def __getattr__(self, name):
        if name in self:
            return self[name]
        else:
            raise KeyError(name)

    def __setattr__(self, name, value):
        self[name] = value

    def __str__(self):
        encode = False
        for value in self.values():
            if isinstance(value, (bool, int, float)):
                encode = True
                break
            elif isinstance(value, str):
                if ("&" in value) | (";" in value):
                    encode = True
                    break
        if encode:
            return json.dumps(self, separators=(",", ":"))
        else:
            return ";".join([f"{k}={v}" for k, v in self.items()])

terence-coudert avatar Jan 15 '24 20:01 terence-coudert

The proposed implementation is commited in branch 738-improve-mongodb-storage commit 32a984189d962672f647ac567bba9fec9c76af8e

terence-coudert avatar Jan 18 '24 14:01 terence-coudert

Closing, since this fix was merged into master Jan 25, 2024 in commit 2b5dec2048b.

jesper-friis avatar May 01 '24 14:05 jesper-friis