Only load .packages.urllib3.contrib.pyopenssl if we have an old version of OpenSSL.

See issue #3213

Ok, @alex and @reaperhulk really need to sign off on this before I consider merging it. ;)

Ok, all commenters, *please* read some of the discussion on #3213 before making further comments here. You'll find it helps you avoid retreading some ground. ;)

@reaperhulk, my main concern here is that we are fundamentally looking at adding this patch because "importing PyOpenSSL is slow". My question is: do you consider that a bug?

It would help to quantify slow. In the long long ago (pre-cryptography 1.0) importing pyOpenSSL was slow (1+ seconds), but on my 4 year old laptop I just tested and it took about 50ms to import pyOpenSSL 16.2 + cryptography 1.7.  `import requests` with no pyOpenSSL installed takes ~63ms and ~108ms for requests+pyOpenSSL. That doesn't seem particularly problematic.

It'd also help if I took @Lukasa's advice and actually read the whole issue that spawned this.

I don't consider the current import performance to be a bug, but if someone wants to try to improve it on cryptography (which is probably the dominant source of import time for pyopenssl) I'm happy to review. The biggest single source of time is likely when it loops over the lib object to build a new conditional lib object. That could be optimized if cffi supported a means of conditional binding, but we're likely talking only ~10ms?

So step 1 is: are we talking about the same level of "slow" here?

@Lukasa @reaperhulk so it's worth noting that `slow` will change based on how many things are installed + how many possible entry-points exist. `pkg_resources`, if I remember correctly, will scan all of `site_packages` for entry-points. So if you're testing `pyOpenSSL` in a fresh virtual environment, you're import speed (given that cryptography apparently scans entry-points at import) is going to be faster than @dsully since they seem to be installing a lot of things in one `site_packages` directory.

Granted, this is a fundamental flaw of how `pkg_resources` works, but I think it's still a legitimate problem. I haven't looked at what cryptography uses `pkg_resources` to find at import, but there would only be "import time" benefits to avoiding that scan rather than any real performance benefit to not doing it when cryptography is imported.

I'd also like a better understanding of `slow` from @dsully + maybe a better description of how much is being installed into their site-packages directory.

Also, to set everyone's expectations appropriately, this appears to be a problem @dsully is encountering at work, so I completely expect them to *not* respond until Monday during work hours.

Okay, this is getting a bit more interesting. `pkg_resources` is invoked to determine what backends are available to cryptography. This is done in `cryptography.hazmat.backends.__init__`. requests doesn't need that check since it directly imports the backend it requires. However, if you look in that you can see that we **are** doing it lazily. To summarize a wasted hour here, `import pkg_resources` is actually where we pay the speed penalty. I haven't looked into what's going on inside `pkg_resources`, but it seems likely that a side effect of importing is an immediate scan of the packages?

Anyway, this points us to a potential significant performance improvement: just `import pkg_resources` inside the function call so it is lazily imported as well. On my machine with a test virtualenv containing 100 packages this drops the import time by 150ms.

@reaperhulk If the cryptography team is okay with moving the import inside the function that seems suitable and should eliminate the need for this PR based on your findings.

@reaperhulk Yes - removing the pkg_resources import until it's needed will certainly help. I'll create a PR over there to move the import.

@sigmavirus24 nails it - we have a lot installed in site-packages, and are extremely sensitive about CLI tools start up time. Every millisecond counts in the eyes of our users. I do agree this is a fundamental flaw in pkg_resources. (My weekend was pretty packed, so I wasn't able to reply until now).

I do feel that requests automatically trying to use pyopenssl if it's installed without any way to opt-out is surprise functionality. I do have a work around for now, so this PR can be dropped.

> I do feel that requests automatically trying to use pyopenssl if it's installed without any way to opt-out is surprise functionality.

I mean, you can opt-out *after* import with no difficulty at all. ;)