python-multipart 0.0.9__tar.gz → 0.0.10__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. python_multipart-0.0.10/.gitignore +200 -0
  2. python_multipart-0.0.10/CHANGELOG.md +40 -0
  3. python_multipart-0.0.10/PKG-INFO +49 -0
  4. python_multipart-0.0.10/README.md +22 -0
  5. {python_multipart-0.0.9 → python_multipart-0.0.10}/multipart/__init__.py +11 -2
  6. {python_multipart-0.0.9 → python_multipart-0.0.10}/multipart/decoders.py +11 -10
  7. {python_multipart-0.0.9 → python_multipart-0.0.10}/multipart/multipart.py +321 -399
  8. {python_multipart-0.0.9 → python_multipart-0.0.10}/pyproject.toml +46 -15
  9. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/compat.py +0 -23
  10. python_multipart-0.0.10/tests/test_data/http/bad_header_char.http +5 -0
  11. python_multipart-0.0.10/tests/test_data/http/header_with_number.http +11 -0
  12. python_multipart-0.0.10/tests/test_data/http/header_with_number.yaml +7 -0
  13. python_multipart-0.0.10/tests/test_data/http/mixed_plain_and_base64_encoding.http +23 -0
  14. python_multipart-0.0.10/tests/test_data/http/mixed_plain_and_base64_encoding.yaml +18 -0
  15. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_multipart.py +52 -19
  16. python_multipart-0.0.9/.gitignore +0 -61
  17. python_multipart-0.0.9/PKG-INFO +0 -70
  18. python_multipart-0.0.9/README.rst +0 -28
  19. python_multipart-0.0.9/tests/test_data/http/bad_header_char.http +0 -5
  20. {python_multipart-0.0.9 → python_multipart-0.0.10}/LICENSE.txt +0 -0
  21. {python_multipart-0.0.9 → python_multipart-0.0.10}/multipart/exceptions.py +0 -0
  22. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/__init__.py +0 -0
  23. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/CR_in_header.http +0 -0
  24. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/CR_in_header.yaml +0 -0
  25. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/CR_in_header_value.http +0 -0
  26. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/CR_in_header_value.yaml +0 -0
  27. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/almost_match_boundary.http +0 -0
  28. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/almost_match_boundary.yaml +0 -0
  29. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/almost_match_boundary_without_CR.http +0 -0
  30. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/almost_match_boundary_without_CR.yaml +0 -0
  31. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/almost_match_boundary_without_LF.http +0 -0
  32. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/almost_match_boundary_without_LF.yaml +0 -0
  33. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/almost_match_boundary_without_final_hyphen.http +0 -0
  34. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/almost_match_boundary_without_final_hyphen.yaml +0 -0
  35. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/bad_end_of_headers.http +0 -0
  36. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/bad_end_of_headers.yaml +0 -0
  37. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/bad_header_char.yaml +0 -0
  38. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/bad_initial_boundary.http +0 -0
  39. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/bad_initial_boundary.yaml +0 -0
  40. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/base64_encoding.http +0 -0
  41. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/base64_encoding.yaml +0 -0
  42. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/empty_header.http +0 -0
  43. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/empty_header.yaml +0 -0
  44. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/multiple_fields.http +0 -0
  45. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/multiple_fields.yaml +0 -0
  46. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/multiple_files.http +0 -0
  47. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/multiple_files.yaml +0 -0
  48. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/quoted_printable_encoding.http +0 -0
  49. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/quoted_printable_encoding.yaml +0 -0
  50. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field.http +0 -0
  51. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field.yaml +0 -0
  52. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field_blocks.http +0 -0
  53. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field_blocks.yaml +0 -0
  54. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field_longer.http +0 -0
  55. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field_longer.yaml +0 -0
  56. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field_single_file.http +0 -0
  57. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field_single_file.yaml +0 -0
  58. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field_with_leading_newlines.http +0 -0
  59. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_field_with_leading_newlines.yaml +0 -0
  60. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_file.http +0 -0
  61. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/single_file.yaml +0 -0
  62. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/utf8_filename.http +0 -0
  63. {python_multipart-0.0.9 → python_multipart-0.0.10}/tests/test_data/http/utf8_filename.yaml +0 -0
@@ -0,0 +1,200 @@
1
+ # Project-specific ignores.
2
+ tmp/
3
+
4
+ # Installer logs
5
+ pip-log.txt
6
+
7
+ # Unit test / coverage reports
8
+ .coverage*
9
+ .tox
10
+ nosetests.xml
11
+
12
+ # CTags files
13
+ tags
14
+
15
+ #Translations
16
+ *.mo
17
+
18
+ #Mr Developer
19
+ .mr.developer.cfg
20
+
21
+ # SublimeText project files
22
+ /*.sublime-project
23
+ *.sublime-workspace
24
+
25
+ # Windows image file caches
26
+ Thumbs.db
27
+
28
+ # Folder config file
29
+ Desktop.ini
30
+
31
+ # Recycle Bin used on file shares
32
+ $RECYCLE.BIN/
33
+
34
+ # Linux ignores
35
+ *~
36
+
37
+ # OS X ignores
38
+ .DS_Store
39
+
40
+
41
+ # Byte-compiled / optimized / DLL files
42
+ __pycache__/
43
+ *.py[cod]
44
+ *$py.class
45
+
46
+ # C extensions
47
+ *.so
48
+
49
+ # Distribution / packaging
50
+ .Python
51
+ build/
52
+ develop-eggs/
53
+ dist/
54
+ downloads/
55
+ eggs/
56
+ .eggs/
57
+ lib/
58
+ lib64/
59
+ parts/
60
+ sdist/
61
+ var/
62
+ wheels/
63
+ share/python-wheels/
64
+ *.egg-info/
65
+ .installed.cfg
66
+ *.egg
67
+ MANIFEST
68
+
69
+ # PyInstaller
70
+ # Usually these files are written by a python script from a template
71
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
72
+ *.manifest
73
+ *.spec
74
+
75
+ # Installer logs
76
+ pip-log.txt
77
+ pip-delete-this-directory.txt
78
+
79
+ # Unit test / coverage reports
80
+ htmlcov/
81
+ .tox/
82
+ .nox/
83
+ .coverage
84
+ .coverage.*
85
+ .cache
86
+ nosetests.xml
87
+ coverage.xml
88
+ *.cover
89
+ *.py,cover
90
+ .hypothesis/
91
+ .pytest_cache/
92
+ cover/
93
+
94
+ # Translations
95
+ *.mo
96
+ *.pot
97
+
98
+ # Django stuff:
99
+ *.log
100
+ local_settings.py
101
+ db.sqlite3
102
+ db.sqlite3-journal
103
+
104
+ # Flask stuff:
105
+ instance/
106
+ .webassets-cache
107
+
108
+ # Scrapy stuff:
109
+ .scrapy
110
+
111
+ # Sphinx documentation
112
+ docs/_build/
113
+
114
+ # PyBuilder
115
+ .pybuilder/
116
+ target/
117
+
118
+ # Jupyter Notebook
119
+ .ipynb_checkpoints
120
+
121
+ # IPython
122
+ profile_default/
123
+ ipython_config.py
124
+
125
+ # pyenv
126
+ # For a library or package, you might want to ignore these files since the code is
127
+ # intended to run in multiple environments; otherwise, check them in:
128
+ # .python-version
129
+
130
+ # pipenv
131
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
132
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
133
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
134
+ # install all needed dependencies.
135
+ #Pipfile.lock
136
+
137
+ # poetry
138
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
139
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
140
+ # commonly ignored for libraries.
141
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
142
+ #poetry.lock
143
+
144
+ # pdm
145
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
146
+ #pdm.lock
147
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
148
+ # in version control.
149
+ # https://pdm.fming.dev/#use-with-ide
150
+ .pdm.toml
151
+
152
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
153
+ __pypackages__/
154
+
155
+ # Celery stuff
156
+ celerybeat-schedule
157
+ celerybeat.pid
158
+
159
+ # SageMath parsed files
160
+ *.sage.py
161
+
162
+ # Environments
163
+ .env
164
+ .venv
165
+ env/
166
+ venv/
167
+ ENV/
168
+ env.bak/
169
+ venv.bak/
170
+
171
+ # Spyder project settings
172
+ .spyderproject
173
+ .spyproject
174
+
175
+ # Rope project settings
176
+ .ropeproject
177
+
178
+ # mkdocs documentation
179
+ /site
180
+
181
+ # mypy
182
+ .mypy_cache/
183
+ .dmypy.json
184
+ dmypy.json
185
+
186
+ # Pyre type checker
187
+ .pyre/
188
+
189
+ # pytype static type analyzer
190
+ .pytype/
191
+
192
+ # Cython debug symbols
193
+ cython_debug/
194
+
195
+ # PyCharm
196
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
197
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
198
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
199
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
200
+ #.idea/
@@ -0,0 +1,40 @@
1
+ # Changelog
2
+
3
+ ## 0.0.10 (2024-09-21)
4
+
5
+ * Support `on_header_begin` [#103](https://github.com/Kludex/python-multipart/pull/103).
6
+ * Improve type hints on `FormParser` [#104](https://github.com/Kludex/python-multipart/pull/104).
7
+ * Fix `OnFileCallback` type [#106](https://github.com/Kludex/python-multipart/pull/106).
8
+ * Improve type hints [#110](https://github.com/Kludex/python-multipart/pull/110).
9
+ * Improve type hints on `File` [#111](https://github.com/Kludex/python-multipart/pull/111).
10
+ * Add type hint to helper functions [#112](https://github.com/Kludex/python-multipart/pull/112).
11
+ * Minor fix for Field.__repr__ [#114](https://github.com/Kludex/python-multipart/pull/114).
12
+ * Fix use of chunk_size parameter [#136](https://github.com/Kludex/python-multipart/pull/136).
13
+ * Allow digits and valid token chars in headers [#134](https://github.com/Kludex/python-multipart/pull/134).
14
+ * Fix headers being carried between parts [#135](https://github.com/Kludex/python-multipart/pull/135).
15
+
16
+ ## 0.0.9 (2024-02-10)
17
+
18
+ * Add support for Python 3.12 [#85](https://github.com/Kludex/python-multipart/pull/85).
19
+ * Drop support for Python 3.7 [#95](https://github.com/Kludex/python-multipart/pull/95).
20
+ * Add `MultipartState(IntEnum)` [#96](https://github.com/Kludex/python-multipart/pull/96).
21
+ * Add `QuerystringState` [#97](https://github.com/Kludex/python-multipart/pull/97).
22
+ * Add `TypedDict` callbacks [#98](https://github.com/Kludex/python-multipart/pull/98).
23
+ * Add config `TypedDict`s [#99](https://github.com/Kludex/python-multipart/pull/99).
24
+
25
+ ## 0.0.8 (2024-02-09)
26
+
27
+ * Check if Message.get_params return 3-tuple instead of str on parse_options_header [#79](https://github.com/Kludex/python-multipart/pull/79).
28
+ * Cleanup unused regex patterns [#82](https://github.com/Kludex/python-multipart/pull/82).
29
+
30
+ ## 0.0.7 (2024-02-03)
31
+
32
+ * Refactor header option parser to use the standard library instead of a custom RegEx [#75](https://github.com/andrew-d/python-multipart/pull/75).
33
+
34
+ ## 0.0.6 (2023-02-27)
35
+
36
+ * Migrate package installation to `pyproject.toml` (PEP 621) [#54](https://github.com/andrew-d/python-multipart/pull/54).
37
+ * Use yaml.safe_load instead of yaml.load [#46](https://github.com/andrew-d/python-multipart/pull/46).
38
+ * Add support for Python 3.11, drop EOL 3.6 [#51](https://github.com/andrew-d/python-multipart/pull/51).
39
+ * Add support for Python 3.8-3.10, drop EOL 2.7-3.5 [#42](https://github.com/andrew-d/python-multipart/pull/42).
40
+ * `QuerystringParser`: don't raise an AttributeError in `__repr__` [#30](https://github.com/andrew-d/python-multipart/pull/30).
@@ -0,0 +1,49 @@
1
+ Metadata-Version: 2.3
2
+ Name: python-multipart
3
+ Version: 0.0.10
4
+ Summary: A streaming multipart parser for Python
5
+ Project-URL: Homepage, https://github.com/Kludex/python-multipart
6
+ Project-URL: Documentation, https://kludex.github.io/python-multipart/
7
+ Project-URL: Changelog, https://github.com/Kludex/python-multipart/blob/master/CHANGELOG.md
8
+ Project-URL: Source, https://github.com/Kludex/python-multipart
9
+ Author-email: Andrew Dunham <andrew@du.nham.ca>, Marcelo Trylesinski <marcelotryle@gmail.com>
10
+ License-Expression: Apache-2.0
11
+ License-File: LICENSE.txt
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Environment :: Web Environment
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+
28
+ # [Python-Multipart](https://kludex.github.io/python-multipart/)
29
+
30
+ [![Package version](https://badge.fury.io/py/python-multipart.svg)](https://pypi.python.org/pypi/python-multipart)
31
+ [![Supported Python Version](https://img.shields.io/pypi/pyversions/python-multipart.svg?color=%2334D058)](https://pypi.org/project/python-multipart)
32
+
33
+ ---
34
+
35
+ `python-multipart` is an Apache2-licensed streaming multipart parser for Python.
36
+ Test coverage is currently 100%.
37
+
38
+ ## Why?
39
+
40
+ Because streaming uploads are awesome for large files.
41
+
42
+ ## How to Test
43
+
44
+ If you want to test:
45
+
46
+ ```bash
47
+ $ pip install '.[dev]'
48
+ $ inv test
49
+ ```
@@ -0,0 +1,22 @@
1
+ # [Python-Multipart](https://kludex.github.io/python-multipart/)
2
+
3
+ [![Package version](https://badge.fury.io/py/python-multipart.svg)](https://pypi.python.org/pypi/python-multipart)
4
+ [![Supported Python Version](https://img.shields.io/pypi/pyversions/python-multipart.svg?color=%2334D058)](https://pypi.org/project/python-multipart)
5
+
6
+ ---
7
+
8
+ `python-multipart` is an Apache2-licensed streaming multipart parser for Python.
9
+ Test coverage is currently 100%.
10
+
11
+ ## Why?
12
+
13
+ Because streaming uploads are awesome for large files.
14
+
15
+ ## How to Test
16
+
17
+ If you want to test:
18
+
19
+ ```bash
20
+ $ pip install '.[dev]'
21
+ $ inv test
22
+ ```
@@ -2,11 +2,20 @@
2
2
  __author__ = "Andrew Dunham"
3
3
  __license__ = "Apache"
4
4
  __copyright__ = "Copyright (c) 2012-2013, Andrew Dunham"
5
- __version__ = "0.0.9"
5
+ __version__ = "0.0.10"
6
6
 
7
- from .multipart import FormParser, MultipartParser, OctetStreamParser, QuerystringParser, create_form_parser, parse_form
7
+ from .multipart import (
8
+ BaseParser,
9
+ FormParser,
10
+ MultipartParser,
11
+ OctetStreamParser,
12
+ QuerystringParser,
13
+ create_form_parser,
14
+ parse_form,
15
+ )
8
16
 
9
17
  __all__ = (
18
+ "BaseParser",
10
19
  "FormParser",
11
20
  "MultipartParser",
12
21
  "OctetStreamParser",
@@ -1,5 +1,6 @@
1
1
  import base64
2
2
  import binascii
3
+ from io import BufferedWriter
3
4
 
4
5
  from .exceptions import DecodeError
5
6
 
@@ -33,11 +34,11 @@ class Base64Decoder:
33
34
  :param underlying: the underlying object to pass writes to
34
35
  """
35
36
 
36
- def __init__(self, underlying):
37
+ def __init__(self, underlying: BufferedWriter):
37
38
  self.cache = bytearray()
38
39
  self.underlying = underlying
39
40
 
40
- def write(self, data):
41
+ def write(self, data: bytes) -> int:
41
42
  """Takes any input data provided, decodes it as base64, and passes it
42
43
  on to the underlying object. If the data provided is invalid base64
43
44
  data, then this method will raise
@@ -73,14 +74,14 @@ class Base64Decoder:
73
74
  # Return the length of the data to indicate no error.
74
75
  return len(data)
75
76
 
76
- def close(self):
77
+ def close(self) -> None:
77
78
  """Close this decoder. If the underlying object has a `close()`
78
79
  method, this function will call it.
79
80
  """
80
81
  if hasattr(self.underlying, "close"):
81
82
  self.underlying.close()
82
83
 
83
- def finalize(self):
84
+ def finalize(self) -> None:
84
85
  """Finalize this object. This should be called when no more data
85
86
  should be written to the stream. This function can raise a
86
87
  :class:`multipart.exceptions.DecodeError` if there is some remaining
@@ -97,7 +98,7 @@ class Base64Decoder:
97
98
  if hasattr(self.underlying, "finalize"):
98
99
  self.underlying.finalize()
99
100
 
100
- def __repr__(self):
101
+ def __repr__(self) -> str:
101
102
  return f"{self.__class__.__name__}(underlying={self.underlying!r})"
102
103
 
103
104
 
@@ -111,11 +112,11 @@ class QuotedPrintableDecoder:
111
112
  :param underlying: the underlying object to pass writes to
112
113
  """
113
114
 
114
- def __init__(self, underlying):
115
+ def __init__(self, underlying: BufferedWriter) -> None:
115
116
  self.cache = b""
116
117
  self.underlying = underlying
117
118
 
118
- def write(self, data):
119
+ def write(self, data: bytes) -> int:
119
120
  """Takes any input data provided, decodes it as quoted-printable, and
120
121
  passes it on to the underlying object.
121
122
 
@@ -142,14 +143,14 @@ class QuotedPrintableDecoder:
142
143
  self.cache = rest
143
144
  return len(data)
144
145
 
145
- def close(self):
146
+ def close(self) -> None:
146
147
  """Close this decoder. If the underlying object has a `close()`
147
148
  method, this function will call it.
148
149
  """
149
150
  if hasattr(self.underlying, "close"):
150
151
  self.underlying.close()
151
152
 
152
- def finalize(self):
153
+ def finalize(self) -> None:
153
154
  """Finalize this object. This should be called when no more data
154
155
  should be written to the stream. This function will not raise any
155
156
  exceptions, but it may write more data to the underlying object if
@@ -167,5 +168,5 @@ class QuotedPrintableDecoder:
167
168
  if hasattr(self.underlying, "finalize"):
168
169
  self.underlying.finalize()
169
170
 
170
- def __repr__(self):
171
+ def __repr__(self) -> str:
171
172
  return f"{self.__class__.__name__}(underlying={self.underlying!r})"