tagclient
The Python client for tag-server: the tagcore
Tag API from Python, taking and returning the protocol's protobuf messages.
from tagclient import TagClient, TagServerError, pb
with TagClient() as tag: # $TAG_SERVER, or tag-server's default socket
tag.attach() # the only base
print(tag.get_info().board_desc, tag.git_sha())
print(pb.tag.TagState.Name(tag.get_status().state))
for state in tag.state_log():
print(state)
try:
tag.start(pb.tagdata.Config())
except TagServerError as e:
print(e.code.name, e.message, e.ack_err_name, e.transport_failed)
Installing
From a checkout, in a virtual environment:
pip install -e host/python/tagclient[test]
It depends only on grpcio, grpcio-tools, protobuf and
googleapis-common-protos; no native build. The protocol modules are compiled
from the repository's proto/ when tagclient is first
imported, so nothing generated is committed and the client always matches the
checkout. For a copy installed outside the checkout, set TAGCLIENT_PROTO_DIR
to a proto/ directory.
Using it
TagClient(target=None, timeout=30.0)connects totarget, a gRPC address such asunix:///tmp/tag-server.sockor127.0.0.1:50061. With no target it uses$TAG_SERVER, or the server's default socket. As a context manager it detaches on exit if it attached.- Methods are the service's calls in snake_case:
attach,get_info,get_status,start,get_data_log,read_memory,calland the rest. They take and return messages frompb.tag,pb.tagdataandpb.service. Helpers:state_log()pages through the state log, andread_u32/write_u32access one little-endian word. TagServerErroris raised on any failure. It carriescode(agrpc.StatusCode),message,ack_err(the firmware'sAck.Err, orNone, withack_err_name), andtransport_failed. The codes are listed intag_service.proto.- The memory calls need the server started with
--enable-debug. - The client does not page data logs: how the index advances depends on the
tag's log format (see
tag-dwnld), soget_data_log(index)returns one raw page. tagclient.configshapegives whichConfigfields each tag type supports, read from the tags' default configs in the checkout, andmerge(), the same ruletag-start --mergeand qtmonitor's Restore use: copy only fields the tag supports and the file speaks for, zeros included. It is the Python counterpart of tagcore'sConfigShape; see Tag Configuration Model. SetTAGCLIENT_DEFAULT_CONFIG_DIRto anembedded/proto-cdirectory for a copy installed outside the checkout.
Examples
examples/ has Python versions of tag-info,
tag-start, tag-stop, tag-reset, tag-dwnld and tag-peek, and a live
status monitor.
Tests
TAG_SERVER_BIN=<build-dir>/Release/bin/tag-server pytest host/python/tagclient
tests/test_configshape.py needs neither a
server nor a tag, and runs without TAG_SERVER_BIN. It holds
tagclient.configshape to the same cases and the same frozen reference table
as tagcore's config_shape_check.
Each server test starts its own tag-server on a temporary socket.
tests/test_server.py needs no tag: it covers errors,
the debug switch, attaching to a missing base, TCP, shutdown and a second
server on a busy socket. tests/test_hardware.py
runs only with TAG_SERVER_HARDWARE=1 and one base connected. It reads
information, status, the state log and memory, and holds an idle session on
keepalives. It never starts, stops, erases or writes.