diff --git a/README.md b/README.md index a988b94..a941f0a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ pyLast ====== -[![Build status](https://travis-ci.org/pylast/pylast.svg?branch=develop)](https://travis-ci.org/pylast/pylast) -[![PyPI version](https://img.shields.io/pypi/v/pylast.svg)](https://pypi.python.org/pypi/pylast/) +[![Build status](https://travis-ci.org/pylast/pylast.svg?branch=develop)](https://travis-ci.org/pylast/pylast) +[![PyPI version](https://img.shields.io/pypi/v/pylast.svg)](https://pypi.python.org/pypi/pylast/) [![Coverage (Codecov)](https://codecov.io/gh/pylast/pylast/branch/develop/graph/badge.svg)](https://codecov.io/gh/pylast/pylast) [![Coverage (Coveralls)](https://coveralls.io/repos/github/pylast/pylast/badge.svg?branch=develop)](https://coveralls.io/github/pylast/pylast?branch=develop) @@ -20,6 +20,7 @@ Install via pip: pip install pylast +pyLast >= 2.0.0 supports Python 2.7.9+ and 3.4+. Features -------- diff --git a/pylast/__init__.py b/pylast/__init__.py index 79fdcfb..1b1337a 100644 --- a/pylast/__init__.py +++ b/pylast/__init__.py @@ -10,7 +10,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -22,15 +22,16 @@ import hashlib from xml.dom import minidom, Node -import xml.dom -import time -import shelve -import tempfile -import sys import collections -import warnings import re +import shelve import six +import ssl +import sys +import tempfile +import time +import warnings +import xml.dom __version__ = '1.9.0' __author__ = 'Amr Hassan, hugovk' @@ -43,35 +44,17 @@ def _deprecation_warning(message): warnings.warn(message, DeprecationWarning) -def _can_use_ssl_securely(): - # Python 3.3 doesn't support create_default_context() but can be made to - # work sanely. - # <2.7.9 and <3.2 never did any SSL verification so don't do SSL there. - # >3.4 and >2.7.9 has sane defaults so use SSL there. - v = sys.version_info - return v > (3, 3) or ((2, 7, 9) < v < (3, 0)) - - -if _can_use_ssl_securely(): - import ssl - if sys.version_info[0] == 3: - if _can_use_ssl_securely(): - from http.client import HTTPSConnection - else: - from http.client import HTTPConnection import html.entities as htmlentitydefs + from http.client import HTTPSConnection from urllib.parse import splithost as url_split_host from urllib.parse import quote_plus as url_quote_plus unichr = chr elif sys.version_info[0] == 2: - if _can_use_ssl_securely(): - from httplib import HTTPSConnection - else: - from httplib import HTTPConnection import htmlentitydefs + from httplib import HTTPSConnection from urllib import splithost as url_split_host from urllib import quote_plus as url_quote_plus @@ -150,58 +133,8 @@ RE_XML_ILLEGAL = (u'([\u0000-\u0008\u000b-\u000c\u000e-\u001f\ufffe-\uffff])' + XML_ILLEGAL = re.compile(RE_XML_ILLEGAL) -# Python <=3.3 doesn't support create_default_context() -# <2.7.9 and <3.2 never did any SSL verification -# FIXME This can be removed after 2017-09 when 3.3 is no longer supported and -# pypy3 uses 3.4 or later, see -# https://en.wikipedia.org/wiki/CPython#Version_history -if sys.version_info[0] == 3 and sys.version_info[1] == 3: - import certifi - SSL_CONTEXT = ssl.SSLContext(ssl.PROTOCOL_TLSv1) - SSL_CONTEXT.verify_mode = ssl.CERT_REQUIRED - SSL_CONTEXT.options |= ssl.OP_NO_COMPRESSION - # Intermediate from https://wiki.mozilla.org/Security/Server_Side_TLS - # Create the cipher string - cipher_string = """ - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 - DHE-RSA-AES128-GCM-SHA256 - DHE-RSA-AES256-GCM-SHA384 - ECDHE-ECDSA-AES128-SHA256 - ECDHE-RSA-AES128-SHA256 - ECDHE-ECDSA-AES128-SHA - ECDHE-RSA-AES256-SHA384 - ECDHE-RSA-AES128-SHA - ECDHE-ECDSA-AES256-SHA384 - ECDHE-ECDSA-AES256-SHA - ECDHE-RSA-AES256-SHA - DHE-RSA-AES128-SHA256 - DHE-RSA-AES128-SHA - DHE-RSA-AES256-SHA256 - DHE-RSA-AES256-SHA - ECDHE-ECDSA-DES-CBC3-SHA - ECDHE-RSA-DES-CBC3-SHA - EDH-RSA-DES-CBC3-SHA - AES128-GCM-SHA256 - AES256-GCM-SHA384 - AES128-SHA256 - AES256-SHA256 - AES128-SHA - AES256-SHA - DES-CBC3-SHA - !DSS - """ - cipher_string = ' '.join(cipher_string.split()) - SSL_CONTEXT.set_ciphers(cipher_string) - SSL_CONTEXT.load_verify_locations(certifi.where()) - # Python >3.4 and >2.7.9 has sane defaults -elif sys.version_info > (3, 4) or ((2, 7, 9) < sys.version_info < (3, 0)): - SSL_CONTEXT = ssl.create_default_context() +SSL_CONTEXT = ssl.create_default_context() class _Network(object): @@ -1180,15 +1113,10 @@ class _Request(object): (HOST_NAME, HOST_SUBDIR) = self.network.ws_server if self.network.is_proxy_enabled(): - if _can_use_ssl_securely(): - conn = HTTPSConnection( - context=SSL_CONTEXT, - host=self.network._get_proxy()[0], - port=self.network._get_proxy()[1]) - else: - conn = HTTPConnection( - host=self.network._get_proxy()[0], - port=self.network._get_proxy()[1]) + conn = HTTPSConnection( + context=SSL_CONTEXT, + host=self.network._get_proxy()[0], + port=self.network._get_proxy()[1]) try: conn.request( @@ -1198,15 +1126,7 @@ class _Request(object): raise NetworkError(self.network, e) else: - if _can_use_ssl_securely(): - conn = HTTPSConnection( - context=SSL_CONTEXT, - host=HOST_NAME - ) - else: - conn = HTTPConnection( - host=HOST_NAME - ) + conn = HTTPSConnection(context=SSL_CONTEXT, host=HOST_NAME) try: conn.request( @@ -4387,15 +4307,7 @@ class _ScrobblerRequest(object): def execute(self): """Returns a string response of this request.""" - if _can_use_ssl_securely(): - connection = HTTPSConnection( - context=SSL_CONTEXT, - host=self.hostname - ) - else: - connection = HTTPConnection( - host=self.hostname - ) + connection = HTTPSConnection(context=SSL_CONTEXT, host=self.hostname) data = [] for name in self.params.keys(): diff --git a/setup.py b/setup.py index 2bf413c..6d21e2a 100755 --- a/setup.py +++ b/setup.py @@ -7,12 +7,6 @@ setup( version="1.9.0", author="Amr Hassan ", install_requires=['six'], - # FIXME This can be removed after 2017-09 when 3.3 is no longer supported - # and pypy3 uses 3.4 or later, see - # https://en.wikipedia.org/wiki/CPython#Version_history - extras_require={ - ':python_version=="3.3"': ["certifi"], - }, tests_require=['mock', 'pytest', 'coverage', 'pep8', 'pyyaml', 'pyflakes'], description=("A Python interface to Last.fm and Libre.fm"), author_email="amr.hassan@gmail.com", @@ -26,10 +20,11 @@ setup( "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", ], keywords=["Last.fm", "music", "scrobble", "scrobbling"], packages=find_packages(exclude=('tests*',)),