- Magic in place of Basic
- Some picture of globals (tree array)
A Pythonic wrapper around InterSystems IRIS globals providing an intuitive interface for working with hierarchical data.
- 1. IRIS Global Reference Python API
- 2. Introduction
- 3. Installation
- 4. Basic Usage
- 5. Support of remote connection
- 6. Core Methods
- 7. Dictionary & JSON Operations
- 8. Python Magic Methods
- 9. Array support
- 10. Transaction support
- 11. Benefits
- 12. Roadmap
- 13. Compare to other libraries
- 14. Testing
- 15. License
InterSystems IRIS is a powerful database platform that provides a unique hierarchical data structure called globals. Globals are a key-value store that can be used to store hierarchical data in a tree-like structure. This hierarchical data structure is very powerful but can be difficult to work with using traditional programming languages.
The IRIS Global Reference Python API is a Pythonic wrapper around InterSystems IRIS globals that provides an intuitive interface for working with hierarchical data. The API provides a set of core methods for working with globals, including data operations, node information, navigation, and iteration. The API also provides support for converting globals to dictionaries and JSON and back, making it easy to work with hierarchical data in Python.
Key differences with globals and dictionaries:
- Globals don't have a notion of arrays
- This project provides a serialization to store arrays in globals
- A global node can have both values and child nodes
- In a dictionary, a node can have either a value or child nodes, but not both
- To solve this, the API binds the root node to
Nonekey
- To solve this, the API binds the root node to
- In a dictionary, a node can have either a value or child nodes, but not both
- Globals are ordered
- Dictionaries are unordered
pip install iris-global-referenceto have direct access to an iris terminal, you can use the following command:
pip install iris-global-reference --target=<mgr_dir>/pythonHere's a comprehensive example showing various ways to interact with globals:
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
team.kill() # Clear any existing data
# Different ways to set values
team.set((), "Baseball") # Set root node
team["name"] = "Boston Red Sox" # Dictionary-style assignment
team.set(("players", "1"), "Babe Ruth") # Tuple subscript
team.set(["players", "2"], "Cy Young") # List subscript
team["players", "3"] = "Ted Williams" # Multiple subscripts
# Different ways to get values
print(team.get(())) # Get root value: "Baseball"
print(team["name"]) # Dictionary-style access
print(team.get(("players", "1"))) # Using get() method
print(team["players"]["2"]) # Nested dictionary-style
# Check if nodes exist
print(("players", "1") in team) # True
print("nonexistent" in team) # False
# Delete nodes
del team["players", "3"] # Delete using del
team.kill(("players", "2")) # Delete using kill()
# Iteration Examples
# 1. Iterate through all nodes and values
for key, value in team.items():
print(f"Node {key}: {value}") # Shows all nodes with values
# Output :
# Node (): Baseball
# Node ('name',): Boston Red Sox
# Node ('players', '1'): Babe Ruth
# 2. Iterate through direct children only
for key in team.keys(children_only=True):
print(f"Direct child: {key}") # Shows only root level nodes
# Output:
# Direct child: ()
# Direct child: ('name',)
# 3. Custom iteration with subscripts
for sub in team.subscripts(("players",), children_only=True):
print(f"Player: {team.get(sub)}") # Shows only players
# Output:
# Player: Babe Ruth
# Count direct children
print(len(team)) # Number of root level nodes
# Output:
# 3
# Display global structure
print(team.zw()) # Show ZWRITE format
# Output:
# ^demo="Baseball"
# ^demo("name")="Boston Red Sox"
# ^demo("players","1")="Babe Ruth"
# Display this global in a dictionary format
print(team.to_dict())
# Output:
# {
# None: 'Baseball',
# 'name': 'Boston Red Sox',
# 'players': {
# '1': 'Babe Ruth'
# }
# }You can use the GlobalReference class with embedded Python by omitting the connection,
or connect to a remote IRIS instance by passing the native iris connection returned by
iris.connect(...).
import iris
from iris_global import GlobalReference
# Embedded Python, running inside IRIS.
team = GlobalReference("^demo")
# Remote connection, running outside IRIS.
conn = iris.connect("localhost", 1972, "USER", "SuperUser", "SYS")
team = GlobalReference("^demo", connection=conn)
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
# Get values
print(team.get(())) # Baseball
print(team.get(("name",))) # Boston Red Sox
print(team.get(("players", "1"))) # Babe RuthSQLAlchemy engines and iris://... connection strings are no longer supported by
GlobalReference. Use iris.connect(host, port, namespace, username, password) for
remote access.
set(subscript, value): Set a value at the specified nodeget(subscript): Get the value at the specified nodekill(subscript): Delete a node and all its descendantsdelete(subscript): Same as kill() but more Pythonic
The set() method can be used to set values at any node in the global:
team.set((), "Baseball")can be used to set the root node, while:
team.set(("name",), "Boston Red Sox")sets a child node with subscript "name".
set can also be used with str or list subscript:
team.set("", "Baseball")
team.set("name", "Boston Red Sox")
team.set(["players", "1"], "Babe Ruth")You can also use dictionary type subscript:
team["name"] = "Boston Red Sox"
team["players", "1"] = "Babe Ruth"
team["players"]["1"] = "Babe Ruth"The get() method can be used to retrieve values at any node in the global:
team.get(()) # Returns "Baseball"
team.get(("name",)) # Returns "Boston Red Sox"
team.get(("players", "1")) # Returns "Babe Ruth"get can also be used with str or list subscript:
team.get("") # Returns "Baseball"
team.get("name") # Returns "Boston Red Sox"
team.get(["players", "1"]) # Returns "Babe Ruth"You can also use dictionary type subscript:
print(team["name"]) # Returns "Boston Red Sox"
print(team["players", "1"]) # Returns "Babe Ruth"
print(team["players"]["1"]) # Returns "Babe Ruth"The kill() method can be used to delete a node and all its descendants:
team.kill(("players",))kill can also be used with str or list subscript:
team.kill("players")
team.kill(["players"])You can also use dictionary type subscript:
del team["players"]Same as kill() but more Pythonic.
data(subscript): Get node status (0=undefined, 1=value only, 10=descendants only, 11=both)has_value(subscript): Check if node has a valuehas_descendants(subscript): Check if node has child nodes
The data() method can be used to get the status of a node:
from iris_global import GlobalReference
data = {
None: "root",
"a": {1: "value a"}
}
team = GlobalReference("^data").from_dict(data)
print(team.data(())) # 11 (node with descendants and value)
print(team.data(("a",))) # 10 (node with descendants only)
print(team.data(("a", 1))) # 1 (node with value only)
print(team.data(("b",))) # 0 (undefined node)Works with str or list subscript:
print(team.data("")) # 11
print(team.data("a")) # 10
print(team.data(["a", 1])) # 1
print(team.data("b")) # 0The has_value() method can be used to check if a node has a value:
from iris_global import GlobalReference
data = {
None: "root",
"a": {1: "value a"}
}
team = GlobalReference("^data").from_dict(data)
print(team.has_value(())) # True
print(team.has_value(("a",))) # False
print(team.has_value(("a", 1))) # True
print(team.has_value(("b",))) # FalseWorks with str or list subscript:
print(team.has_value("")) # True
print(team.has_value("a")) # False
print(team.has_value(["a", 1])) # True
print(team.has_value("b")) # FalseThe has_descendants() method can be used to check if a node has child nodes:
from iris_global import GlobalReference
data = {
None: "root",
"a": {1: "value a"}
}
team = GlobalReference("^data").from_dict(data)
print(team.has_descendants(())) # True
print(team.has_descendants(("a",))) # True
print(team.has_descendants(("a", 1))) # False
print(team.has_descendants(("b",))) # FalseWorks with str or list subscript:
print(team.has_descendants("")) # True
print(team.has_descendants("a")) # True
print(team.has_descendants(["a", 1])) # False
print(team.has_descendants("b")) # Falsenext(subscript, direction): Get next subscript at same level (direction=1) or previous (direction=-1)previous(subscript): Get previous subscript at the same levelquery(subscript, direction): Navigate through nodes like ObjectScript $QUERYorder(subscript, direction): Legacy through nodes like ObjectScript $ORDER
The next() method can be used to get the next subscript:
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
# Query nodes
print(team.next(())) # Returns ("name",)
print(team.next(("name",))) # Returns ("players",)
print(team.next(("players",))) # Returns ("players", "1")
print(team.next(("players", "1"))) # Returns ("players", "2")
print(team.next(("players", "2"))) # Returns Noneworks with str or list subscript:
print(team.next("")) # Returns ("name",)
print(team.next("name")) # Returns ("players",)
print(team.next("players")) # Returns ("players", "1")
print(team.next(["players", "1"])) # Returns ("players", "2")
print(team.next(["players", "2"])) # Returns NoneSame as next().
The query() method can be used to navigate through nodes like ObjectScript $QUERY:
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
# Query nodes
print(team.query(())) # Returns ("name",)
print(team.query(("name",))) # Returns ("players",)
print(team.query(("players",))) # Returns ("players", "1")
print(team.query(("players", "1"))) # Returns ("players", "2")
print(team.query(("players", "2"))) # Returns Noneworks with str or list subscript:
print(team.query("")) # Returns ("name",)
print(team.query("name")) # Returns ("players",)
print(team.query("players")) # Returns ("players", "1")
print(team.query(["players", "1"])) # Returns ("players", "2")
print(team.query(["players", "2"])) # Returns NoneLegacy method to navigate through nodes like ObjectScript $ORDER:
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
# Get next subscript
print(team.order(())) # Returns "name"
print(team.order(("name",))) # Returns "players"
print(team.order(("players",))) # Returns None
print(team.order(("players", ""))) # Returns "1"
print(team.order(("players", "1"))) # Returns "2"
print(team.order(("players", "2"))) # Returns Noneworks with str or list subscript:
print(team.order("")) # Returns "name"
print(team.order("name")) # Returns "players"
print(team.order("players")) # Returns None
print(team.order(["players", ""])) # Returns "1"
print(team.order(["players", "1"])) # Returns "2"
print(team.order(["players", "2"])) # Returns NoneNote: subscript value are always returned as string tuples
subscripts(subscript, direction, with_descendants, with_values, with_root, children_only): Get all subscripts at subscript levelkeys(subscript, direction, with_descendants, with_values, with_root, children_only): Get all subscripts at subscript levelvalues(subscript, direction, with_descendants, with_values, with_root, children_only): Get all values at subscript levelitems(subscript, direction, with_descendants, with_values, with_root, children_only): Get all subscripts and values at subscript level
The subscripts() method can be used to get all subscripts at a subscript level.
Signature:
subscripts(subscript, direction=1, with_descendants=False, with_values=False, with_root=False, children_only=False)subscript: Subscript to start fromdirection: Direction (1=forward, -1=backward)with_descendants: Include child nodes default: Falsewith_values: Only include nodes with values default: Falsewith_root: Include the start node default: Falsechildren_only: Only include direct children default: False
Note: subscripts aim to have the same behavior as ObjectScript $ORDER
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
team.set(("world_series", "1"), "1903")
team.set(("world_series", "2"), "1912")
# Get all subscripts
for subscript in team.subscripts():
print(subscript) # Returns ('name',), ('players',), ('world_series',)
# Get subscripts starting from "players"
for subscript in team.subscripts(("players",)):
print(subscript) # Returns ('world_series',)
# Get subscripts starting from "players" that are nested
for subscript in team.subscripts(("players","")):
print(subscript) # Returns ('players', '1'), ('players', '2')
# or
for subscript in team.subscripts(("players",), children_only=True):
print(subscript) # Returns ('players', '1'), ('players', '2')
# Get subscripts only with values
for subscript in team.subscripts(with_values=True):
print(subscript) # Returns ('name',)
# Get subscripts only with descendants
for subscript in team.subscripts(with_descendants=True):
print(subscript) # Returns ('name',), ('players',), ('players', '1'), ('players', '2'), ('world_series',), ('world_series', '1'), ('world_series', '2')
# Get subscripts with root node
for subscript in team.subscripts(with_root=True):
print(subscript) # Returns (), ('name',), ('players',), ('world_series',)
# Get subscripts only with descendants and values
for subscript in team.subscripts(with_descendants=True, with_values=True):
print(subscript) # Returns ('name',), ('players', '1'), ('players', '2'), ('world_series', '1'), ('world_series', '2')
# Get subscripts with root node and descendants and values
for subscript in team.subscripts(with_root=True, with_descendants=True, with_values=True):
print(subscript) # Returns (), ('name',), ('players', '1'), ('players', '2'), ('world_series', '1'), ('world_series', '2')The keys() method can be used to get all subscripts at a subscript level.
Signature:
keys(subscript, direction=1, with_descendants=True, with_values=True, with_root=True, children_only=False)subscript: Subscript to start fromdirection: Direction (1=forward, -1=backward)with_descendants: Include child nodes default: Truewith_values: Only include nodes with values default: Truewith_root: Include the start node default: Truechildren_only: Only include direct children default: False
Note: keys aim to have the same behavior as Python dictionary keys() It means return all subscripts with values by descending all branches including the root node Basically, same as subscripts(with_descendants=True, with_values=True, with_root=True) Aim to be close as possible to ObjectScript ZWRITE
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
team.set(("world_series", "1"), "1903")
team.set(("world_series", "2"), "1912")
# Get keys
for key in team.keys():
print(key) # Returns (), ('name',), ('players', '1'), ('players', '2'), ('world_series', '1'), ('world_series', '2')
# Get all keys
for key in team.keys(with_values=False): # Returns all subscripts even without values
print(key) # Returns ('name',), ('players',), ('players', '1'), ('players', '2'), ('world_series',), ('world_series', '1'), ('world_series', '2')
# Get keys starting from "players"
for key in team.keys(("players",)):
print(key) # Returns ('players', '1'), ('players', '2'), ('world_series', '1'), ('world_series', '2')
# Get keys starting from "players" that are nested
for key in team.keys(("players",), children_only=True):
print(key) # Returns ('players', '1'), ('players', '2')
# or
for key in team.keys(("players","")):
print(key) # Returns ('players', '1'), ('players', '2')The values() method can be used to get all values at a subscript level.
Signature:
values(subscript, direction=1, with_descendants=True, with_values=True, with_root=True, children_only=False)subscript: Subscript to start fromdirection: Direction (1=forward, -1=backward)with_descendants: Include child nodes default: Truewith_values: Only include nodes with values default: Truewith_root: Include the start node default: Truechildren_only: Only include direct children default: False
Note: values aim to have the same behavior as Python dictionary values() It means return all values by descending all branches including the root node
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
team.set(("world_series", "1"), "1903")
team.set(("world_series", "2"), "1912")
# Get values
for value in team.values():
print(value) # Returns "Baseball", "Boston Red Sox", "Babe Ruth", "Cy Young", "1903", "1912"The items() method can be used to get all subscripts and values at a subscript level.
Signature:
items(subscript, direction=1, with_descendants=True, with_values=True, with_root=True, children_only=False)subscript: Subscript to start fromdirection: Direction (1=forward, -1=backward)with_descendants: Include child nodes default: Truewith_values: Only include nodes with values default: Truewith_root: Include the start node default: Truechildren_only: Only include direct children default: False
Note: items aim to have the same behavior as Python dictionary items() It means return all subscripts and values by descending all branches including the root node
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
team.set(("world_series", "1"), "1903")
team.set(("world_series", "2"), "1912")
# Get items
for key, value in team.items():
print(key, value) # Returns (), "Baseball", ('name',), "Boston Red Sox", ('players', '1'), "Babe Ruth", ('players', '2'), "Cy Young", ('world_series', '1'), "1903", ('world_series', '2'), "1912"The zw() method can be used to display the global in ObjectScript ZWRITE format:
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
team.set(("world_series", "1"), "1903")
team.set(("world_series", "2"), "1912")
print(team.zw())
# ^demo=Baseball
# ^demo("name")="Boston Red Sox"
# ^demo("players","1")="Babe Ruth"
# ^demo("players","2")="Cy Young"
# ^demo("world_series","1")="1903"
# ^demo("world_series","2")="1912"Convert globals to dictionaries or JSON and back.
to_dict(subscript, with_descendants, with_values, with_root, children_only, merge_leafs): Export global to dictionaryfrom_dict(data): Import dictionary to globalto_json(subscript, with_descendants, with_values, with_root, children_only, merge_leafs): Export global to JSONfrom_json(json_str, root_name): Import JSON to global
The to_dict() method can be used to export a global to a dictionary.
Signature:
to_dict(subscript=None, with_descendants=True, with_values=True, with_root=True, children_only=False, merge_leafs=True)subscript: Subscript to start fromwith_descendants: Include child nodes default: Truewith_values: Only include nodes with values default: Truewith_root: Include the start node default: Truechildren_only: Only include direct children default: Falsemerge_leafs: Merge leaf nodes into a single value default: True
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
team.set(("world_series", "1"), "1903")
team.set(("world_series", "2"), "1912")
# Export to dictionary
data_dict = team.to_dict()
print(data_dict)
# returns:
# {
# None: "Baseball",
# "name": "Boston Red Sox",
# "players": {
# "1": "Babe Ruth",
# "2": "Cy Young"
# },
# "world_series": {
# "1": "1903",
# "2": "1912"
# }
# }
# Note: root node is bound to None key
# Note: leaf nodes are merged by default
# Export to dictionary unmeged
print(team.to_dict(merge_leafs=False))
# returns:
# {
# None: "Baseball",
# "name": {None: "Boston Red Sox"},
# "players": {
# "1": {None: "Babe Ruth"},
# "2": {None: "Cy Young"}
# },
# "world_series": {
# "1": {None: "1903"},
# "2": {None: "1912"}
# }
# }The from_dict() method can be used to import a dictionary to a global.
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Dictionary data
data_dict = {
None: "Baseball",
"name": "Boston Red Sox",
"players": {
"1": "Babe Ruth",
"2": "Cy Young"
},
"world_series": {
"1": "1903",
"2": "1912"
}
}
# Note: root node is bound to None key
# Import dictionary
team.from_dict(data_dict)
# Unmerged dictionary data can be imported as well
data_dict = {
None: "Baseball",
"name": {None: "Boston Red Sox"},
"players": {
"1": {None: "Babe Ruth"},
"2": {None: "Cy Young"}
},
"world_series": {
"1": {None: "1903"},
"2": {None: "1912"}
}
}
team_unmerged = GlobalReference("^unmerged")
team_unmerged.from_dict(data_dict)
# Check values
team_unmerged.to_dict() == team.to_dict() # TrueThe to_json() method can be used to export a global to JSON.
Signature:
to_json(subscript=None, with_descendants=True, with_values=True, with_root=True, children_only=False, merge_leafs=True, root_name="_")subscript: Subscript to start fromwith_descendants: Include child nodes default: Truewith_values: Only include nodes with values default: Truewith_root: Include the start node default: Truechildren_only: Only include direct children default: Falsemerge_leafs: Merge leaf nodes into a single value default: Trueroot_name: Rename the root node
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")
team.set(("world_series", "1"), "1903")
team.set(("world_series", "2"), "1912")
# Export to JSON
print(team.to_json())
# returns:
# {
# "name": "Boston Red Sox",
# "players": {
# "1": "Babe Ruth",
# "2": "Cy Young"
# },
# "world_series": {
# "1": "1903",
# "2": "1912"
# },
# "_": "Baseball"
# }
# Note: root node is bound to "_"
# Note: leaf nodes are merged by default
# Export to JSON unmeged
print(team.to_json(merge_leafs=False))
# returns:
# {
# "name": {"_": "Boston Red Sox"},
# "players": {
# "1": {"_": "Babe Ruth"},
# "2": {"_": "Cy Young"}
# },
# "world_series": {
# "1": {"_": "1903"},
# "2": {"_": "1912"}
# },
# "_": "Baseball"
# }
# Root node can be renamed
print(team.to_json(root_name="__root__"))
# returns:
# {
# "name": "Boston Red Sox",
# "players": {
# "1": "Babe Ruth",
# "2": "Cy Young"
# },
# "world_series": {
# "1": "1903",
# "2": "1912"
# },
# "__root__": "Baseball"
# }The from_json() method can be used to import JSON to a global.
import json
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# JSON data
json_str = """
{
"name": "Boston Red Sox",
"players": {
"1": "Babe Ruth",
"2": "Cy Young"
},
"world_series": {
"1": "1903",
"2": "1912"
},
"_": "Baseball"
}
"""
# Import JSON
team.from_json(json_str)
# Check values
print(json.loads(json_str) == json.loads(team.to_json())) # True
# Root node can be renamed
json_str = """
{
"name": "Boston Red Sox",
"players": {
"1": "Babe Ruth",
"2": "Cy Young"
},
"world_series": {
"1": "1903",
"2": "1912"
},
"__root__": "Baseball"
}
"""
team.from_json(json_str, root_name="__root__")
# Check values
print(json.loads(json_str) == json.loads(team.to_json(root_name="__root__"))) # TrueGlobalReference implements Python magic methods for a more Pythonic experience:
# Dictionary-like access
team["name"] = "Boston Red Sox"
print(team["name"])
del team["players", "3"]
# Check if node exists
if ("players", "1") in team:
print("Player exists!")
# Get number of direct child nodes
num_nodes = len(team)
# Iterate directly
for key,value in team:
print(key, value)Values returned with [] are Key objects. For string, integer, float, and bytes values,
the returned key is also a subclass of the matching Python primitive:
name = team["name"]
isinstance(name, str) # TrueBracket access on a Key is always global child access, not native primitive indexing.
Use .value, str(key), or bytes(key) when you need primitive indexing:
team["name"][0] # Looks up subscript ("name", 0)
team["name"].value[0] # Returns first character from the string valueBoolean values are returned as plain Key wrappers because Python does not allow
subclassing bool.
Note: Array support is experimental
To support array from dict/json, i used a serialization to store the array in a global. The serialization is the following:
- the root node contains an serialization string eg:
__array__ - the children nodes contains the array values
- the children nodes are named with the serialization string and the index of the array
example:
from iris_global import GlobalReference
GlobalReference("demo").kill()
gref = GlobalReference("demo")
my_dict = {"a": 1, "b": 2, "array": [1, 2, 3], "array_of_dicts": [{"a": 1}, {"b": 2}]}
gref.from_dict(my_dict)
print(gref.to_dict()) # {'a': 1, 'array': [1, 2, 3], 'array_of_dicts': [{'a': 1}, {'b': 2}], 'b': 2}
print(gref.zw())
# ^demo("a")=1
# ^demo("array")="__array__"
# ^demo("array","__array__0")=1
# ^demo("array","__array__1")=2
# ^demo("array","__array__2")=3
# ^demo("array_of_dicts")="__array__"
# ^demo("array_of_dicts","__array__0","a")=1
# ^demo("array_of_dicts","__array__1","b")=2
# ^demo("b")=2
# can still present global as dict without serialization
print(gref.to_dict(merge_array=False))
# returns:
# {
# 'a': 1,
# 'array': {None: '__array__', '__array__0': 1, '__array__1': 2, '__array__2': 3},
# 'array_of_dicts': {None: '__array__', '__array__0': {'a': 1}, '__array__1': {'b': 2}},
# 'b': 2
# }
# the serialization string can be changed
gref.kill()
gref.from_dict(my_dict, array_prefix="__list__")
print(gref.zw())
# ^demo("a")=1
# ^demo("array")="__list__"
# ^demo("array","__list__0")=1
# ^demo("array","__list__1")=2
# ^demo("array","__list__2")=3
# ^demo("array_of_dicts")="__list__"
# ^demo("array_of_dicts","__list__0","a")=1
# ^demo("array_of_dicts","__list__1","b")=2
# ^demo("b")=2Transactions can be supported by using the with statement:
from iris_global import GlobalReference
# Create a reference to a global with a transaction
with GlobalReference("^demo") as team:
team.set((), "Baseball")
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")or
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
# Start transaction
with team:
team.set(("name",), "Boston Red Sox")
team.set(("players", "1"), "Babe Ruth")
team.set(("players", "2"), "Cy Young")Otherwize, you can use the begin(), commit() and rollback() methods:
from iris_global import GlobalReference
# Create a reference to a global
team = GlobalReference("^demo")
# Set values
team.set((), "Baseball")
# Start transaction
team.begin()
team.set(("name",), "Boston Red Sox")
# Commit transaction
team.commit()- Pythonic: Provides a Pythonic interface for working with globals
- Intuitive: Simplifies working with hierarchical data
- Efficient: Reduces the need for complex ObjectScript code
- Flexible: Supports a wide range of data operations
ObjectScript has a merge operation that can be used to merge two globals. This operation is not supported by the API. However, you can achieve the same result by exporting the globals to dictionaries, merging the dictionaries, and then importing the merged dictionary back to a global.
from iris_global import GlobalReference
# Create a reference to a global
team1 = GlobalReference("^team1")
team11 = GlobalReference("^team11")
team2 = GlobalReference("^team2")
# Set values
team1.set((), "Baseball")
team1.set(("name",), "Boston Red Sox")
team1.set(("players", "1"), "Babe Ruth")
team11.set((), "Baseball")
team11.set(("name",), "Boston Red Sox")
team11.set(("players", "1"), "Babe Ruth")
team2.set((), "Baseball")
team2.set(("name",), "New York Yankees")
team2.set(("players", "2"), "Lou Gehrig")
# Export to dictionaries
data1 = team1.to_dict()
data2 = team2.to_dict()
# Merge dictionaries
data1.update(data2)
# Import merged dictionary
team1.from_dict(data1)
prin(team1.zw())
# ^team1=Baseball
# ^team1("name")=New York Yankees
# ^team1("players","1")=Babe Ruth
# ^team1("players","2")=Lou Gehrig
# or
team11.from_dict(team2)
prin(team11.zw())
# ^team11=Baseball
# ^team11("name")=New York Yankees
# ^team11("players","1")=Babe Ruth
# ^team11("players","2")=Lou GehrigThe benefit of this approach is that it allows you to use Python's built-in dictionary operations to manipulate globals, making it easier to work with hierarchical data structures. For the more, no need to build a complex python code to merge two globals.
- Add support for global arrays
- Add support for byte set/get
- Add support for listbuild, vector, pva, bit
- Add support of mutli-dimensional variables
This table compares the api of the iris_global library with other libraries, only low-level operations are compared:
| Feature | iris_global | irisnative | embedded-python | comments |
|---|---|---|---|---|
| initialize | global_reference = GlobalReference("^demo", connection=conn) |
conn = iris.connect(...); global_reference = iris.createIRIS(conn) |
global_reference = iris.gref("^demo") |
omit connection for embedded Python |
| set value | global_reference.set(("name",1), "Boston Red Sox") |
global_reference.set("Boston Red Sox", "demo", "name", 1) |
global_reference.set(["name",1], "Boston Red Sox") |
for irisnative, the value is the first argument |
| get value | global_reference.get(("name",1)) |
global_reference.get("demo", "name", 1) |
global_reference.get(["name",1]) |
|
| check if node exists | global_reference.data(("name",1)) |
global_reference.isDefined("demo", "name", 1) |
global_reference.data(["name",1]) |
|
| delete node | global_reference.kill(("name",1)) |
global_reference.kill("demo", "name", 1) |
global_reference.kill(["name",1]) |
|
| order | global_reference.order(("name",1)) |
global_reference.nextSubscript(False, "demo", "name", 1) |
global_reference.order(["name",1]) |
for irisnative, the reverse flag is the first argument |
General remarks:
- iris_global support for get/set can be used with str, list or tuple subscript
- irisnative use the value as the first argument
- embedded-python use list subscript
- irisnative use nextSubscript instead of order
- irisnative use isDefined instead of data
Run the test suite:
python -m pytestMIT License - see LICENSE for details.