I am working with a large number of message types with similar but not identical structure. All the stuff that's common among these is in another message. When a message comes in, I parse it using the common message type. However, I can't seem to find a way to access the fields outside of this type (i.e. the non-common fields). Is there a way to access the unknown field set in python?
Edit:
I just saw this in the documentation:
"If a message has unknown fields, the current Java and C++ implementations write them in arbitrary order after the sequentially-ordered known fields. The current Python implementation does not track unknown fields."
Does this mean that if I parse using the common type, eg:
proto = msg_pb2.Common()
proto.ParseFromString(raw_msg)
Any fields not defined in message Common are thrown away?
To someone looking for an answer to this, the reflection module helped me:
https://developers.google.com/protocol-buffers/docs/reference/python/google.protobuf.reflection-module
The relevant sample code:
Sample usage:
file_descriptor = descriptor_pb2.FileDescriptorProto()
file_descriptor.ParseFromString(proto2_string)
msg_descriptor = descriptor.MakeDescriptor(file_descriptor.message_type[0])
msg_class = reflection.MakeClass(msg_descriptor)
msg = msg_class()
Args:
descriptor: A descriptor.Descriptor object describing the protobuf.
Returns:
The Message class object described by the descriptor.
Related
I want to subscribe to vehicles in my simulation. However, I find it very difficult to understand which variables I can use for this, as the documentation does not include this information.
traci.vehicle.subscribe(veh_id, [
tc.VAR_SPEED,
tc.VAR_ACCELERATION,
tc.VAR_EMERGENCY_DECEL,
# tc.VAR_ROUTE,
tc.VAR_POSITION,
# tc.VAR_FOLLOWER,
tc.VAR_NEXT_TLS
])
The issue is, that tc.VAR_ROUTE causes this error in the terminal:
traci.exceptions.TraCIException: Could not add subscription. Get Vehicle Variable: unsupported variable 0x57 specified
and tc.VAR_FOLLOWER causes this error in SUMO:
Error: Storage::readChar(): invalid position
Quitting (on error).
Why is that? Also I do not quite understand how to learn more about the different constants. For example, which ones can I use to subscribe to vehicles?
When I look into the file under traci/constants.py, there are different types of variables.
starting with CMD_ (the comments call these "command")
starting with RESPONSE_ (the comments call these "response")
starting with VAR_ (the comments say these are "Variable types (for CMD_GET_*_VARIABLE)")
stop flags, departure flags, and many more
Also, the comments sometimes say something like: (get: ...; set: ...)
e.g. here:
# position (2D) (get: vehicle, poi, inductionloop, lane area detector; set: poi)
VAR_POSITION = 0x42
What does that mean, I know that I can get the subscription results from subscribing to these constants, but how could I possibly set them?
My main question is if someone can please explain how these constants are structured and which ones I can use for subscribing to vehicles.
You are right this is not well documented. I added a ticket: https://github.com/eclipse/sumo/issues/8579
The answer to your direct question is that everything which is listed in the value retrieval section of the docs (which should be equivalent to having a "get" in the constants file comment) should be "subscribable".
VAR_ROUTE is not, because it is only used to set a route using the edge list but there is no equivalent getter. You can only subscribe to the route ID for instance. VAR_FOLLOWER in turn needs a parameter when subscribing, so you need to give that as an additional argument. How to do that unfortunately depends on your SUMO version.
For SUMO 1.9 and later the call looks like this:
traci.vehicle.subscribe(vehID, (tc.VAR_FOLLOWER,), begin, end, {tc.VAR_FOLLOWER: ("d", dist)})
I'm using doxygen in combination with doxypypy to document Python source code.
class Test:
"""
This is a test class.
The thest class only serves the purpose of a MWE.
Attributes:
memberA (int): This is member A.
memberB (int): This is member B.
memberC (int): This is member C. A and B never invite C to their party.
"""
def __init__(self):
self.memberA = []
self.memberB = []
self.memberC = []
I now want to group members A and B in a member group (by using #{ and #} etc.) but several attempts of implementing this in the docstring were futile. What is the correct syntax of achieving this? (I'm quite new to Python in general, I'm coming from the C++ side... I'm using Google commenting style)
EDIT: Also, I failed to find out so far what formats I can use now. I know I can use doxygen special commands, but does doxypypy know how to read e.g. Google Style Doc?
EDIT2: I also discovered, that doxygen/doxypypy ignore the type hints... does anyone know how to include them?
EDIT3: Member groups can be used by using
###{
#items in group
###}
I find myself stuck on this problem, and repeated Googling, checking SO, and reading numerous docs has not helped me get the right answer, so I hope this isn't a bad question.
One entity I want to create is an event taking place during a convention. I'm giving it the property start_time = ndb.TimeProperty(). I also have a property date = messages.DateProperty(), and I'd like to keep the two discrete (in other words, not using DateTimeProperty).
When a user enters information to create an event, I want to specify defaults for any fields they do not enter at creation and I'd like to set the default time as midnight, but I can't seem to format it correctly so the service accepts it (constant 503 Service Unavailable response when I try it using the API explorer).
Right now I've set things up like this (some unnecessary details removed):
event_defaults = {...
...
"start_time": 0000,
...
}
and then I try looping over my default values to enter them into a dictionary which I'll use to .put() the info on the server.
data = {field.name: getattr(request, field.name) for field in request.all_fields()
for default in event_defaults:
if data[default] in (None, []):
data[default] = event_defaults[default]
setattr(request, default, event_defaults[default])
In the logs, I see the error Encountered unexpected error from ProtoRPC method implementation: BadValueError (Expected time, got 0). I have also tried using the time and datetime modules, but I must be using them incorrectly, because I still receive errors.
I suppose I could work around this problem by using ndb.StringProperty() instead, and just deal with strings, but then I'd feel like I would be missing out on a chance to learn more about how GAE and NDB work (all of this is for a project on udacity.com, so learning is certainly the point).
So, how can I structure my default time properly for midnight? Sorry for the wall of text.
Link to code on github. The conference.py file contains the code I'm having the trouble with, and models.py contains my definitions for the entities I'm working with.
Update: I'm a dummy. I had my model class using a TimeProperty() and the corresponding message class using a StringField(), but I was never making the proper conversion between expected types. That's why I could never seem to give it the right thing, but it expected two different things at different points in the code. Issue resolved.
TimeProperty expects a datetime.time value
import datetime
event_defaults = {...
...
"start_time": datetime.time(),
...
}
More in the docs: https://cloud.google.com/appengine/docs/python/ndb/entity-property-reference#Date_and_Time
Use the datetime() library to convert it into a valid ndb time property value
if data['time']:
data['time'] = datetime.strptime(data['time'][:10], "%H:%M").time()
else:
data['time'] = datetime.datetime.now().time()
ps: Don't forget to change data['time'] with your field name
Please read this whole question before answering, as it's not what you think... I'm looking at creating python object wrappers that represent hardware devices on a system (trimmed example below).
class TPM(object):
#property
def attr1(self):
"""
Protects value from being accidentally modified after
constructor is called.
"""
return self._attr1
def __init__(self, attr1, ...):
self._attr1 = attr1
...
#classmethod
def scan(cls):
"""Calls Popen, parses to dict, and passes **dict to constructor"""
Most of the constructor inputs involve running command line outputs in subprocess.Popen and then parsing the output to fill in object attributes. I've come up with a few ways to handle these, but I'm unsatisfied with what I've put together just far and am trying to find a better solution. Here are the common catches that I've found. (Quick note: tool versions are tightly controlled, so parsed outputs don't change unexpectedly.)
Many tools produce variant outputs, sometimes including fields and sometimes not. This means that if you assemble a dict to be wrapped in a container object, the constructor is more or less forced to take **kwargs and not really have defined fields. I don't like this because it makes static analysis via pylint, etc less than useful. I'd prefer a defined interface so that sphinx documentation is clearer and errors can be more reliably detected.
In lieu of **kwargs, I've also tried setting default args to None for many of the fields, with what ends up as pretty ugly results. One thing I dislike strongly about this option is that optional fields don't always come at the end of the command line tool output. This makes it a little mind-bending to look at the constructor and match it up to tool output.
I'd greatly prefer to avoid constructing a dictionary in the first place, but using setattr to create attributes will make pylint unable to detect the _attr1, etc... and create warnings. Any ideas here are welcome...
Basically, I am looking for the proper Pythonic way to do this. My requirements, for a re-summary are the following:
Command line tool output parsed into a container object.
Container object protects attributes via properties post-construction.
Varying number of inputs to constructor, with working static analysis and error detection for missing required fields during runtime.
Is there a good way of doing this (hopefully without a ton of boilerplate code) in Python? If so, what is it?
EDIT:
Per some of the clarification requests, we can take a look at the tpm_version command. Here's the output for my laptop, but for this TPM it doesn't include every possible attribute. Sometimes, the command will return extra attributes that I also want to capture. This makes parsing to known attribute names on a container object fairly difficult.
TPM 1.2 Version Info:
Chip Version: 1.2.4.40
Spec Level: 2
Errata Revision: 3
TPM Vendor ID: IFX
Vendor Specific data: 04280077 0074706d 3631ffff ff
TPM Version: 01010000
Manufacturer Info: 49465800
Example code (ignore lack of sanity checks, please. trimmed for brevity):
def __init__(self, chip_version, spec_level, errata_revision,
tpm_vendor_id, vendor_specific_data, tpm_version,
manufacturer_info):
self._chip_version = chip_version
...
#classmethod
def scan(cls):
tpm_proc = Popen("/usr/sbin/tpm_version")
stdout, stderr = Popen.communicate()
tpm_dict = dict()
for line in tpm_proc.stdout.splitlines():
if "Version Info:" in line:
pass
else:
split_line = line.split(":")
attribute_name = (
split_line[0].strip().replace(' ', '_').lower())
tpm_dict[attribute_name] = split_line[1].strip()
return cls(**tpm_dict)
The problem here is that this (or a different one that I may not be able to review the source of to get every possible field) could add extra things that cause my parser to work, but my object to not capture the fields. That's what I'm really trying to solve in an elegant way.
I've been working on a more solid answer to this the last few months, as I basically work on hardware support libraries and have finally come up with a satisfactory (though pretty verbose) answer.
Parse the tool outputs, whatever they look like, into objects structures that match up to how the tool views the device. These can have very generic dict structures, but should be broken out as much as possible.
Create another container class on top of that that which uses attributes to access items in the tool-container-objects. This enforces an API and can return sane errors across multiple versions of the tool, and across differing tool outputs!
I'm trying to access the "last-sample" property from GstXvImageSink which is derived from GstBaseSink.
I'm getting:
TypeError: object of type 'GstXvImageSink' does not have property 'last-sample'
Is there a special way to get properties from base classes in pygtk or is this property somehow hidden?
Code:
def take_snapshoot(self):
sample = self.__snapshot_source_video_sink.get_property("last-sample")
My fault. I'm using gstreamer 0.1 and I was reading documentation for gstreamer 1.0
Everything that was reffering to GstBuffer is now GstSample.
After http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-porting-1.0.html
GST_TAG_IMAGE, GST_TAG_PREVIEW_IMAGE, GST_TAG_ATTACHMENT: many tags that used to be of type GstBuffer are now of type GstSample (which is basically a struct containing a buffer alongside caps and some other info).
So in my case the answer is to use:
def take_snapshoot(self):
sample = self.__snapshot_source_video_sink.get_property("last-buffer")