aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2018-12-07 11:43:38 +0800
committerAlex Gaynor <alex.gaynor@gmail.com>2018-12-06 22:43:38 -0500
commit7e422821b9f800f5345c37011c510dc9e76f552c (patch)
tree684836bedeb4ae9d898a014068f1555cd25c58aa
parentfec719b60441b1e69bcca26446b8025bb69ee1fd (diff)
downloadcryptography-7e422821b9f800f5345c37011c510dc9e76f552c.tar.gz
cryptography-7e422821b9f800f5345c37011c510dc9e76f552c.tar.bz2
cryptography-7e422821b9f800f5345c37011c510dc9e76f552c.zip
remove idna as a primary dependency (#4624)
* remove idna as a primary dependency * empty commit * dynamodb test fix (thanks to Matt Bullock) * review feedback
-rw-r--r--.travis.yml9
-rw-r--r--CHANGELOG.rst4
-rw-r--r--docs/faq.rst12
-rw-r--r--setup.py7
-rw-r--r--src/cryptography/x509/general_name.py29
-rw-r--r--tests/x509/test_x509_ext.py26
-rw-r--r--tox.ini1
7 files changed, 67 insertions, 21 deletions
diff --git a/.travis.yml b/.travis.yml
index 8fda6709..2a636ad1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,6 +29,8 @@ matrix:
env: TOXENV=py36
- python: 3.7
env: TOXENV=py37
+ - python: 3.7
+ env: TOXENV=py37-idna
- python: pypy-5.3
env: TOXENV=pypy-nocoverage
# PyPy 5.3 isn't available for xenial
@@ -121,10 +123,9 @@ matrix:
- python: 2.7
env: DOWNSTREAM=aws-encryption-sdk
- python: 2.7
- env: DOWNSTREAM=dynamodb-encryption-sdk OPENSSL=1.1.0j
- # dynamodb-encryption-sdk tests fail on xenial for whatever reason
- dist: trusty
- sudo: false
+ # BOTO_CONFIG works around this boto issue on travis:
+ # https://github.com/boto/boto/issues/3717
+ env: DOWNSTREAM=dynamodb-encryption-sdk OPENSSL=1.1.0j BOTO_CONFIG=/dev/null
- python: 2.7
env: DOWNSTREAM=certbot OPENSSL=1.1.0j
- python: 2.7
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index b75836d4..eb7a4d89 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -8,6 +8,10 @@ Changelog
.. note:: This version is not yet released and is under active development.
+* **BACKWARDS INCOMPATIBLE:** :term:`U-label` strings were deprecated in
+ version 2.1, but this version removes the default ``idna`` dependency as
+ well. If you still need this deprecated path please install cryptography
+ with the ``idna`` extra: ``pip install cryptography[idna]``.
* Added support for :class:`~cryptography.hazmat.primitives.hashes.SHA512_224`
and :class:`~cryptography.hazmat.primitives.hashes.SHA512_256` when using
OpenSSL 1.1.1.
diff --git a/docs/faq.rst b/docs/faq.rst
index 409f6ce0..dce94b73 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -99,6 +99,18 @@ support multiple versions of Python. The Python 3.4 ``abi3`` wheel can be used
with any version of Python greater than or equal to 3.4. Recent versions of
``pip`` will automatically install ``abi3`` wheels.
+``ImportError``: ``idna`` is not installed
+------------------------------------------
+
+``cryptography`` deprecated passing :term:`U-label` strings to various X.509
+constructors in version 2.1 and in version 2.5 moved the ``idna`` dependency
+to a ``setuptools`` extra. If you see this exception you should upgrade your
+software so that it no longer depends on this deprecated feature. If that is
+not yet possible you can also install ``cryptography`` with
+``pip install cryptography[idna]`` to automatically install the missing
+dependency. This workaround will be available until the feature is fully
+removed.
+
.. _`NaCl`: https://nacl.cr.yp.to/
.. _`PyNaCl`: https://pynacl.readthedocs.io
.. _`WSGIApplicationGroup`: https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIApplicationGroup.html
diff --git a/setup.py b/setup.py
index 937d1ac5..bd98fd5e 100644
--- a/setup.py
+++ b/setup.py
@@ -287,7 +287,6 @@ setup(
python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
install_requires=[
- "idna >= 2.1",
"asn1crypto >= 0.21.0",
"six >= 1.4.1",
] + setup_requirements,
@@ -311,6 +310,12 @@ setup(
"flake8-import-order",
"pep8-naming",
],
+ # This extra is for the U-label support that was deprecated in
+ # cryptography 2.1. If you need this deprecated path install with
+ # pip install cryptography[idna]
+ "idna": [
+ "idna >= 2.1",
+ ]
},
# for cffi
diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py
index 42082746..1b0f8c8f 100644
--- a/src/cryptography/x509/general_name.py
+++ b/src/cryptography/x509/general_name.py
@@ -30,6 +30,20 @@ _GENERAL_NAMES = {
}
+def _lazy_import_idna():
+ # Import idna lazily becase it allocates a decent amount of memory, and
+ # we're only using it in deprecated paths.
+ try:
+ import idna
+ return idna
+ except ImportError:
+ raise ImportError(
+ "idna is not installed, but a deprecated feature that requires it"
+ " was used. See: https://cryptography.io/en/latest/faq/#importe"
+ "rror-idna-is-not-installed"
+ )
+
+
class UnsupportedGeneralNameType(Exception):
def __init__(self, msg, type):
super(UnsupportedGeneralNameType, self).__init__(msg)
@@ -81,10 +95,7 @@ class RFC822Name(object):
return instance
def _idna_encode(self, value):
- # Import idna lazily becase it allocates a decent amoutn of memory, and
- # we're only using it in deprecated paths.
- import idna
-
+ idna = _lazy_import_idna()
_, address = parseaddr(value)
parts = address.split(u"@")
return parts[0] + "@" + idna.encode(parts[1]).decode("ascii")
@@ -106,10 +117,7 @@ class RFC822Name(object):
def _idna_encode(value):
- # Import idna lazily becase it allocates a decent amoutn of memory, and
- # we're only using it in deprecated paths.
- import idna
-
+ idna = _lazy_import_idna()
# Retain prefixes '*.' for common/alt names and '.' for name constraints
for prefix in ['*.', '.']:
if value.startswith(prefix):
@@ -193,10 +201,7 @@ class UniformResourceIdentifier(object):
return instance
def _idna_encode(self, value):
- # Import idna lazily becase it allocates a decent amoutn of memory, and
- # we're only using it in deprecated paths.
- import idna
-
+ idna = _lazy_import_idna()
parsed = urllib_parse.urlparse(value)
if parsed.port:
netloc = (
diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py
index bfa37847..152db964 100644
--- a/tests/x509/test_x509_ext.py
+++ b/tests/x509/test_x509_ext.py
@@ -20,6 +20,7 @@ from cryptography.hazmat.backends.interfaces import (
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.x509 import DNSName, NameConstraints, SubjectAlternativeName
+from cryptography.x509.general_name import _lazy_import_idna
from cryptography.x509.oid import (
AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID,
NameOID, ObjectIdentifier
@@ -44,6 +45,17 @@ def _make_certbuilder(private_key):
)
+def test_lazy_idna_import():
+ try:
+ __import__("idna")
+ pytest.skip("idna is installed")
+ except ImportError:
+ pass
+
+ with pytest.raises(ImportError):
+ _lazy_import_idna()
+
+
class TestExtension(object):
def test_not_an_oid(self):
bc = x509.BasicConstraints(ca=False, path_length=None)
@@ -1661,10 +1673,8 @@ class TestKeyUsageExtension(object):
class TestDNSName(object):
- def test_init(self):
- name = x509.DNSName(u"*.xn--4ca7aey.example.com")
- assert name.value == u"*.xn--4ca7aey.example.com"
-
+ def test_init_deprecated(self):
+ pytest.importorskip("idna")
with pytest.warns(utils.DeprecatedIn21):
name = x509.DNSName(u".\xf5\xe4\xf6\xfc.example.com")
assert name.value == u".xn--4ca7aey.example.com"
@@ -1673,6 +1683,10 @@ class TestDNSName(object):
name = x509.DNSName(u"\xf5\xe4\xf6\xfc.example.com")
assert name.value == u"xn--4ca7aey.example.com"
+ def test_init(self):
+ name = x509.DNSName(u"*.xn--4ca7aey.example.com")
+ assert name.value == u"*.xn--4ca7aey.example.com"
+
with pytest.raises(TypeError):
x509.DNSName(1.3)
@@ -1788,6 +1802,7 @@ class TestRFC822Name(object):
assert gn.value == u"administrator"
def test_idna(self):
+ pytest.importorskip("idna")
with pytest.warns(utils.DeprecatedIn21):
gn = x509.RFC822Name(u"email@em\xe5\xefl.com")
@@ -1827,6 +1842,7 @@ class TestUniformResourceIdentifier(object):
assert gn.value == u"singlelabel:443/test"
def test_idna_no_port(self):
+ pytest.importorskip("idna")
with pytest.warns(utils.DeprecatedIn21):
gn = x509.UniformResourceIdentifier(
u"http://\u043f\u044b\u043a\u0430.cryptography"
@@ -1835,6 +1851,7 @@ class TestUniformResourceIdentifier(object):
assert gn.value == u"http://xn--80ato2c.cryptography"
def test_idna_with_port(self):
+ pytest.importorskip("idna")
with pytest.warns(utils.DeprecatedIn21):
gn = x509.UniformResourceIdentifier(
u"gopher://\u043f\u044b\u043a\u0430.cryptography:70/some/path"
@@ -1849,6 +1866,7 @@ class TestUniformResourceIdentifier(object):
assert gn.value == "ldap:///some-nonsense"
def test_query_and_fragment(self):
+ pytest.importorskip("idna")
with pytest.warns(utils.DeprecatedIn21):
gn = x509.UniformResourceIdentifier(
u"ldap://\u043f\u044b\u043a\u0430.cryptography:90/path?query="
diff --git a/tox.ini b/tox.ini
index f6e1b6e1..d4c3022b 100644
--- a/tox.ini
+++ b/tox.ini
@@ -5,6 +5,7 @@ envlist = py27,pypy,py34,py35,py36,py37,docs,pep8,py3pep8
[testenv]
extras =
test
+ idna: idna
deps =
# This must be kept in sync with Jenkinsfile and .travis/install.sh
coverage