AttributeError: 'str' object has no attribute 'copy'

Hello,

I try to execute my RF test using RequestsLibrary but it doesn’t work anymore (I have changed my computer so perhaps there is something which is missing because it worked fine before…)

Here is my code

${header}=  Create Dictionary    Content-Type=application/json;charset=utf-8    Accept=application/json;charset=utf-8
Create Session    mysession    ${base_url}  proxies=${proxy}    headers=${header}

${body}=    Get File    file.json 
${response}=    Post Request    mysession    myURI    data=${body} 

And I have this error that I can’t resolve => AttributeError: ‘str’ object has no attribute ‘copy’.

My configuration :

  • Python 3.8.5
  • RF 3.2.2
  • RequestsLibrary 0.7.1

Thanks for your help !

Hi John,

Which line is that error occurring on? remember Log is your friend, log the result of the variables (even if just temporarily) you set to confirm their content this will often give you a clue as to the cause of the problem.

Which version of RequestsLibrary did you have on you old computer? I would suggest you compare the changes between those versions as a first place to look.

FYI version 0.7.1 is quite a fair way back, RequestsLibrary is up to v0.9.1 however Post Request is deprecated, so now might be a good time to update your test cases to work with the newer library, so you can take advantage of all the bug fixes.

Most robot framework libraries wrap a python or java module or class which in turn may wrap an application on your system, so the issue may be because you are using an old version of RequestsLibrary that is no longer compatible with a newer underlying requests module. So check the python requests module version on both machines as well.

Hopefully this helps,

Dave.

Hi Dave,

Thanks for your answer.
On my old computer, the Requests library had the same version, that’s the reason why I don’t understand…
So, I have update my Requests Library, replace my former “Post Requests” by “Post on Session”.
I put the “Log” keyword like this (because it seems that it’s just after the “Get file” that the problem occurs) :

${body}=    Get File    file.json 
Log ${body}

But it’s the same. And I have checked on my project but I don’t found the famous “copy” attribute.
On the “Post on Session” documentation, I see => “If you want to pass a json body pass a dictionary as json parameter.”

Another thing : when I open my json file on Eclipse, I have the error message “Could not find node.js. This will resul in editors missings key features. please make sur node.js is installed and that your PATH environment variable constains the location to the node executable”.

Perhaps it’s the cause ?

Requests Library doesn’t use or care about node.js, so I don’t think that is related.

does the word “copy” exist in file.json? if so perhaps everything was working and it was the server not handling the request?

what did you get when you Log ${response}? Log ${body} will only tell you if the file loaded as expected, ${response} should contain the server response.

Oh something I just thought of, Post On Session may fail if you get something other that 200 OK, so you might need to use expected_status option if you are expecting the server to respond with something else.

You can still use the data option to send the json string as you are currently doing, so no need to change. in some earlier versions of requests library (not sure which versions) you could pass the dictionary to the data option but not any more.

If you want to use the json option you’ll need to convert the string to a dictionary like this:

${sbody}=    Get File    file.json 
Log ${sbody}
${dbody}    evaluate  json.loads(${sbody})    json
Log ${dbody}

But unless you need to change something I wouldn’t bother, it’s just an extra step.

Hi Dave,

The word “copy” doesn’t appear on my json file.
I’m waiting for a 200 code, so it’s OK :slight_smile:
The Log ${response} give me the same error.

However, I have checked on “session.py” of my request library and there is a place where the “copy” word is used. Here the piece of code:

        proxies = proxies if proxies is not None else {}
        headers = prepared_request.headers
        url = prepared_request.url
        scheme = urlparse(url).scheme
        new_proxies = proxies.copy()
        no_proxy = proxies.get('no_proxy')

I don’t know if it’ usefull…

Hmm i’ve never looked at that file before, just checked now and none of the “session.py” files I found had that, so I can’t say if that is normal or not.

Can you show the actual error you’re getting from Post On Session? maybe something else in the error will give me a clue.

Dave.

Might be similar to PATCH On Session throwing AttributeError: 'str' object has no attribute 'items' · Issue #314 · MarketSquare/robotframework-requests · GitHub

A space problem or string instead of dictionary.

Bye,
Luca

Hi Dave,

Here is the log (on TRACE mode) :

20210817 08:04:30.948 : INFO : Log level changed from INFO to TRACE.
20210817 08:04:30.948 : TRACE : Return: 'INFO'
20210817 08:04:30.949 : TRACE : Arguments: [ 'Content-Type=application/json;charset=utf-8' | 'Accept=application/json;charset=utf-8' | 'X-Ms-PartToken=xxxxxx' | 'X-Ms-Partenaire=yyyyyyy' ]
20210817 08:04:30.949 : TRACE : Return: {'Accept': 'application/json;charset=utf-8',
 'Content-Type': 'application/json;charset=utf-8',
 'X-Ms-PartToken': 'xxxxxxx',
 'X-Ms-Partenaire': 'yyyyyyy'}
20210817 08:04:30.950 : INFO : ${header} = {'Content-Type': 'application/json;charset=utf-8', 'Accept': 'application/json;charset=utf-8', 'X-Ms-PartToken': 'xxxxxx', 'X-Ms-Partenaire': 'yyyyyyy'}
20210817 08:04:30.950 : TRACE : Arguments: [ 'mysession' | 'My_URI' | proxies='cccccccccccccccccccccccccccccccccccc'' | headers={'Accept': 'application/json;charset=utf-8',
 'Content-Type': 'application/json;charset=utf-8',
 'X-Ms-PartToken': 'xxxxxx',
 'X-Ms-Partenaire': 'yyyyyyy'} ]
20210817 08:04:30.951 : INFO : Creating Session using : alias=mysession, url=My_URI, headers={'Content-Type': 'application/json;charset=utf-8', 'Accept': 'application/json;charset=utf-8', 'X-Ms-PartToken': 'xxxxxx', 'X-Ms-Partenaire': 'yyyyyyy'},                     cookies={}, auth=None, timeout=None, proxies=My_Proxy, verify=False,                     debug=0 
20210817 08:04:30.951 : DEBUG : Creating session: mysession
20210817 08:04:30.951 : TRACE : Return: <requests.sessions.Session object at 0x0000020252920D90>
20210817 08:04:30.951 : TRACE : Arguments: [ 'LOTS_ENTRANTS\\JSON\\JSON_VENTE\\Vente_AGRI.json' ]
20210817 08:04:30.952 : INFO : Getting file '<a href="file://C:\Users\jonathan.vidot\eclipse-workspace\INOTR\LOTS_ENTRANTS\JSON\JSON_VENTE\Vente_AGRI.json">C:\Users\jonathan.vidot\eclipse-workspace\INOTR\LOTS_ENTRANTS\JSON\JSON_VENTE\Vente_AGRI.json</a>'.
20210817 08:04:30.952 : TRACE : Return: 'My_JSON_file'
20210817 08:04:30.960 : FAIL : AttributeError: 'str' object has no attribute 'copy'
20210817 08:04:30.960 : DEBUG : Traceback (most recent call last):
  File "C:\Users\jonathan.vidot\AppData\Local\Programs\Python\Python38\Lib\site-packages\RequestsLibrary\utils.py", line 138, in decorator
    return func(*args, **kwargs)
  File "C:\Users\jonathan.vidot\AppData\Local\Programs\Python\Python38\Lib\site-packages\RequestsLibrary\RequestsOnSessionKeywords.py", line 60, in post_on_session
    response = self._common_request("post", session, url,
  File "C:\Users\jonathan.vidot\AppData\Local\Programs\Python\Python38\Lib\site-packages\RequestsLibrary\RequestsKeywords.py", line 37, in _common_request
    resp = method_function(
  File "C:\Users\jonathan.vidot\AppData\Local\Programs\Python\Python38\Lib\site-packages\requests\sessions.py", line 590, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "C:\Users\jonathan.vidot\AppData\Local\Programs\Python\Python38\Lib\site-packages\requests\sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\jonathan.vidot\AppData\Local\Programs\Python\Python38\Lib\site-packages\requests\sessions.py", line 636, in send
    kwargs.setdefault('proxies', self.rebuild_proxies(request, self.proxies))
  File "C:\Users\jonathan.vidot\AppData\Local\Programs\Python\Python38\Lib\site-packages\requests\sessions.py", line 289, in rebuild_proxies
    new_proxies = proxies.copy()

Hi Luca,

Unfortunatly I tried to do your solution but it doesn’t work.
The space are good and I put a header which is a dictionary…

The problem is on proxy parameter it should be a dictionary while seems you’re passing a string.

Hello,
Thanks for your answer.
I’m going to try it but how do you put it on dictionary ? I’m lost… what is the key corresponding to the proxy URL ? Is a key provided by my organisation or is there a general key for proxy ?

${proxy}=    Create Dictionary    ???=My_proxy_URL
${header}=    Create Dictionary    Content-Type=application/json;charset=utf-8    Accept=application/json;charset=utf-8    X-Ms-PartToken=xxxxx    X-Ms-Partenaire=yyyyyy
Create Session    mysession    ${base_url}    proxies=${proxy}    headers=${header}

Because, for example, on my POSTMAN, the proxy is a system configuration, so I haven’t the corresponding key in “Params” tab…

It’s an evolution of the last version of requestLibrary ? Because before I change my computer, all works fine…

In the official documentation you’ll find the dictionary format: Developer Interface — Requests 2.26.0 documentation

Hello,
If I well understand, the format should be like this ? :

${header}=    Create Dictionary    Content-Type=application/json;charset=utf-8    Accept=application/json;charset=utf-8    X-Ms-PartToken=xxxxxx   X-Ms-Partenaire=yyyyyy
${proxyDict}=    Create Dictionary    http=My_URL_PROXY:My_port_PROXY
Create Session    mysession    ${base_url}    headers=${header}    proxies=${proxyDict}

When i tri to put it on a dictionary format, it doesn’t work :frowning:
The error message says that he can’t connect to the proxy => (Caused by ProxyError(‘Cannot connect to proxy.’, FileNotFoundError(2, ‘No such file or directory’)))

As I am not a python developer, I would have this configuration in RF mode (with keyword)
Do you think it’s possible ?

When I work step by step :

${header}=    Create Dictionary    Content-Type=application/json;charset=utf-8    Accept=application/json;charset=utf-8    X-Ms-PartToken=xxxxxx   X-Ms-Partenaire=yyyyyy 
${proxyDict}=    Create Dictionary    http=[proxy_URL]:[port]
Log    ${proxyDict}    
Create Session    mysession    ${base_url}    headers=${header}    proxies=${proxyDict}
${body}=    Get File    JSON_file.json 

All work fine, the session is created and the file is getting.
But when I add the line where I want to post on session, the error message (cannot connect to proxy) is appeared.

${header}=    Create Dictionary    Content-Type=application/json;charset=utf-8    Accept=application/json;charset=utf-8    X-Ms-PartToken=xxxxxx   X-Ms-Partenaire=yyyyyy 
${proxyDict}=    Create Dictionary    http=[proxy_URL]:[port]
Log    ${proxyDict}    
Create Session    mysession    ${base_url}    headers=${header}    proxies=${proxyDict}
${body}=    Get File    JSON_file.json 
${response}=    Post On Session    mysession    My_URI   data=${body}

Error message : ProxyError: HTTPSConnectionPool(host='My_URI, port=My_port): Max retries exceeded with url: My_URI (Caused by ProxyError(‘Cannot connect to proxy.’, FileNotFoundError(2, ‘No such file or directory’)))

I don’t think that the proxy is out because I can reach an URL of my organisation which needed to have an activated proxy…

After many and many time of research, I have found the problem.
The proxy system was strangely configured (with a list of proxy URLs in HTTP and HTTPS).
I deleted this list and replaced by only one proxy URL.
I also replace “Get File” keyword by “Load JSON From File” to be sure that the file is in JSON format.

And it works.
Besides, I don’t know why…

I have done 2 tests :
One without proxy configured
Create Session mysession ${base_url} headers=${header} => It works

One with proxy configured
${proxyDict}= Create Dictionary http=My_proxy_URL:port https=My_proxy_URL:port

And my proxy system is configured with http://My_proxy_URL:port

Thanks at all for your time !