Getting all field names from a protocol buffer? - python

I want to get all the field names of a proto into a list. Is there a way to do this? I looked in the documentation and there doesn't seem to be anything for this.

Every proto class possess a DESCRIPTOR class variable that can be used to inspect the fields of corresponding protobuf messages.
Have a look at the documentation of the Descriptor and FieldDescriptor classes for more details.
Here is a simple example to get the FieldDescriptors of all the fields in message into a list:
res = message.DESCRIPTOR.fields
To get the names of the fields "exactly as they appear in the .proto file":
res = [field.name for field in message.DESCRIPTOR.fields]
or (from the comments):
res = message.DESCRIPTOR.fields_by_name.keys()
To get the full names of the fields "including containing scope":
res = [field.full_name for field in message.DESCRIPTOR.fields]

qfiard's answer didn't work for me. Calling message.DESCRIPTOR.fields.keys() produced AttributeError: 'list' object has no attribute 'keys'.
Not sure why it wouldn't work. Maybe it has something to do with how the message was defined/compiled.
The workaround was to do a list composition of the individual field objects and get the name property for each. This gave me a list of strings of all fields in this list.
res = [f.name for f in message.DESCRIPTOR.fields]
Note that this does not get you the field names within those fields recursively.

You can easily get a list of fields as follows
message_fields = [field for field in message.DESCRIPTOR.fields_by_name]

I bumped to Python 3.9 and some of these solutions broke, so I found a solution using the public interface of a message object, not using the DESCRIPTOR attribute.
fields = [desc.name for desc, val in message.ListFields()]
Note however, this solution will only fetch the fields which have been set.
Doc is here: https://googleapis.dev/python/protobuf/latest/google/protobuf/message.html#google.protobuf.message.Message.ListFields

Related

Convert Django Queryset to list or dict

From my views.py I doing this query:
var_query = DB.objects.filter(Q(user_id=str(request.user.id)) & Q(router_name='router1' )).values('router_type', 'router_ip')
Working because I get this result:
{'router1': set(['[{"router_type": "CISCO", "router_ip": "192.168.1.1"}]'])}
the type of var_query is: <class 'django.db.models.query.QuerySet'>
When I convert this with list()
converted = list(var_query)
and this error:
AttributeError: 'set' object has no attribute 'iteritems'
becasue when a convert this queryset to list is inserted this: set(['
How to convert to real list or dict so I can work with my key or value?
It's not really clear what your final aim is. But it seems like you are overcomplicating things unnecessarily. I would suggest simplifying your approach and just filter the queryset normally (note, it looks like these Q objects are also unnecessary here, you can just pass the args in directly).
var_query = DB.objects.filter(
Q(user_id=str(request.user.id)) & Q(router_name='router1')
)
The result will be a queryset object that implements the iterator protocol and can be iterated over normally like a list or list-like object. Then to work with the fields in the data that you seem to be interested in, you can just do something like:
var_query = DB.objects.filter(
Q(user_id=str(request.user.id)) & Q(router_name='router1')
)
for obj in var_query:
router_type = obj.router_type
router_ip = obj.router_ip
# ... do other stuff with your data.
You don't need to bother using values unless you really have a proper use case for it.
If you can supply more context we can refine a more accurate solution.

Get Salesforce Object List

I'm trying to pull a list of all the Salesforce Objects (tables names) from Salesforce. In the examples I see of people getting the Object data, the name of the Object is already known. I want to see the entire list of Objects prior to that. Is this possible? I am using simple_salesforce.
Thank you!!!
Nevermind, I found it
for x in sf.describe()["sobjects"]:
print(x["name"])
You can use Schema.getGlobalDescribe().Values() to get descriptions of each object, which are of type Schema.SObjectType. Then you can call the .getDescribe() method to get the object description, then call the .getName() method on the object description to get the object name:
for(Schema.SObjectType objectType : Schema.getGlobalDescribe().Values()){
String name = objectType.getDescribe().getName();
System.debug('Object name is==>' +name);
}

How to get filter key and result tuple in Django

Assume there is a list contains all keys to search called taglist. To filter all Post contains tag in taglist, I use the following command.
Post.objects.filter(tags__tag__in=taglist).order_by('-id')
and in class Post
tags = models.ManyToManyField('PostMention')
in PostMenthion
class PostMention(models.Model):
tag = models.CharField(unique=True,max_length=200)
and I will get a Query list about the result.
Can I get a list of tuple like(each_result,tag_that_used_to_found_the_result)?
Yes, we can .annotate(..) each row with the related Tag:
from django.db.models import F
Post.objects.filter(
tags__tag__in=taglist
).annotate(
the_tag=F('tags__tag')
).order_by('-id')
Here the Post objects will have an extra attribute .the_tag, that contains the string of the tag that matched. In case multiple tags matched, multiple Post objects will be in the queryset, each with their .the_tag attribute.
We can post-process this to a 2-tuple, but I think an attribute is a better choice, since then it is clear what this field contains.

simple-salesforce not recognizing custom object

I am using simple_salesforce and get all records of a custom object called "SER__Condition__c". I know for a fact that that is the name because I got a list of table names from our administrator.
"api" is an instance of "simple_salesforce.Salesforce".
This is the command I'm executing:
pprint(api.query('SELECT Id FROM SER__Condition__c'))
Which returns this error:
File "path\to\lib\simple_salesforce\api.py", line 698, in _exception_handler
raise exc_cls(result.url, result.status_code, name, response_content)
simple_salesforce.api.SalesforceMalformedRequest: Malformed request https://xxx.salesforce.com/services/data/v29.0/query/?q=SELECT+Id+FROM+SER__Condition__c. Response content: [{'message': "\nSELECT Id FROM SER__Condition__c\n
^\nERROR at Row:1:Column:16\nsObject type 'SER__Condition__c' is not supported. If you are attempting to use a custom object, be sure to append the '__c' after the entity name. Please reference your WSDL or the describe call for the appropriate names.", 'errorCode': 'INVALID_TYPE'}]
Using the exact same command for a default object returns all the records as expected:
pprint(api.query('SELECT Id FROM Account'))
The same also holds true for these two:
api.Account.get('xxxxxxxxxxxxxxxxxx')
api.SER__Condition__c.get('xxxxxxxxxxxxxxxx')
It probably is a permissions issue. Make sure the SER__Condition__c object is visible to the user you are running the query as.
I am 90% sure the issue is with the name of the object. Per Salesforce, the naming convention for a custom object cannot include two consecutive underscores. From the Salesforce error message on object creation: "Error: The Object Name field can only contain underscores and alphanumeric characters. It must be unique, begin with a letter, not include spaces, not end with an underscore, and not contain two consecutive underscores."
If you change "SER__Condition__c" to "SER_Condition__c" (a single underscore between "SER" and "Contition") it should fix the issue.
Yes, I resolved this issue by editing the user profile's custom object permissions. It looks like it defaults to none.

filter() method in python django

out_links = Link.objects.filter(iweb=iweb_id).order_by('-pub_date')
for link in out_links:
comments = LinkComment.objects.filter(link=link.id)
Filter method creates the list of object, so out_links is a list, right ?
Next, after for loop, I filtering again to find objects in LinkComments class by link id.
The question arises though, shoud I refer to link as it would be the object or rather a list?
I'm not shure about it as long it is django views? link.id or link['id']? My python says [ ], but django does not work.
The out_links is a queryset and in the for loop you can reach all LinkComments by:
for link in out_links:
comments = link.linkcomment_set.all()
Filter creates a QuerySet, as explained in the documentation: https://docs.djangoproject.com/en/dev/ref/models/querysets/#methods-that-return-new-querysets
If you subscript a QuerySet, like comments[n], you get the nth member (just as you would with a list). Where you have an order_by, that is in the order specified by that clause. You cannot query by id using the subscript notation.
When you iterate over the QuerySet, you get the members of the queryset, which are python model objects, and you may treat them just as you do anywhere else in your code.
Filter method creates the list of object, so out_links is a list,
right ?
Wrong. It creates QuerySet object, which also happens to be an iterable.

Categories

Resources