-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: What features should be included in v2? #1944
Comments
What's the reasoning for starting deprecation warnings in |
Also related thread that has many good ideas, some of which we've already done: #776 |
You basically nailed it with the polluting v1.x series with deprecation warnings. 1.x will still be supported so there's no reason users can't continue to use the features they're used to in 1.x. Also provides a valid upgrade path for users if we hide these features behind flags so you don't have to fix ALL the things all at once, instead you can fix one thing at a time and enable flags as you go, it'd be tougher to provide that experience without adding the deprecations to v2.x. |
I get that feel and I support it if that's the route we want to go, but at the same time I feel it kind of defeats the premise of versioning. There is an implicit expectation that the biggest breaking changes are included in the most major version bump. Hmm. (Will people feel tricked if they upgrade to v2.x series and be all "wow that was easy, just some warnings" and then suddenly v2.1 breaks everything?) Also I worry about the maintainer burden of committing to letting people stay in 1.x indefinitely (py2/py3 flashback). Perhaps a better compromise is to ship the deprecation warnings in 1.x and supply a convenient way to disable them? ( Could even add a transition period in 1.x where the deprecations are opt-in ( |
@shazow If we go that route we're splitting up the actual features with the logic for detecting when they'd be used and should emit a deprecation warning. Best to keep all of that work in the same stream so managing this all doesn't get confusing? And I understand wanting to follow strict versioning guidance but I fear that it wouldn't do a lot to protect our users from unwanted breakages. Any route that requires opt-in to get deprecations is going to be ignored, if there is a way to opt out in v1.x it'll need to be applied to every code base successfully using v1.x which is a ton of lifting for every project that uses us to do. "Staying on 1.x indefinitely" is a part of the service we provide with Tidelift. It's exactly the kind of thing we should be doing as long as we have a partnership with them, 1.x works just fine as long as it receives security fixes. There'll be a time to sunset this version but it's likely no time soon. My thought is that coordinating with our major upstream dependent packages (pip, requests, boto, etc) along with allowing an alpha version plenty of time to bake with documentation to remediation strategies in deprecation warnings will be enough to protect/brace users from the inevitable "things stop working now". At least that's the hope :) |
This is a difficult question with good arguments either side, but just to clarify: Tidelift will also expect us to fix security issues in 2.x, right? |
@pquentin Yeah Tidelift will expect security fixes in 2.x as well. |
Hmm, I could be imagining the process incorrectly! I was picturing starting off by littering Did you have something different in mind? Personally, I have trouble imagining a scenario where people complain relatively more that we put deprecation warnings about v2 stuff in v1.x branches, but that could be a limitation of my imagination. :)
Right, I get that maintaining older version branches is part of the arrangement with Tidelift and being a good open source steward in general, but it's still in our power whether we actively encourage people to migrate to the new API or encourage people to stay with what they already have (the default if we try to stay neutral). Anyway, I don't feel incredibly strongly about this. My main concern is imagining two possible outcomes: one where most people switch to v2 pretty quickly due to deprecation warning awareness vs most people staying on v1 for way too long because they're pinning v1.x and have no reason to make the explicit effort to check out v2. |
I agree with this. The deprecation warnings belong in 1.x. The changes in 2.0 |
Okay I'm convinced after thinking about the scenarios more. We'll add deprecation warnings to v1.26.x when we feel we're getting close enough to releasing v2.0.0a1. Now that the where is decided: we're thinking of using |
I believe so. I think it makes sense to inherit from |
Do we know how much breakage this is going to cause? My understanding is that integrating other HTTP implementations will break compatibility anyway (as we've seen with the v2 branch and the sync part of python-trio/hip), so I'm not sure how helpful this will be anyway. I think I'd rather stick to dropping old Python versions and improving security, which can only help with 2.x adoption. (Much the same way that Python 3 should probably have been only about Unicode strings by default) |
Sounds good to me.
@pquentin My wording was bad above, I updated the wording in the original post. This shouldn't cause any breakage, want to keep the httplib behavior as the default but signal to the user that APIs on the from http.client import HTTPConnection as _HTTPConnection
class BaseHTTPConnection:
def request(...): ...
def request_chunked(...): ...
def connect(): ...
def close(): ...
class BaseHTTPSConnection(BaseHTTPConnection):
def set_cert(...): ...
# These will still be the default ConnectionCls on ConnectionPool
# but users can swap them out if desired.
class HTTPConnection(BaseHTTPConnection, _HTTPConnection):
...
class HTTPSConnection(BaseHTTPSConnection, HTTPConnection):
...
# If we create an HTTPConnection using h11 for example
# it'll inherit from BaseHTTPConnection
class H11HTTPConnection(BaseHTTPConnection):
... This will allow us to implement extra edit: Also means we can have
|
This sounds good to me. If we're looking at providing a typesafe API, we can define a protocol that the API is typed as returning so that people using mypy are warned when methods or attributes they use aren't provided by that protocol (even if they are provided by the runtime-returned concrete type). |
Throwing |
My pet feature request: Add a default PoolManager, so that beginners don't have to be intimidated by the word "PoolManager". Go does this also, and it seems to work very well in practice. (Note: This proposal is to use a module-global instance that persists across requests like Go, rather than a one-off instance that gets disposed after each request like Requests.) Something like: # urllib3/__init__.py:
DEFAULT_POOL = PoolManager()
def request(...):
"""
request is a short-cut which uses the DEFAULT_POOL.
For more complex configurations, consider making your own PoolManager instance.
"""
return DEFAULT_POOL.request(...) So that as a beginner, the Quick Start can be: import urllib3
r = urllib3.request('GET', ...) Also once upon a time I wanted to introduce the idea of a SessionManager that would contain a PoolManager plus other things, but I think we decided not to go that route. |
@shazow How could I forget that feature! Agree we should provide a top-level |
Proposal for consideration: Add back verb shortcuts? (I don't have strong feelings about this, but something that could be worth considering for v2.) urllib3 originally launched with verb shortcuts, but they were removed because I didn't like that .get collided with other common APIs like dictionaries. In the end, maybe I was wrong and the "smell" is worth the usability convenience? |
eh, I'm -1 on the verb aliases, |
/cc @dstufft in case he has ideas/opinions. :) |
If y'all are considering a lot of breaking changes in urllib3 I would appreciate shipping with compat shims of some sort that allows libraries to work with both urllib3 versions, or to at least keep this user requirement in mind somehow. The Sentry sdk will likely not be in a position to enforce an upper bound or a high lower bound on the version of urllib3 it requires due to version conflicts with user deptree. |
|
@untitaker Yeah we're aiming for zero functional API breaks despite the major increment. An example of this is the To do this we can:
We'd need to do some investigation to see how frequently we're subclassed. |
I updated my comment and linked to the existing issues for things I was thinking about as well as added others in there. |
Yeah I'll have to create issues for all the things we've discussed that don't already have one. |
One thing that definetly could be easier is to hook into name resolution and connection buildup/socket creation. Sentry had to duplicate some code to make this work: https://github.com/getsentry/sentry/blob/807f1cb1c5fbed1fccad3b22cf0795023eb2e1b3/src/sentry/net/http.py#L22 (see also outer folder) What we're trying to do here is to prevent urllib3/requests from making requests to the local network. This requires us to control the step between dns lookup and socket opening, as that's where we have the concrete IP we would connect to. For reference here is the equivalent in Rust: https://github.com/getsentry/symbolicator/blob/d95667c8505b0a02ca194759a6f59d9a5b1ab152/src/utils/http.rs#L92 -- While not any shorter it does not use private APIs or copy code. |
Another big idea suggestion: Translated Documentation
Given that list we can maybe start with Mandarin, German, Russian, Japanese, French, Portuguese and Korean? Warehouse has seen success with Weblate and it seems like there's good support for Sphinx and RTD. |
Making a borderline political statement (politics around language is 100% a thing in India), I'm sure you won't need a Hindi translation -- I reckon 100% of Indian users who'll reach urllib3's documentation will be able to read English. I doubt you would even be able find someone who'd be willing to do the translation 100% on board for using Weblate for the translations, that is indeed working pretty well PyPI. :) |
@pradyunsg Got it! Thanks for that data point :) |
I love the idea of doing community translations of our docs, and I don't think that even needs to be blocked by a v2 release (or vice versa). :) |
@shazow Agree, but it'd be nice to use Weblate which costs money and pay our community translators for their efforts. We can make releases of translations before the actual 2.0 release for sure! |
I'm happy to include plenty of stuff in v2, but I'm worried about a huge 2.0 release that contains lots of stuff and that is only released after a year of development in late 2021. We did make this error in the past: the existing Instead, let's release early and often! Proposed plan
That way, even if 1.x will the be most used version for some time, 2.0 can still get some usage quickly, which will get us feedback quickly, so that we can fix things early. What do you think? |
Are you sure? 馃槈 From https://weblate.org/en/hosting/:
|
pip won't support Python 2.x in 2021 anymore either. |
@dstufft Sure, but not supporting Python 2 and using urllib3 2.0 are two different things! I was talking about the latter, to note that releasing 2.0 early would not be a problem. Thanks for dropping Python 2 in January 2021, by the way! This will allow requests to drop support too, I think they're aiming to do it ~6 months after pip. |
re: @pquentin's proposal: Totally agree we should split up things into either breaking changes or improvements in order to make sure we can get across the finish line. So we can schedule things as either v2.0 and v2.1. I guess my worry is timing of when deprecation warnings for breaking features that should land in v1.26 both get developed and released before the v2.0 release goes out (with sufficient time). Here's my thoughts on what exactly the release schedule would look like:
Another thought, should all deprecations for v2.0 breaking changes be shipped with the first v1.26.0 release, or is it okay to add new deprecations in a patch version of 1.26.x? I'm leaning towards adding the deprecations as a part of v1.26.0 but then that obviously delays v1.26.0 and v2.0 going out, but maybe that's a good thing? Probably most courteous to our users. This makes sure we ship the most important features of v2.0 ASAP but is a little more legwork and planning for us, but also compliments the discussion above for adding the deprecations to v1.26.0 so I think I'm in favor of this :) Would love others thoughts too. |
The v2.0 Roadmap page is live now with a list of features and other information regarding the release: https://urllib3.readthedocs.io/en/latest/v2-roadmap.html This doesn't mean we're not accepting more feature requests for v2.0 since at this point any feature request is probably landing in v2.0 anyways :) These are however the highlighted features. I'll keep this open for now and split the individual features into their own if they aren't ones already. Might close it once we start working on v2.0 proper. |
Added issue numbers to all the features and added them to the v2.0 milestone (boy that's a lot!) Also added deprecation issues to the v1.26 milestone since we're shipping v1.26.0 with all deprecations. |
One thing that came to mind this morning was urllib3's (really httplib's) edge cases around incomplete server responses. There was some work in #949 to add a flag on strictly enforcing content length on responses. The intention was to make the flag default to I'm not sure I'm still in favor of changing the default, since it's almost certainly breaking, but wanted to bring it up before we solidify 2.0. psf/requests#4956 details a number of places people have been bitten by this. |
What about a parse_url that "validates" the given URL and return a None instead of URL if the input is completely wrong? Or alternatively a validate() method that returns a boolean? |
@andreamoro what do you expect the validation to be? |
We already validate for obviously wrong URLs. The one you provided would likely be parsed as a host without a scheme which is a supported input. |
@sethmlarson you are right in saying that is validated as a host, and in fact I posted the wrong example when I published the post.
That being said, with the previous URL is probably correct interpret the URL as an host but you may agree with me that an address without a scheme doesn't really make sense. And leaving the scheme as assumption to me does not sound a good choice. So a validation could probably be a more strict/stringent set of rules against a dictionary of addresses that people might want to validate against. E.g.
|
I would like to see more granular support for IPv6. There are several possibilities: force IPv6, force IPv4, use IPv6 if available, and (for completeness) use IPv4 if available. |
I'd like to see solving the regression of handling "domain\user" type of usernames (#1870). |
Any reason SessionManager was dropped? We are currently in a situation where we need the PoolManager to have global cookie state, and this would have been incredibly easy way to achieve that. |
|
Add jitter to Also fix how |
Going to close this issue since v2.0 pre-releases have shipped. If there are features (or fixes) in this issue that you want to land in urllib3 please open a separate issue for them. |
Roadmap is Live! 馃コ
Mission
Improve urllib3 incrementally by keeping 99% functional API compatibility while dropping Python versions 2.7 and 3.5.
Unlock further improvements down the road by untangling our API from httplib while maintaining httplib as our default HTTP implementation.
Roadmap
We'll be adding DeprecationWarnings to 1.26.x for changing behavior whenever v2 is getting close to an alpha version to start preparing users to upgrade.
Our team will continue to maintain the
1.x
series with bug fixes and security fixes for the forseable future. The v2 release hopefully will be available in late 2021 after Pip has dropped support for Python 2.Features
I've created a v2.0 Milestone to track what major features we'd like to deliver before shipping a 2.0.0 alpha version:
HTTPConnection
object that doesn't subclasshttp.client.HTTPConnection
([v2] Create a BaseHTTPConnection APIs聽#1985, [v2] Create BaseHTTPResponse API聽#1986)like
h11
, macOSNetwork.URLSession
(cc BeeWare/@freakboy3742), or even HTTP/2 (?!?!)<2
to help users installing us with old Pip versions ([v2] Detect unsupported Python versions and raise a helpful ImportError聽#1987)commonName
on certificates (Feature: Remove support for common names in certificates聽#497)urllib3.exceptions.SSLError
for common issueslike expired certificates, bad subjectAltName ([v2] Improve usability of SSLError/CertificateError聽#1991)
Content-Encoding: zstd
(RFC 8478) ([v2] Add support for Content-Encoding: zstd聽#1992)encode_multipart_formdata
聽#624)urllib3.request()
method with a defaultPoolManager()
([v2] Add a top-level urllib3.request() method聽#1993)I'm open to adding more or further clarifying some of these issues.
cc @urllib3/maintainers @nateprewitt
The text was updated successfully, but these errors were encountered: