3780: Lazy load idna library
diff --git a/AUTHORS.rst b/AUTHORS.rst
index c05befce32..cc9e75f3bd 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -175,3 +175,4 @@ Patches and Suggestions
 - Hussain Tamboli <hussaintamboli18@gmail.com> (`@hussaintamboli <https://github.com/hussaintamboli>`_)
 - Casey Davidson (`@davidsoncasey <https://github.com/davidsoncasey>`_)
 - Andrii Soldatenko (`@a_soldatenko <https://github.com/andriisoldatenko>`_)
+- Moinuddin Quadri <moin18@gmail.com> (`@moin18 <https://github.com/moin18>`_)
diff --git a/requests/models.py b/requests/models.py
index 91555b58f8..d1a9c8687d 100644
--- a/requests/models.py
+++ b/requests/models.py
@@ -9,6 +9,7 @@
 
 import collections
 import datetime
+import sys
 
 # Import encoding now, to avoid implicit import later.
 # Implicit import within threads may cause LookupError when standard library is in a ZIP,
@@ -21,7 +22,6 @@
 
 from .auth import HTTPBasicAuth
 from .cookies import cookiejar_from_dict, get_cookie_header, _copy_cookie_jar
-from .packages import idna
 from .packages.urllib3.fields import RequestField
 from .packages.urllib3.filepost import encode_multipart_formdata
 from .packages.urllib3.util import parse_url
@@ -331,6 +331,22 @@ def prepare_method(self, method):
         if self.method is not None:
             self.method = to_native_string(self.method.upper())
 
+    @staticmethod
+    def _get_idna_encoded_host(host):
+        try:
+            from .packages import idna
+        except ImportError:
+            # tolerate the possibility of downstream repackagers unvendoring `requests`
+            # For more information, read: packages/__init__.py
+            import idna
+            sys.modules['requests.packages.idna'] = idna
+
+        try:
+            host = idna.encode(host, uts46=True).decode('utf-8')
+        except idna.IDNAError:
+            raise UnicodeError
+        return host
+
     def prepare_url(self, url, params):
         """Prepares the given HTTP URL."""
         #: Accept objects that have string representations.
@@ -368,17 +384,17 @@ def prepare_url(self, url, params):
         if not host:
             raise InvalidURL("Invalid URL %r: No host supplied" % url)
 
-        # In general, we want to try IDNA encoding every hostname, as that
-        # allows users to automatically get the correct behaviour. However,
-        # we’re quite strict about IDNA encoding, so certain valid hostnames
-        # may fail to encode. On failure, we verify the hostname meets a
-        # minimum standard of only containing ASCII characters, and not starting
-        # with a wildcard (*), before allowing the unencoded hostname through.
-        try:
-            host = idna.encode(host, uts46=True).decode('utf-8')
-        except (UnicodeError, idna.IDNAError):
-            if not unicode_is_ascii(host) or host.startswith(u'*'):
+        # In general, we want to try IDNA encoding the hostname if the string contains
+        # non-ASCII characters. This allows users to automatically get the correct IDNA
+        # behaviour. For strings containing only ASCII characters, we need to also verify
+        # it doesn't start with a wildcard (*), before allowing the unencoded hostname.
+        if not unicode_is_ascii(host):
+            try:
+                host = self._get_idna_encoded_host(host)
+            except UnicodeError:
                 raise InvalidURL('URL has an invalid label.')
+        elif host.startswith(u'*'):
+            raise InvalidURL('URL has an invalid label.')
 
         # Carefully reconstruct the network location
         netloc = auth or ''
diff --git a/requests/packages/__init__.py b/requests/packages/__init__.py
index 4077265e97..971c2ad024 100644
--- a/requests/packages/__init__.py
+++ b/requests/packages/__init__.py
@@ -34,9 +34,3 @@
 except ImportError:
     import chardet
     sys.modules['%s.chardet' % __name__] = chardet
-
-try:
-    from . import idna
-except ImportError:
-    import idna
-    sys.modules['%s.idna' % __name__] = idna

Changes based on comment from previous Pull Request: https://github.com/kennethreitz/requests/pull/3787

Fix for issue: https://github.com/kennethreitz/requests/issues/3780
