Working with attributes¶
This is a collection of recipes for working with attributes.
Reading attributes¶
One way of reading attributes is while iterating the results of a query:
with db.transaction() as tr:
with tr.query_data(...) as cursor:
for rec in cursor:
# Print the variable code and value
print(f"{rec['var']}:", rec["variable"])
# This returns a Dict[str, wreport.Var]
attrs = rec.query_attrs()
# Print all the attributes
for name, value in attrs.items():
print(f" {name}:", value)
Note that, since they are not always needed, attributes are not retrieved by
default in queries, and running query_attrs
will make a new query to
retrieve them, potentially adding a database query for each resulting variable.
If you know you are going to also need the attributes, you can add
query=attrs
to the query, and attributes will be read together with
variable data, resulting in a more efficient query:
with db.transaction() as tr:
with tr.query_data({"query": "attrs"}) as cursor:
for rec in cursor:
# Print the variable code and value
print(f"{rec['var']}:", rec["variable"])
# This returns a Dict[str, wreport.Var]
# and since query=attrs was used, it won't make an extra
database query:
attrs = rec.query_attrs()
# Print all the attributes
for name, value in attrs.items():
print(f" {name}:", value)
If you are not processing attributes together as you iterate data, you can use
the context_id
output parameter (see Parameters used when reading query results for data values) to store
references to variables, that you can use to access their attributes at any
later time:
interesting_vars = []
with db.transaction() as tr:
with tr.query_data(...) as cursor:
for rec in cursor:
if ...:
interesting_vars.append(rec["context_id")
for context_id in interesting_vars:
attrs = tr.attr_query_data(contex_id)
if attrs["B33196"].enqi() == 1:
...
Although querying attributes separately is often not needed, this possibility becomes useful when modifying attributes. See below.
Updating attributes¶
You can insert or remove attributes while iterating the results of a query:
with db.transaction() as tr:
with tr.query_data({"var": "B12101"}) as cursor:
for rec in cursor:
# Check that the temperature is within a given range
if rec.enqd() < 150 or req.enqd() > 310:
# If it's not, add/update "Data has been invalidated"...
rec.insert_attrs({"B33196": 1})
# ...and remove "Percent confidence"
rec.remove_attrs(["B33007"])
If you are not processing attributes together as you iterate data, you can use
the context_id
output parameter (see Parameters used when reading query results for data values) to store
references to variables, that you can use to work on their attributes at a
later time.
For example, this identifies sequences of consecutive data whose values never change, and invalidates all of them except the last one (see issue227):
invalid_list = []
prev = None
with db.transaction() as tr:
for row in tr.query_data(....):
value = row["variable"].get()
if prev == value:
invalid_list.append(row["context_id"])
prev = value
for ctxid in invalid_list:
tr.attr_insert_data(ctxid, {"B33196": 1})
tr.attr_remove_data(ctxid, ["B33007"])