urllib3 Problem? - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: urllib3 Problem? (/thread-24545.html) |
urllib3 Problem? - gw1500se - Feb-18-2020 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) RE: urllib3 Problem? - buran - Feb-18-2020 do you have a newly created file named requests.py? RE: urllib3 Problem? - gw1500se - Feb-18-2020 No, that is part of the MailJet API. I don't have access to that source. RE: urllib3 Problem? - buran - Feb-18-2020 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. RE: urllib3 Problem? - gw1500se - Feb-18-2020 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. RE: urllib3 Problem? - buran - Feb-18-2020 no, it's not urlib3 issue. However it's something on your system, not problem with the mailjet-api-client in my opinion RE: urllib3 Problem? - buran - Feb-18-2020 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? RE: urllib3 Problem? - gw1500se - Feb-24-2020 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 RE: urllib3 Problem? - gw1500se - Mar-02-2020 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): passAlthough that does not answer the underlying question of why did this suddenly start happening and what changed, where? |