Accessing salesforce metadata using python simple-salesforce - python

When reading the simple-salesforce docs, it only shows accessing object metadata using hard-coded methods like such:
sf.Contact.metadata()
Is there no way to do something like this?
sf["Contact"].metadata()
I want to loop through a list of objects and retrieve all these objects fields, but it seems like this isn't possible due to the limitation seen above.
for obj in objects:
fields = [x["name"] for x in sf[obj].describe()["fields"]]
# processing for each object
Is there any way to access object metadata using a string parameter, instead of a hard-coded value?

The sf. interface is actually call to the the get_attr method in the Salesforce class.
get_attr returns the value of SFType(name, self.session_id, self.sf_instance, self.sf_version, self.proxies).
You could do what you would like with the following:
from simple_salesforce import SFType
....
sf_object = ['Case', 'Contact', 'Account', 'Custom1__c', 'Custom2__c']
for each in sf_object:
SFType(each, sf.session_id, sf.sf_instance, sf.sf_version, sf.proxies).metadata()
Hope that helps.

Related

Parse JSON MSG in Python

I am trying to parse a json MSG into a python dict.
For reference, the message is received from the Things Network with the python MQTT handler.
Here is the format I am receiving when I print the object
msg = MSG(variable_group=MSG(data0=0, data1=0, data2=0), variable2='name', variable3='num')
In its default state, I can access individual fields by msg.variable2 for example which provides 'name' but does not provide the variable name itself.
This is fine for a scenario in which I hardcode everything into my system, but I would like it to be a bit more adaptable and create new entries for variables as they come in.
Is there any way to parse this in such a way that I get both the data and the variable name?
Thanks!
EDIT:
From the input above, I would like to get a python dict containing the variable name and data.
dict =
{
variable_group : MSG(data0=0, data1=0, data2=0),
variable2 : 'name',
variable3 : 'num'
}
Currently, I can access the data via a for loop and can print the variable names if I print the entire structure, but cannot access the variable names through a looping mechanism
EDIT 2:
After doing some digging on the wrapper found the following:
def _json_object_hook(d):
return namedtuple("MSG", d.keys())(*d.values())
def json2obj(data):
return json.loads(data, object_hook=_json_object_hook)
Where the input shown above is created by passing it as 'data' to json2obj.
I am still unsure how to get a dict out of this format, haven't used object_hooks before.
From discussion in the comments below, it appears that the MSG object is a namedtuple created on the fly out of the json object.
In a case like that you can get the fields by looking at the _fields of the object. You can dict-ify a namedtuple like this
def nt_to_dict(nt):
return {field, getattr(nt, field) for field in nt._fields}
or you could just inspect the object by trolling _fields in code and using getattr as needed

Retrieve and Rank Python: What kind of "Answer Data" to pass to rank method?

I'm accessing the Retreive-And-Rank service using Python. So far I've uploaded my configuration and documents and have trained my ranker on the relevance file. All that is left, I presume, is to pass some query results (from Solr?) into the "rank" method of my R-A-R object.
My question: What exactly are those results, and what form do they come in? And how do I access them?
Right now I am accessing the PySolr object using the get_pysolr_client() method, then searching a query and using the returned results:
answer_data = pysolr.search(query)
rrv1.rank(<my_ranker_id>, answer_data, top_answers=10)
I'm doing this because it's analogous to what IBM does in the rank() method in the Java example. But I'm getting the error message:
AttributeError: 'Results' object has no attribute 'read'
I'm getting this because PySolr returns a "Results" object.
What should I be passing instead to the rank() method to get it to work?
The Retrieve_and_Rank specification for the rank method is as follows, and I think that answer_data is supposed to be a "file-like" object:
def rank(self, ranker_id, answer_data, top_answers=10)
One workaround is to call pysolr's _send_request method:
results = pysolr._send_request("GET", path="/fcselect?q=%s&ranker_id=%s&wt=json" %
(query_string, ranker_id))
for doc in json.loads(results)["response"]["docs"]:
print doc
Thanks to rishavc on dW Answers for this.

Why can't I call __dict__ on object in list that happens to be within another object within a list within a dictionary?

Here's my setup: dictD contains a key users paired with value = list of UserObjects. Each UserObject has an attribute username plus two arrays, threads and comments.
I was able to convert dictD's array of user objects into a dictionary style with this call:
dictD["users"] = [user.__dict__ for user in dictD["users"]]
If I dump out dictD, here's the relevant part before I try to do my manipulation:
{
'users':[
{
'username': Redditor(user_name='$$$$$$$$$$'),
'threads':[
<__main__.redditThread instance at 0x7f05db28b320>
],
'comments':[
<__main__.comment instance at 0x7f05db278e60>
]
},
{
'username': Redditor(user_name='##########e\ gone'),
'threads':[
<__main__.redditThread instance at 0x7f05db2a4a70>
],
'comments':[
<__main__.comment instance at 0x7f05db298e18>
]
}
As you can see the comments contain comment objects and the threads list contains thread objects. So I'd like to do the same call for them that I did for the users array. But when I try to do this:
for user in dictD["users"]:
user.threads = [thread.__dict__ for thread in user.threads]
user.comments = [comment.__dict__ for comment in user.comments]
I run into this error:
AttributeError: 'dict' object has no attribute 'threads'
I also tried
users = dictD["users"]
for user in users...
but this triggers the same error message. How can I turn objects in lists into dictionary form when those objects' lists are themselves held within objects within lists within a dictionary?
Incidentally, I am doing all this so I can insert these objects into MongoDB, so if there is an easier way to serialize a complex object, please let me into the secret. Thank you.
Promoting my comment to an answer since it seems reasonable and nobody else is posting: it looks at a glance like you're confusing Python for Javascript: a dict with a key 'threads' is not an object you can reference with .threads, only with ["threads"]. ie. user.threads should be user["threads"]. A dict usually only has the same standard attributes (see: https://docs.python.org/2/library/stdtypes.html#typesmapping or https://docs.python.org/3/library/stdtypes.html#mapping-types-dict for Python 3.) The problem isn't that you're trying to call __dict__ on an object, it's that you're trying to get an attribute from an object that doesn't exist, later in that same line of code.
If you want to recreate complex objects from MongoDB rather than just nested dicts and lists then that is basically a process of deserialization; you can either handle that manually, or maybe use some sort of object mapping library to do it for you (eg. something like Mongoobject might work, though I've not tested it myself)

How to get dictionary object in Mongoengine Python?

On querying pymongo i get a dictionary object that can be sent directly as a response to the api request. Where as mongoengine returns a Document object on querying database. So I have to parse every object before it can be sent as the response in the api.
this is how I have to query in mongoengine.
users = User.objects(location = 'US')
This will return me a BaseQueryList object which contains User model type object. Instead I need that it should return me a list of dictionary type objects of Users.
In BaseQueryList there is one method called as_pymongo, we can use this to get rows as list of dict like where we get pymongo. The following is an example
users = User.objects(location = 'US').as_pymongo()
OR
In BaseQueryList there are in list of User class objects.
In User class object there is one method called _data, this will returns data as dict
So you can try like following
users = [user._data for user in users._iter_results()]
It could be help you.
Mongoengine has to_mongo() method that gives you Python dict.
users = User.objects(location = 'US')
users.to_mongo()

django session check for existance

I am trying to check if the session does have anything in it. What I did is:
if request.session:
# do something
but it is not working. Is there any way of knowing whether the session contains something at that moment?
If I do request.session['some_name'], it works, but in some cases, I just need to know if the session is empty or not.
Asking with some specific names is not always a wanted thing.
Eg. if there is no session, it returns an error, since some_name doesn't exist.
request.session is an instance of SessionBase object which behaves like dictionary but it it is not a dictionary. This object has a "private" field ( actually it's a property ) called _session which is a dictionary which holds all data.
The reason for that is that Django does not load session until you call request.session[key]. It is lazily instantiated.
So you can try doing that:
if request.session._session:
# do something
or you can do it by looking at keys like this:
if request.session.keys():
# do something
Note how .keys() works:
django/contrib/sessions/backends/base.py
class SessionBase(object):
# some code
def keys(self):
return self._session.keys()
# some code
I always recommend reading the source code directly.
Nowadays there's a convenience method on the session object
request.session.is_empty()

Categories