r"""Parse a Content-type like header. Return the main content-type and a dictionary of options. >>> d = "form-data; foo=\"b\\\\a\\\"r\"; file*=utf-8''T%C3%A4st" >>> ct, d = _parse_header(d) >>> ct 'form-data' >>> d['file'] == r'T\u00e4st'.encode('ascii').decode('unicode_esc
(line: str)
| 1222 | |
| 1223 | |
| 1224 | def _parse_header(line: str) -> Tuple[str, Dict[str, str]]: |
| 1225 | r"""Parse a Content-type like header. |
| 1226 | |
| 1227 | Return the main content-type and a dictionary of options. |
| 1228 | |
| 1229 | >>> d = "form-data; foo=\"b\\\\a\\\"r\"; file*=utf-8''T%C3%A4st" |
| 1230 | >>> ct, d = _parse_header(d) |
| 1231 | >>> ct |
| 1232 | 'form-data' |
| 1233 | >>> d['file'] == r'T\u00e4st'.encode('ascii').decode('unicode_escape') |
| 1234 | True |
| 1235 | >>> d['foo'] |
| 1236 | 'b\\a"r' |
| 1237 | """ |
| 1238 | parts = _parseparam(";" + line) |
| 1239 | key = next(parts) |
| 1240 | # decode_params treats first argument special, but we already stripped key |
| 1241 | params = [("Dummy", "value")] |
| 1242 | for p in parts: |
| 1243 | i = p.find("=") |
| 1244 | if i >= 0: |
| 1245 | name = p[:i].strip().lower() |
| 1246 | value = p[i + 1 :].strip() |
| 1247 | params.append((name, native_str(value))) |
| 1248 | decoded_params = email.utils.decode_params(params) |
| 1249 | decoded_params.pop(0) # get rid of the dummy again |
| 1250 | pdict = {} |
| 1251 | for name, decoded_value in decoded_params: |
| 1252 | value = email.utils.collapse_rfc2231_value(decoded_value) |
| 1253 | if len(value) >= 2 and value[0] == '"' and value[-1] == '"': |
| 1254 | value = value[1:-1] |
| 1255 | pdict[name] = value |
| 1256 | return key, pdict |
| 1257 | |
| 1258 | |
| 1259 | def _encode_header(key: str, pdict: Dict[str, str]) -> str: |
no test coverage detected