Update upstream source from tag 'upstream/2.1.0'
Update to upstream version '2.1.0'
with Debian dir 69870a9048f3c157ae1ffe461db2793cf413a42f
Andrej Shadura
1 year, 11 months ago
0 | name: Continuous Integration | |
1 | ||
2 | on: | |
3 | push: | |
4 | branches: [ master ] | |
5 | pull_request: | |
6 | branches: [ master ] | |
7 | ||
8 | jobs: | |
9 | lint: | |
10 | runs-on: ubuntu-latest | |
11 | ||
12 | steps: | |
13 | - uses: actions/checkout@v2 | |
14 | - name: Set up Python ${{ matrix.python-version }} | |
15 | uses: actions/setup-python@v2 | |
16 | with: | |
17 | python-version: '3.x' | |
18 | - name: Install dependencies | |
19 | run: | | |
20 | python -m pip install --upgrade pip | |
21 | python -m pip install flake8 black mypy | |
22 | - name: Lint with flake8 | |
23 | run: | | |
24 | flake8 unpaddedbase64/ tests/ | |
25 | - name: Lint with black | |
26 | run: | | |
27 | black --check --diff unpaddedbase64/ tests/ | |
28 | - name: Lint with mypy | |
29 | run: | | |
30 | mypy --strict unpaddedbase64/ tests/ | |
31 | ||
32 | test: | |
33 | needs: lint | |
34 | runs-on: ubuntu-latest | |
35 | strategy: | |
36 | matrix: | |
37 | python-version: ['3.x', '3.6', 'pypy-3.6'] | |
38 | ||
39 | steps: | |
40 | - uses: actions/checkout@v2 | |
41 | - name: Set up Python ${{ matrix.python-version }} | |
42 | uses: actions/setup-python@v2 | |
43 | with: | |
44 | python-version: ${{ matrix.python-version }} | |
45 | - name: Test with unittest | |
46 | run: | | |
47 | python -m unittest --verbose |
0 | 0 | .coverage |
1 | 1 | .tox/ |
2 | 2 | __pycache__/ |
3 | unpaddedbase64.egg-info/ | |
4 | unpaddedbase64.pyc | |
5 | build/ | |
6 | 3 | dist/ |
4 | poetry.lock |
0 | language: python | |
1 | env: | |
2 | - TOXENV=packaging | |
3 | - TOXENV=pep8 | |
4 | - TOXENV=py3pep8 | |
5 | - TOXENV=py27 | |
6 | - TOXENV=py33 | |
7 | - TOXENV=py34 | |
8 | - TOXENV=pypy | |
9 | ||
10 | install: | |
11 | - pip install tox | |
12 | ||
13 | script: | |
14 | - tox |
0 | 0 | Unpadded Base64 |
1 | 1 | =============== |
2 | ||
3 | .. image:: https://img.shields.io/pypi/v/unpaddedbase64.svg | |
4 | :target: https://pypi.python.org/pypi/unpaddedbase64/ | |
5 | :alt: Latest Version | |
6 | ||
7 | .. image:: https://img.shields.io/travis/matrix-org/python-unpaddedbase64.svg | |
8 | :target: https://travis-ci.org/matrix-org/python-unpaddedbase64 | |
9 | 2 | |
10 | 3 | Encode and decode Base64 without "=" padding. |
11 | 4 | |
12 | 5 | `RFC 4648`_ specifies that Base64 should be padded to a multiple of 4 bytes |
13 | using "=" characters. However this conveys no benefit so many protocols choose | |
14 | to use Base64 without the "=" padding. | |
6 | using "=" characters. However many protocols choose to omit the "=" padding. | |
15 | 7 | |
16 | 8 | .. _`RFC 4648`: https://tools.ietf.org/html/rfc4648 |
17 | 9 | |
20 | 12 | |
21 | 13 | .. code:: bash |
22 | 14 | |
23 | pip install unpaddedbase64 | |
15 | python3 -m pip install unpaddedbase64 | |
24 | 16 | |
25 | 17 | Using |
26 | 18 | ----- |
28 | 20 | .. code:: python |
29 | 21 | |
30 | 22 | import unpaddedbase64 |
31 | assert (unpaddedbase64.encode_base64(b'\x00')) == u'AA' | |
32 | assert (unpaddedbase64.decode_base64(u'AA')) == b'\x00' | |
23 | assert (unpaddedbase64.encode_base64(b'\x00')) == 'AA' | |
24 | assert (unpaddedbase64.decode_base64('AA')) == b'\x00' |
0 | [build-system] | |
1 | requires = ["poetry_core>=1.0.0"] | |
2 | build-backend = "poetry.core.masonry.api" | |
3 | ||
4 | [tool.poetry] | |
5 | name = "unpaddedbase64" | |
6 | version = "2.1.0" | |
7 | description = 'Encode and decode Base64 without "=" padding' | |
8 | license = "Apache-2.0" | |
9 | authors = [ "The Matrix.org Foundation C.I.C." ] | |
10 | readme = "README.rst" | |
11 | homepage = "https://github.com/matrix-org/python-unpaddedbase64" | |
12 | keywords = ["base64"] | |
13 | ||
14 | [tool.poetry.urls] | |
15 | "Issue Tracker" = "https://github.com/matrix-org/python-unpaddedbase64/issues" | |
16 | ||
17 | [tool.poetry.dependencies] | |
18 | python = "^3.6" | |
19 | ||
20 | [tool.poetry.dev-dependencies] | |
21 | black = "*" | |
22 | flake8 = "*" | |
23 | mypy = "*" |
0 | #!/usr/bin/env python | |
1 | ||
2 | # Copyright 2015 OpenMarket Ltd | |
3 | # | |
4 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | # you may not use this file except in compliance with the License. | |
6 | # You may obtain a copy of the License at | |
7 | # | |
8 | # http://www.apache.org/licenses/LICENSE-2.0 | |
9 | # | |
10 | # Unless required by applicable law or agreed to in writing, software | |
11 | # distributed under the License is distributed on an "AS IS" BASIS, | |
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | # See the License for the specific language governing permissions and | |
14 | # limitations under the License. | |
15 | ||
16 | from setuptools import setup | |
17 | from codecs import open | |
18 | import os | |
19 | ||
20 | here = os.path.abspath(os.path.dirname(__file__)) | |
21 | ||
22 | ||
23 | def read_file(path_segments): | |
24 | """Read a UTF-8 file from the package. Takes a list of strings to join to | |
25 | make the path""" | |
26 | file_path = os.path.join(here, *path_segments) | |
27 | with open(file_path, encoding="utf-8") as f: | |
28 | return f.read() | |
29 | ||
30 | ||
31 | def exec_file(path_segments, name): | |
32 | """Extract a constant from a python file by looking for a line defining | |
33 | the constant and executing it.""" | |
34 | result = {} | |
35 | code = read_file(path_segments) | |
36 | lines = [line for line in code.split('\n') if line.startswith(name)] | |
37 | exec("\n".join(lines), result) | |
38 | return result[name] | |
39 | ||
40 | ||
41 | setup( | |
42 | name="unpaddedbase64", | |
43 | version=exec_file(("unpaddedbase64.py",), "__version__"), | |
44 | py_modules=["unpaddedbase64"], | |
45 | description="Unpadded Base64", | |
46 | long_description=read_file(("README.rst",)), | |
47 | keywords="base64", | |
48 | ) |
0 | # Copyright 2015 OpenMarket Ltd | |
1 | # | |
2 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
3 | # you may not use this file except in compliance with the License. | |
4 | # You may obtain a copy of the License at | |
5 | # | |
6 | # http://www.apache.org/licenses/LICENSE-2.0 | |
7 | # | |
8 | # Unless required by applicable law or agreed to in writing, software | |
9 | # distributed under the License is distributed on an "AS IS" BASIS, | |
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
11 | # See the License for the specific language governing permissions and | |
12 | # limitations under the License. | |
13 | ||
14 | from unpaddedbase64 import encode_base64, decode_base64 | |
15 | import unittest | |
16 | ||
17 | ||
18 | class TestUnpaddedBase64(unittest.TestCase): | |
19 | ||
20 | def test_encode(self): | |
21 | self.assertEqual(encode_base64(b''), u'') | |
22 | self.assertEqual(encode_base64(b'\x00'), u'AA') | |
23 | self.assertEqual(encode_base64(b'\x00\x00'), u'AAA') | |
24 | self.assertEqual(encode_base64(b'\x00\x00\x00'), u'AAAA') | |
25 | ||
26 | def test_decode(self): | |
27 | self.assertEqual(decode_base64(u''), b'') | |
28 | self.assertEqual(decode_base64(u'AA'), b'\x00') | |
29 | self.assertEqual(decode_base64(u'AAA'), b'\x00\x00') | |
30 | self.assertEqual(decode_base64(u'AAAA'), b'\x00\x00\x00') | |
31 | with self.assertRaises(Exception): | |
32 | decode_base64(u'A') | |
33 | ||
34 | def test_encode_urlunsafe_chars(self): | |
35 | self.assertEqual(encode_base64(b'\xff\xe6\x9a'), u'/+aa') | |
36 | self.assertEqual(encode_base64(b'\xff\xe6\x9a', True), u'_-aa') | |
37 | ||
38 | def test_decode_urlunsafe_chars(self): | |
39 | self.assertEqual(decode_base64(u'/+aa'), b'\xff\xe6\x9a') | |
40 | self.assertEqual(decode_base64(u'_-aa'), b'\xff\xe6\x9a') |
0 | # Copyright 2015 OpenMarket Ltd | |
1 | # Copyright 2021 The Matrix.org Foundation C.I.C. | |
2 | # | |
3 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | # you may not use this file except in compliance with the License. | |
5 | # You may obtain a copy of the License at | |
6 | # | |
7 | # http://www.apache.org/licenses/LICENSE-2.0 | |
8 | # | |
9 | # Unless required by applicable law or agreed to in writing, software | |
10 | # distributed under the License is distributed on an "AS IS" BASIS, | |
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | # See the License for the specific language governing permissions and | |
13 | # limitations under the License. | |
14 | ||
15 | from unpaddedbase64 import encode_base64, decode_base64 | |
16 | import unittest | |
17 | ||
18 | ||
19 | class TestUnpaddedBase64(unittest.TestCase): | |
20 | def test_encode(self) -> None: | |
21 | self.assertEqual(encode_base64(b""), "") | |
22 | self.assertEqual(encode_base64(b"\x00"), "AA") | |
23 | self.assertEqual(encode_base64(b"\x00\x00"), "AAA") | |
24 | self.assertEqual(encode_base64(b"\x00\x00\x00"), "AAAA") | |
25 | ||
26 | def test_decode(self) -> None: | |
27 | self.assertEqual(decode_base64(""), b"") | |
28 | self.assertEqual(decode_base64("AA"), b"\x00") | |
29 | self.assertEqual(decode_base64("AAA"), b"\x00\x00") | |
30 | self.assertEqual(decode_base64("AAAA"), b"\x00\x00\x00") | |
31 | with self.assertRaises(Exception): | |
32 | decode_base64("A") | |
33 | ||
34 | def test_encode_urlunsafe_chars(self) -> None: | |
35 | self.assertEqual(encode_base64(b"\xff\xe6\x9a"), "/+aa") | |
36 | self.assertEqual(encode_base64(b"\xff\xe6\x9a", True), "_-aa") | |
37 | ||
38 | def test_decode_urlunsafe_chars(self) -> None: | |
39 | self.assertEqual(decode_base64("/+aa"), b"\xff\xe6\x9a") | |
40 | self.assertEqual(decode_base64("_-aa"), b"\xff\xe6\x9a") |
0 | [tox] | |
1 | envlist = packaging, pep8, py3pep8, py27, py33, py34, pypy | |
2 | ||
3 | [testenv] | |
4 | deps = | |
5 | coverage | |
6 | pytest | |
7 | commands = | |
8 | coverage run --source unpaddedbase64 -m pytest | |
9 | coverage report -m --fail-under 100 | |
10 | ||
11 | [testenv:packaging] | |
12 | deps = | |
13 | check-manifest | |
14 | commands = check-manifest | |
15 | ||
16 | [testenv:pep8] | |
17 | basepython = python2.7 | |
18 | deps = | |
19 | flake8 | |
20 | commands = flake8 . | |
21 | ||
22 | [testenv:py3pep8] | |
23 | basepython = python3.4 | |
24 | deps = | |
25 | flake8 | |
26 | commands = flake8 . |
0 | # Copyright 2014, 2015 OpenMarket Ltd | |
1 | # Copyright 2021 The Matrix.org Foundation C.I.C. | |
2 | # | |
3 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | # you may not use this file except in compliance with the License. | |
5 | # You may obtain a copy of the License at | |
6 | # | |
7 | # http://www.apache.org/licenses/LICENSE-2.0 | |
8 | # | |
9 | # Unless required by applicable law or agreed to in writing, software | |
10 | # distributed under the License is distributed on an "AS IS" BASIS, | |
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | # See the License for the specific language governing permissions and | |
13 | # limitations under the License. | |
14 | ||
15 | import base64 | |
16 | ||
17 | ||
18 | def encode_base64(input_bytes: bytes, urlsafe: bool = False) -> str: | |
19 | """Encode bytes as an unpadded base64 string.""" | |
20 | ||
21 | if urlsafe: | |
22 | encode = base64.urlsafe_b64encode | |
23 | else: | |
24 | encode = base64.b64encode | |
25 | ||
26 | output_bytes = encode(input_bytes) | |
27 | output_string = output_bytes.decode("ascii") | |
28 | return output_string.rstrip("=") | |
29 | ||
30 | ||
31 | def decode_base64(input_string: str) -> bytes: | |
32 | """Decode an unpadded standard or urlsafe base64 string to bytes.""" | |
33 | ||
34 | input_bytes = input_string.encode("ascii") | |
35 | input_len = len(input_bytes) | |
36 | padding = b"=" * (3 - ((input_len + 3) % 4)) | |
37 | ||
38 | # Passing altchars here allows decoding both standard and urlsafe base64 | |
39 | output_bytes = base64.b64decode(input_bytes + padding, altchars=b"-_") | |
40 | return output_bytes |
0 | # Copyright 2014, 2015 OpenMarket Ltd | |
1 | # | |
2 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
3 | # you may not use this file except in compliance with the License. | |
4 | # You may obtain a copy of the License at | |
5 | # | |
6 | # http://www.apache.org/licenses/LICENSE-2.0 | |
7 | # | |
8 | # Unless required by applicable law or agreed to in writing, software | |
9 | # distributed under the License is distributed on an "AS IS" BASIS, | |
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
11 | # See the License for the specific language governing permissions and | |
12 | # limitations under the License. | |
13 | ||
14 | import base64 | |
15 | ||
16 | __version__ = "1.1.0" | |
17 | ||
18 | ||
19 | def encode_base64(input_bytes, urlsafe=False): | |
20 | """Encode bytes as a base64 string without any padding.""" | |
21 | ||
22 | encode = base64.urlsafe_b64encode if urlsafe else base64.b64encode | |
23 | output_bytes = encode(input_bytes) | |
24 | output_string = output_bytes.decode("ascii") | |
25 | return output_string.rstrip(u"=") | |
26 | ||
27 | ||
28 | def decode_base64(input_string): | |
29 | """Decode a base64 string to bytes inferring padding from the length of the | |
30 | string.""" | |
31 | ||
32 | input_bytes = input_string.encode("ascii") | |
33 | input_len = len(input_bytes) | |
34 | padding = b"=" * (3 - ((input_len + 3) % 4)) | |
35 | decode = base64.b64decode | |
36 | if u'-' in input_string or u'_' in input_string: | |
37 | decode = base64.urlsafe_b64decode | |
38 | output_bytes = decode(input_bytes + padding) | |
39 | return output_bytes |