Content-Disposition fast access in ClientResponse#2455
Content-Disposition fast access in ClientResponse#2455asvetlov merged 2 commits intoaio-libs:masterfrom
Conversation
|
I dislike two properties. |
|
|
I like idea of |
|
PR number is ok for the case -- it doesn't cover the whole issue. |
Codecov Report
@@ Coverage Diff @@
## master #2455 +/- ##
==========================================
+ Coverage 97.14% 97.14% +<.01%
==========================================
Files 39 39
Lines 8125 8136 +11
Branches 1419 1420 +1
==========================================
+ Hits 7893 7904 +11
Misses 101 101
Partials 131 131
Continue to review full report at Codecov.
|
be43246 to
6afa66c
Compare
| return int(content_length) | ||
|
|
||
| @property | ||
| def content_disposition(self, *, header=hdrs.CONTENT_DISPOSITION): |
There was a problem hiding this comment.
Why the property is in HeadersMixin?
Should web.Request has the property?
I thought it is only for ClientResponse
There was a problem hiding this comment.
Indeed it's response only header.
| else: | ||
| value, params = multipart.parse_content_disposition(raw) | ||
| filename = multipart.content_disposition_filename(params) | ||
| self._content_disposition = ContentDisposition(value, params, |
There was a problem hiding this comment.
Convert params into types.MappingProxyType. The value should be immutable
There was a problem hiding this comment.
Will do in next patchset.
| @property | ||
| def content_disposition(self, *, header=hdrs.CONTENT_DISPOSITION): | ||
| """The value of Content-Disposition HTTP header.""" | ||
| if self._content_disposition == False: |
|
|
||
| _content_type = None | ||
| _content_dict = None | ||
| _content_disposition = False |
There was a problem hiding this comment.
Quite strange default. Why False?
There was a problem hiding this comment.
False if header are not parsed/cached yet
None if there was an attempt to parse, but no header found
ContentDisposition if header was found and parsed
| self._content_type, self._content_dict = cgi.parse_header(raw) | ||
|
|
||
| def _parse_content_disposition(self, _CONTENT_DISPOSITION): | ||
| from . import multipart |
There was a problem hiding this comment.
It was here due to circular import
6afa66c to
41fd2c3
Compare
| raw_headers = None # Response raw headers, a sequence of pairs | ||
|
|
||
| _connection = None # current connection | ||
| _content_disposition = False # content disposition cache |
There was a problem hiding this comment.
I still think that's not good choice. None means no value. We tried to parse it, nothing happened. Yes, this will trigger headers lookup for each property access - but that's not a problem.
There was a problem hiding this comment.
Good alternative, but None is fine as well. However, even better would be to use reify here and avoid internal attributes. Headers are immutable in anyway.
41fd2c3 to
2ede86e
Compare
| value, params = multipart.parse_content_disposition(raw) | ||
| params = MappingProxyType(params) | ||
| filename = multipart.content_disposition_filename(params) | ||
| return ContentDisposition(value, params, filename) |
There was a problem hiding this comment.
Convert params into immutable structure
There was a problem hiding this comment.
What do you mean? params is already converted to MappingProxyType line 565
|
|
| self._request_info = request_info | ||
| self._timer = timer if timer is not None else TimerNoop() | ||
| self._auto_decompress = auto_decompress | ||
| self._cache = {} |
There was a problem hiding this comment.
Looks like no. All classes with @reify methods have this and AttributeError is raising without this line.
There was a problem hiding this comment.
Implicit magic. Worth to add notice about.
There was a problem hiding this comment.
I mean the attr is required, not a notice :)
But the notice makes no harm
There was a problem hiding this comment.
Oh, ok. Last time I saw reify in acttion, no special attrs were required.
|
|
||
| assert 'attachment' == response.content_disposition.value | ||
| assert 'bar' == response.content_disposition.parameters["foo"] | ||
| assert 'archive.tar.gz' == response.content_disposition.filename |
There was a problem hiding this comment.
Worth to add two more cases:
content_disposition.parametersis immutable- second access to
content_dispositionreturns the same result ifClientResponse.headerswere modified in-between (I'm surprised to see it's not read-only property).
|
|
||
| .. attribute:: value | ||
|
|
||
| Value of Content-Disposition header itself, e.g. ``attachment``. |
There was a problem hiding this comment.
"attachment" - you want to notice that the value is a string typed.
|
|
||
| .. attribute:: parameters | ||
|
|
||
| A :class:`dict` instance contains all parameters. |
There was a problem hiding this comment.
Actually, it's not a dict, but MapptingProxy. Difference in mutability.
There was a problem hiding this comment.
We could just replace it with *mapping* for sake of simplicity.
I pretty sure not many python developers know what MappingProxy is :)
|
|
||
|
|
||
| ContentDisposition = collections.namedtuple( | ||
| 'ContentDisposition', ('value', 'parameters', 'filename')) |
There was a problem hiding this comment.
I think value is not the best choice. The RFC defines it as a type which suites more to what the value it holds.
| raw = self._headers.get(hdrs.CONTENT_DISPOSITION) | ||
| if raw is None: | ||
| return None | ||
| value, params = multipart.parse_content_disposition(raw) |
There was a problem hiding this comment.
It seems only two values here are valid for HTTP headers case: inline and attachment. May be worth to raise a warning about invalid type or turn the value in Enum?
There was a problem hiding this comment.
According to https://tools.ietf.org/html/rfc6266#section-4.1 any token is valid
There was a problem hiding this comment.
I like Enum but how the change affects multidict and existing users.
I suspect parse_content_disposition is internal API but not 100% sure.
There was a problem hiding this comment.
@redixin Yes, but RFC defines more general Content-Disposition definition. Mozilla explicitly splits it into HTTP headers and Multpart headers. The second one utilize token rule completely, but here we are in HTTP response land.
ff12184 to
dec87c0
Compare
Add ContentDisposition class and content_disposition property Partially implements aio-libs#1670
dec87c0 to
9b6a528
Compare
|
Great work! |
|
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a [new issue] for related bugs. |
Add content_disposition and content_disposition_dict properties
Partially implements #1670
What do these changes do?
Improves ClientResponse ergonomics
Are there changes in behavior for the user?
All changes are documented.
Related issue number
#1670
Checklist
CONTRIBUTORS.txtCHANGESfolder<issue_id>.<type>for example (588.bug)issue_idchange it to the pr id after creating the pr.feature: Signifying a new feature..bugfix: Signifying a bug fix..doc: Signifying a documentation improvement..removal: Signifying a deprecation or removal of public API..misc: A ticket has been closed, but it is not of interest to users.