python-odata icon indicating copy to clipboard operation
python-odata copied to clipboard

Problems extracting odata

Open 4quen opened this issue 5 years ago • 10 comments

I really don't know if this is the right place to write my problem here. If not, pardon me!

I tried out the library but I ran into the following error: error

I'm quite sure I did everything right (and I also doublechecked the providing oDataService if the values were set right). Also username and password are right. This is my code:

`from odata import ODataService from requests.auth import HTTPBasicAuth import requests

url = 'http://source.com/cdsodata/' my_auth = HTTPBasicAuth('XXX', 'YYY') Service = ODataService(url, auth=my_auth) default = 'Geids' Order = Service.entities.get('Geids', default)

query = Service.query(Order) query = query.limit(100) for entity in query: print(entity.Geid)`

Maybe you can help me?

4quen avatar Aug 20 '18 13:08 4quen

Your issue lies in the following two lines, Service.entities is a list of odata.entity.Entity and you specified your default fallback value to be a str object.

default = 'Geids'
Order = Service.entities.get('Geids', default)

This is due to the fact the odata library wasn't able to read your XML response correctly (this was a recurring issue for me, I eventually ended up changing the XML namespaces under odata.metadata.MetaData.namespaces for it to work) or your server doesn't have any Geids entities, hope this helps


if 'Geids' not in Service.entities:
    print('No geids entity definition found.')
    exit()

Order = Service.entities['Geids']

Paradoxis avatar Aug 21 '18 08:08 Paradoxis

Hi, Thank you for your help. The server definitely has some entities here.

Where exactly did you change the XML namespace? In the "metadata.py" ?

But I noticed that when trying the following lines: for ent in Service.entities: print ('...') print (ent) he doesn't give me anything back. (He even doesn't jump into the loop). Whis would happen that I have problems with the connection right? Is there something how I can test the connection?

Best regards, André

4quen avatar Aug 21 '18 11:08 4quen

Some new comment from my side. I looked deeper in the original data and noticed that the odata service provides JSON files. The question now is: Does that have an influence and if yes, where do I have to change it?

Best regards, André

4quen avatar Aug 22 '18 09:08 4quen

It looks like you're trying to use entities that aren't defined. The library requires reflect_entities or it will not populate the entities list. Try something like this:

Service = ODataService(url, auth=my_auth, reflect_entities=True)

A second problem that I had is with the location of the metadata (XML). In your example, the library would look for it here:

http://source.com/cdsodata/$metadata/

If that doesn't return the metadata XML, the library won't be able to build the entities. In my case, I had to use pull request #26 by nicenemo. It includes a fix to the metadata url to not have the trailing slash.

To answer your question: the library expects that the OData service uses JSON except for the metadata XML file.

Tim

tpow avatar Sep 10 '18 02:09 tpow

Hi @tpow , sorry for the late answer, but I was on vacation.

I've added the reflect_entities but still no effect. The location of the metadata is the right one:

snap9

So that can't be the issue here.

Ok, but all entities are in json format, so that can't be neither the problem. Here are two examples of the entities (the first from https://source/cdsodata and the second from the Geids): snap8

snap10

4quen avatar Sep 26 '18 13:09 4quen

Your examples all have $metadata without a trailing slash. Does your OData site return the metadata if you add a slash after $metadata like /cdsodata/$metadata/? If not, you'll need pull request #26 by nicenemo.

Tim

tpow avatar Oct 03 '18 11:10 tpow

Hi, yes it is also returning values when I add the slash ( https://source/cdsodata/$metadata/). So I think #26 will not help here?

4quen avatar Oct 10 '18 07:10 4quen

Hi @4quen,

Perhaps enabling logging would give you some insight? Here's code similar to what I'm using to test things:

import logging                                                                   
import odata                                                                     
import requests                                                                  
username = "XXX"                                                                 
password = "YYY"                                                                 
url = "https://source.com/cdsodata/"                                             
with requests.Session() as s:                                                    
     s.auth = (username, password)                                               
     logging.basicConfig(level=logging.DEBUG)                                    
     log = logging.getLogger("odata")                                            
     Service = odata.ODataService(url, session=s, reflect_entities=True)         
     print(Service)                                                              
     print(len(Service.entities))                                                
                                                                                 
     for ent in Service.entities:                                                
         print(ent)   

If you're using basic auth, the above should work for you.

Also, in a web browser does both https://source.com/cdsodata/$metadata/ and https://source.com/cdsodata/$metadata give you the same results? (It should be providing XML)

Also, does the following give JSON results? https://source.com/cdsodata/Geids Based on your examples, it should.

Tim

tpow avatar Oct 12 '18 03:10 tpow

Hi, I activated the log and received the following lines:

INFO: odata.metadata:Loading metadata document: http://source.com/cdsodata/$metadata/ DEBUG: urllib3.connectionpool:Starting new HTTP connection (1): source.com:80 DEBUG: urllib3.connectionpool:http://source.com:80 "GET /cdsodata/$metadata/ HTTP/1.1" 403 1233 INFO: odata.metadata: Loaded 0 entity sets, total 0 types <ODataService at http://source.com/cdsodata/> 0

And yes all of your three examples showed the expected results.

4quen avatar Oct 12 '18 08:10 4quen

The 403 error indicates that the problem isn't with python-odata, but with your credentials, the access method, or the url. Perhaps you can't connect to that site using basic auth? If you need to authenticate before loading the $metadata url with a browser then you'll need to mimic that before python-odata will work. You might try connecting using the Requests module first and once you get that working I suspect python-odata will work fine.

In my previous example, I'd try replacing the Service = odata.ODataService line and everything following it with something like this:

     response = s.get(url + '$metadata/')                                        
     print(response)                                                             
     response.raise_for_status()                                                 
     print(response.text)    

You can then make changes to your authentication process until the response prints <Response [200]> and you see the xml from the metadata. For example, you should double check the credentials and url. If you're filling out a form in your browser before you can access the odata provider, you might need to post to the form URL (s.post) and then call the ODataService.

Good luck! Tim

tpow avatar Oct 12 '18 21:10 tpow