Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
urllib3 Problem?
#1
I have a script that uses the MailJet REST API which has just started failing. I don't understand what the problem is because the error message referencing urllib3 is not clear to me. I have that library installed. Can someone interpret this error for me?

Traceback (most recent call last):
File "/usr/local/sbin/mailjet.py", line 6, in <module>
from mailjet_rest import Client
File "/usr/lib/python2.7/site-packages/mailjet_rest/__init__.py", line 4, in <module>
from .client import Client
File "/usr/lib/python2.7/site-packages/mailjet_rest/client.py", line 11, in <module>
requests.packages.urllib3.disable_warnings()
AttributeError: 'module' object has no attribute 'packages'

If I try 'pip install urllib3' I get this:

Requirement already satisfied: urllib3 in /usr/lib/python2.7/site-packages (1.10.2)
Reply
#2
do you have a newly created file named requests.py?
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
No, that is part of the MailJet API. I don't have access to that source.
Reply
#4
it's using requests package - that is clear (it's a dependency). However (if I understand correctly) it worked and now - it doesn't. The error says module object has no attribute packages. That is why I think there is something that override the installed requests package which has packages module inside it, so requests.packages should work unless something overrides the package :-)
This is common newbie mistake - to override module from Standard Library or installed third-party package by naming their own script with the same name.
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#5
There is no requests.py on my system. I gather that the issue is NOT urllib3, right? It sounds like I need to go to Mailajet tech support.
Reply
#6
no, it's not urlib3 issue. However it's something on your system, not problem with the mailjet-api-client in my opinion
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#7
can you make a small test.
Create a file with following content
import requests
print(requests.__file__)
in the same folder where your current script is and run it the same way. what does it print?
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#8
Here is the output:

Python 2.7.5 (default, Aug 7 2019, 00:51:29)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> print(requests.__file__)
/usr/lib/python2.7/site-packages/requests/__init__.pyc
Reply
#9
I've been able to track down the source for the offending MailJet script. To me, it looks like the offending line can be commented out:

!/usr/bin/env python
# coding=utf-8

import json
import logging

import requests
from requests.compat import urljoin
from ._version import __version__

requests.packages.urllib3.disable_warnings()


class Config(object):
    API_URL = 'https://api.mailjet.com/'
    API_REF = 'http://dev.mailjet.com/email-api/v3/'
    version = 'v3'
    user_agent = 'mailjet-apiv3-python/' + __version__

    def __init__(self, version=None):
        if version is not None:
            self.version = version
    def __getitem__(self, key):
        url = self.API_URL[0:]
        # Append version to URL.
        # Forward slash is ignored if present in self.version.
        url = urljoin(url, self.version + '/')
        headers = {'Content-type': 'application/json', 'User-agent': self.user_agent}
        if key.lower() == 'contactslist_csvdata':
            url = urljoin(url, 'DATA/')
            headers['Content-type'] = 'text/plain'
        elif key.lower() == 'batchjob_csverror':
            url = urljoin(url, 'DATA/')
            headers['Content-type'] = 'text/csv'
        elif key.lower() != 'send':
            url = urljoin(url, 'REST/')
        url = url + key.split('_')[0].lower()
        return url, headers


class Endpoint(object):

    def __init__(self, url, headers, auth, action=None):
       self._url, self.headers, self._auth, self.action = url, headers, auth, action

    def __doc__(self):
        return self._doc

    def _get(self, filters=None, action_id=None, id=None, **kwargs):
        return api_call(self._auth, 'get', self._url, headers=self.headers, action=self.action, action_id=action_id, filters=filters, resource_id=id, **kwargs)

    def get_many(self, filters=None, action_id=None, **kwargs):
        return self._get(filters=filters, **kwargs)

    def get(self, id=None, filters=None, action_id=None, **kwargs):
        return self._get(id=id, filters=filters, **kwargs)

    def create(self, data=None, filters=None, id=None, action_id=None, **kwargs):
        if self.headers['Content-type'] == 'application/json':
            data = json.dumps(data)
        return api_call(self._auth, 'post', self._url, headers=self.headers, resource_id=id, data=data, action=self.action, action_id=action_id, filters=filters, **kwargs)
    def update(self, id, data, filters=None, action_id=None, **kwargs):
        if self.headers['Content-type'] == 'application/json':
            data = json.dumps(data)
        return api_call(self._auth, 'put', self._url, resource_id=id, headers=self.headers, data=data, action=self.action, action_id=action_id, filters=filters, **kwargs)

    def delete(self, id, **kwargs):
        return api_call(self._auth, 'delete', self._url, action=self.action, headers=self.headers, resource_id=id, **kwargs)


class Client(object):

    def __init__(self, auth=None, **kwargs):
        self.auth = auth
        version = kwargs.get('version', None)
        self.config = Config(version=version)

    def __getattr__(self, name):
        split = name.split('_')
        fname = split[0]
        action = None
        if (len(split) > 1):
            action = split[1]
            if action == 'csvdata':
                action = 'csvdata/text:plain'
            if action == 'csverror':
                action = 'csverror/text:csv'
        url, headers = self.config[name]
        return type(fname, (Endpoint,), {})(url=url, headers=headers, action=action, auth=self.auth)


def api_call(auth, method, url, headers, data=None, filters=None, resource_id=None,
             timeout=60, debug=False, action=None, action_id=None, **kwargs):
    url = build_url(url, method=method, action=action, resource_id=resource_id, action_id=action_id)
    req_method = getattr(requests, method)

    try:
        response = req_method(url, data=data, params=filters, headers=headers, auth=auth,
                              timeout=timeout, verify=True, stream=False)
        return response

    except requests.exceptions.Timeout:
        raise TimeoutError
    except requests.RequestException as e:
        raise ApiError(e)
    except Exception as e:
        raise


def build_headers(resource, action=None, extra_headers=None):
    headers = {'Content-type': 'application/json'}

    if resource.lower() == 'contactslist' and action.lower() == 'csvdata':
        headers = {'Content-type': 'text/plain'}
    elif resource.lower() == 'batchjob' and action.lower() == 'csverror':
        headers = {'Content-type': 'text/csv'}

    if extra_headers:
        headers.update(extra_headers)

    return headers


def build_url(url, method, action=None, resource_id=None, action_id=None):
    if resource_id:
        url += '/%s' % str(resource_id)
    if action:
        url += '/%s' % action
        if action_id:
            url += '/%d' % action_id

    return url


def parse_response(response, debug=False):
    data = response.json()

    if debug:
        logging.debug('REQUEST: %s' % response.request.url)
        logging.debug('REQUEST_HEADERS: %s' % response.request.headers)
        logging.debug('REQUEST_CONTENT: %s' % response.request.body)

        logging.debug('RESPONSE: %s' % response.content)
        logging.debug('RESP_HEADERS: %s' % response.headers)
        logging.debug('RESP_CODE: %s' % response.status_code)

    return data


class ApiError(Exception):
    pass


class AuthorizationError(ApiError):
    pass


class ActionDeniedError(ApiError):
    pass


class CriticalApiError(ApiError):
    pass


class ApiRateLimitError(ApiError):
    pass

class TimeoutError(ApiError):
    pass


class DoesNotExistError(ApiError):
    pass


class ValidationError(ApiError):
    pass
Although that does not answer the underlying question of why did this suddenly start happening and what changed, where?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  'urllib3' Module not found when import 'requests' spanz 5 10,197 Jan-06-2021, 05:57 PM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020