mirror of
https://github.com/scito/extract_otp_secrets.git
synced 2025-12-14 19:01:03 +01:00
Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a822abbba1 | ||
|
|
1b11c4ccb5 | ||
|
|
46dda83624 | ||
|
|
259273ab16 | ||
|
|
ab878ad737 | ||
|
|
fa9324513d | ||
|
|
16aa2ddf8c | ||
|
|
3fb41a4349 | ||
|
|
7484bbe1b6 | ||
|
|
14d86db936 | ||
|
|
b4790b926a | ||
|
|
66545ac1d3 | ||
|
|
b41250c23a | ||
|
|
4e15725c4d | ||
|
|
d8545ea22b | ||
|
|
1f8d9d171b | ||
|
|
0fc8342dd0 | ||
|
|
d2bf496b2b | ||
|
|
0854a70036 | ||
|
|
f9ce96fb57 | ||
|
|
e676bb7ea7 | ||
|
|
153b1d92c0 | ||
|
|
c8cf5ba12b | ||
|
|
1ba64e6efe | ||
|
|
0ba76da085 | ||
|
|
578eda8744 | ||
|
|
b548908014 | ||
|
|
c730388fd6 | ||
|
|
d387522d1b | ||
|
|
47da32cd22 | ||
|
|
7a45e9a444 | ||
|
|
44ba0a966e | ||
|
|
2ee5480fc8 | ||
|
|
8eb0ca2043 | ||
|
|
35f63099c9 | ||
|
|
7362d80e3d | ||
|
|
18d4992afb | ||
|
|
2849dda044 | ||
|
|
5aaa8b24fc | ||
|
|
c81cd6b87d | ||
|
|
3d2fcae6dc | ||
|
|
85d73e347c | ||
|
|
6dfc23ef77 | ||
|
|
23f708a1d0 | ||
|
|
3d8bda5c41 | ||
|
|
f3f3988c59 | ||
|
|
8f0461f62c | ||
|
|
95f99df3fe | ||
|
|
340c569635 | ||
|
|
157e247416 | ||
|
|
a0bf28f4cc | ||
|
|
fd8b165212 | ||
|
|
a467955b13 | ||
|
|
eea0179b5e | ||
|
|
d20d709d6e | ||
|
|
a0c21273e8 | ||
|
|
c7ab0b8ef4 | ||
|
|
8e70ae9da9 | ||
|
|
511bb4a91c | ||
|
|
15cbd77b07 | ||
|
|
2610afe5d8 | ||
|
|
8a4e2e3641 | ||
|
|
a0cf4246c1 | ||
|
|
b3c0912e1f | ||
|
|
1d8b49efcc | ||
|
|
f846ee40af | ||
|
|
f8b0283bdd | ||
|
|
bcbf189289 | ||
|
|
7c295e0963 | ||
|
|
6b72fad3c7 | ||
|
|
c937bede32 | ||
|
|
7402263dfe | ||
|
|
b721571101 | ||
|
|
72bac4d951 | ||
|
|
6c16d28194 | ||
|
|
87d2d4a05d | ||
|
|
ad3f184a56 | ||
|
|
994f96f749 | ||
|
|
8177a97d39 | ||
|
|
0c0ac817b1 | ||
|
|
5133711179 | ||
|
|
5c02e7d478 | ||
|
|
6932793236 | ||
|
|
9c3edea75c | ||
|
|
0ec1314b3d | ||
|
|
414e80c469 | ||
|
|
7f6959783f | ||
|
|
419f65fdea | ||
|
|
9783a5f4f2 | ||
|
|
eccb1948c7 | ||
|
|
01a38e570c | ||
|
|
91b9490afb |
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.x", "3.11", "3.10", "3.9", "3.8", "3.7"]
|
||||
python-version: ["3.12", "3.11", "3.10", "3.9", "3.8"]
|
||||
platform: [ubuntu-latest, macos-latest, windows-latest]
|
||||
# exclude:
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
check-latest: false
|
||||
check-latest: ${{ github.event_name == 'schedule' }}
|
||||
- name: Install zbar shared lib for QReader (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
@@ -60,8 +60,7 @@ jobs:
|
||||
if: matrix.python-version == '3.x' && matrix.platform == 'ubuntu-latest'
|
||||
- name: Test with pytest
|
||||
run: pytest
|
||||
if: (matrix.python-version != '3.x' || matrix.platform != 'ubuntu-latest')
|
||||
# && matrix.platform != 'macos-latest'
|
||||
if: (matrix.python-version != '3.x' || matrix.platform != 'ubuntu-latest') && (matrix.python-version != '3.10' && matrix.platform != 'macos-latest')
|
||||
- name: Test with pytest (with code coverage)
|
||||
run: pytest --cov=extract_otp_secrets_test --junitxml=pytest.xml --cov-report=term-missing | tee pytest-coverage.txt
|
||||
if: matrix.python-version == '3.x' && matrix.platform == 'ubuntu-latest'
|
||||
|
||||
29
.github/workflows/ci_docker.yml
vendored
29
.github/workflows/ci_docker.yml
vendored
@@ -25,7 +25,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build-and-push-docker-debian-image:
|
||||
name: Build Docker Bullseye image and push to repositories
|
||||
name: Build Docker Bookworm image and push to repositories
|
||||
# run only when code is compiling and tests are passing
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -82,12 +82,14 @@ jobs:
|
||||
file: docker/Dockerfile
|
||||
# builder: ${{ steps.buildx.outputs.name }}
|
||||
# Note: tags has to be all lower-case
|
||||
build-args: |
|
||||
BASE_IMAGE=python:3.12-slim-bookworm
|
||||
pull: true
|
||||
tags: |
|
||||
scit0/extract_otp_secrets:latest
|
||||
scit0/extract_otp_secrets:bullseye
|
||||
scit0/extract_otp_secrets:bookworm
|
||||
ghcr.io/scito/extract_otp_secrets:latest
|
||||
ghcr.io/scito/extract_otp_secrets:bullseye
|
||||
ghcr.io/scito/extract_otp_secrets:bookworm
|
||||
# build on feature branches, push only on master branch
|
||||
push: ${{ github.ref == 'refs/heads/master' && github.secret_source == 'Actions'}}
|
||||
|
||||
@@ -98,7 +100,7 @@ jobs:
|
||||
echo "${{ steps.docker_build_qr_reader_latest.outputs.digest }}" > digests.txt
|
||||
- name: Save docker digests as artifacts
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: debian_digests
|
||||
path: digests.txt
|
||||
@@ -174,13 +176,13 @@ jobs:
|
||||
|
||||
- name: Save docker digests as artifacts
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: alpine_digests
|
||||
path: digests.txt
|
||||
|
||||
build-and-push-docker-buster-image:
|
||||
name: Build Docker Buster image (for PyInstsaller) and push to repositories
|
||||
build-and-push-docker-bullseye-image:
|
||||
name: Build Docker Bullseye image (for PyInstsaller) and push to repositories
|
||||
# run only when code is compiling and tests are passing
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -226,23 +228,22 @@ jobs:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GHCR_IO_TOKEN }}
|
||||
|
||||
- name: "Build image from Buster and push to GitHub Container Registry"
|
||||
id: docker_build_buster
|
||||
- name: "Build image from Bullseye and push to GitHub Container Registry"
|
||||
id: docker_build_bullseye
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
# relative path to the place where source code with Dockerfile is located
|
||||
# TODO file:, move to docker/
|
||||
context: .
|
||||
file: docker/Dockerfile
|
||||
# builder: ${{ steps.buildx.outputs.name }}
|
||||
build-args: |
|
||||
BASE_IMAGE=python:3.11-slim-buster
|
||||
BASE_IMAGE=python:3.12-slim-bullseye
|
||||
# Note: tags has to be all lower-case
|
||||
pull: true
|
||||
tags: |
|
||||
scit0/extract_otp_secrets:buster
|
||||
scit0/extract_otp_secrets:bullseye
|
||||
push: ${{ github.secret_source == 'Actions' }}
|
||||
|
||||
- name: Image digest
|
||||
@@ -252,7 +253,7 @@ jobs:
|
||||
echo "${{ steps.docker_build_qr_reader_latest.outputs.digest }}" > digests.txt
|
||||
- name: Save docker digests as artifacts
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: buster_digests
|
||||
name: bullseye_digests
|
||||
path: digests.txt
|
||||
|
||||
43
.github/workflows/ci_release.yml
vendored
43
.github/workflows/ci_release.yml
vendored
@@ -26,7 +26,8 @@ name: release
|
||||
|
||||
# Build matrix:
|
||||
# - Linux x86_64 glibc 2.35: ubuntu-latest
|
||||
# - Linux x86_64 glibc 2.34: extract_otp_secrets:buster
|
||||
# - Linux x86_64 glibc 2.31: extract_otp_secrets:bullseye
|
||||
# - Linux x86_64 glibc 2.36: extract_otp_secrets:bookworm
|
||||
# - Windows x86_64: windows-latest
|
||||
# - MacOS x86_64: macos-11
|
||||
# - Linux x86_64 glibc 2.28: extract_otp_secrets:buster
|
||||
@@ -87,19 +88,19 @@ jobs:
|
||||
https://api.github.com/repos/scito/extract_otp_secrets/releases \
|
||||
--silent \
|
||||
--show-error \
|
||||
-d '{"tag_name":"${{ github.ref }}","target_commitish":"master","name":"${{ steps.meta.outputs.version }} - ${{ steps.meta.outputs.date }}","body":"${{ steps.meta.outputs.tag_message }}\n\n## Executables\n\nDownload the executable for your platform and execute it, see [README.md](https://github.com/scito/extract_otp_secrets#readme)\n\n | Executable | Description |\n | --- | --- |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_linux_x86_64 | Linux x86_64/amd64 (glibc >= 2.28) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_linux_arm64 | Linux arm64 (glibc >= 2.28) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_win_x86_64.exe | Windows x86_64/amd64/x64 |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_win_arm64.exe | N/A |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_macos_x86_64.dmg | N/A, see [README.md](https://github.com/scito/extract_otp_secrets#readme) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_macos_x86_64.pkg | N/A, see [README.md](https://github.com/scito/extract_otp_secrets#readme) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_macos_x86_64 | MacOS x86_64/amd64 (bare executable, see [README.md](https://github.com/scito/extract_otp_secrets#readme); optional libzbar must be installed manually, see [README.md](https://github.com/scito/extract_otp_secrets#readme)) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_macos_arm64 | N/A |\n","draft":true,"prerelease":false,"generate_release_notes":true}')
|
||||
-d '{"tag_name":"${{ github.ref }}","target_commitish":"master","name":"${{ steps.meta.outputs.version }} - ${{ steps.meta.outputs.date }}","body":"${{ steps.meta.outputs.tag_message }}\n\n## Executables\n\nDownload the executable for your platform and execute it, see [README.md](https://github.com/scito/extract_otp_secrets#readme)\n\n | Executable | Description |\n | --- | --- |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_linux_x86_64 | Linux x86_64/amd64 (glibc >= 2.31) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_linux_arm64 | Linux arm64 (glibc >= 2.31) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_win_x86_64.exe | Windows x86_64/amd64/x64 |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_win_arm64.exe | N/A |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_macos_x86_64.dmg | N/A, see [README.md](https://github.com/scito/extract_otp_secrets#readme) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_macos_x86_64.pkg | N/A, see [README.md](https://github.com/scito/extract_otp_secrets#readme) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_macos_x86_64 | MacOS x86_64/amd64 (bare executable, see [README.md](https://github.com/scito/extract_otp_secrets#readme); optional libzbar must be installed manually, see [README.md](https://github.com/scito/extract_otp_secrets#readme)) |\n | extract_otp_secrets${{ steps.meta.outputs.inline_version }}_macos_arm64 | N/A |\n","draft":true,"prerelease":false,"generate_release_notes":true}')
|
||||
echo upload_url=$(jq '.upload_url' <<< "$response") >> $GITHUB_OUTPUT
|
||||
echo $(jq -r '.upload_url' <<< "$response") > release_url.txt
|
||||
echo $(jq -r '.id' <<< "$response") > release_id.txt
|
||||
- name: Save Release URL File for publish
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release_url
|
||||
path: release_url.txt
|
||||
- name: Save asset upload id for publish
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release_id
|
||||
path: release_id.txt
|
||||
@@ -164,7 +165,7 @@ jobs:
|
||||
- name: Image digest
|
||||
# TODO upload digests to assets
|
||||
run: |
|
||||
echo "extract_otp_secrets: ${{ steps.docker_build_buster.outputs.digest }}"
|
||||
echo "extract_otp_secrets: ${{ steps.docker_build_bullseye.outputs.digest }}"
|
||||
|
||||
# TODO use local docker image https://stackoverflow.com/a/61155718/1663871
|
||||
# https://github.com/multiarch/qemu-user-static
|
||||
@@ -172,13 +173,14 @@ jobs:
|
||||
- name: Run Pyinstaller in container for ${{ matrix.EXE }}
|
||||
run: |
|
||||
docker run --pull always --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
docker run --platform ${{ matrix.PLATFORM }} --pull always --entrypoint /bin/bash --rm -v "$(pwd)":/files -w /files scit0/extract_otp_secrets:buster -c 'apt-get update && apt-get -y install binutils && pip install -U -r /files/requirements.txt && pip install pyinstaller && PYTHONHASHSEED=31 && pyinstaller -y --add-data /usr/local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile --name ${{ matrix.EXE }} --distpath /files/dist/ /files/src/extract_otp_secrets.py'
|
||||
docker run --platform ${{ matrix.PLATFORM }} --pull always --entrypoint /bin/bash --rm -v "$(pwd)":/files -w /files scit0/extract_otp_secrets:bullseye -c 'apt-get update && apt-get -y install binutils && pip install -U -r /files/requirements.txt && pip install pyinstaller && PYTHONHASHSEED=31 && pyinstaller -y --add-data /usr/local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile --name ${{ matrix.EXE }} --distpath /files/dist/ /files/src/extract_otp_secrets.py'
|
||||
|
||||
- name: Smoke tests ${{ matrix.PLATFORM }}
|
||||
- name: Smoke tests linux/amd64
|
||||
if: matrix.PLATFORM == 'linux/amd64'
|
||||
run: |
|
||||
dist/${{ matrix.EXE }} -V
|
||||
dist/${{ matrix.EXE }} -h
|
||||
dist/${{ matrix.EXE }} --debug
|
||||
dist/${{ matrix.EXE }} example_export.png
|
||||
dist/${{ matrix.EXE }} - < example_export.txt
|
||||
dist/${{ matrix.EXE }} --qr ZBAR example_export.png
|
||||
@@ -186,19 +188,19 @@ jobs:
|
||||
dist/${{ matrix.EXE }} --qr QREADER_DEEP example_export.png
|
||||
dist/${{ matrix.EXE }} --qr CV2 example_export.png
|
||||
dist/${{ matrix.EXE }} --qr CV2_WECHAT example_export.png
|
||||
- name: Smoke tests ${{ matrix.PLATFORM }}
|
||||
- name: Smoke tests linux/arm64
|
||||
if: matrix.PLATFORM == 'linux/arm64'
|
||||
run: |
|
||||
docker run --platform ${{ matrix.PLATFORM }} --pull always --entrypoint /bin/bash --rm -v "$(pwd)":/files -w /files scit0/extract_otp_secrets -c 'dist/${{ matrix.EXE }} -V && dist/${{ matrix.EXE }} -h && dist/${{ matrix.EXE }} example_export.png && dist/${{ matrix.EXE }} - < example_export.txt && dist/${{ matrix.EXE }} --qr ZBAR example_export.png && dist/${{ matrix.EXE }} --qr QREADER example_export.png && dist/${{ matrix.EXE }} --qr QREADER_DEEP example_export.png && dist/${{ matrix.EXE }} --qr CV2 example_export.png && dist/${{ matrix.EXE }} --qr CV2_WECHAT example_export.png'
|
||||
- name: Load Release URL File from release job
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: release_url
|
||||
- name: Display structure of files
|
||||
run: ls -R
|
||||
- name: Upload EXE to artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.EXE }}
|
||||
path: dist/${{ matrix.EXE }}
|
||||
@@ -236,8 +238,8 @@ jobs:
|
||||
ASSET_MIME: application/vnd.microsoft.portable-executable
|
||||
UPLOAD: true
|
||||
CMD_BUILD: |
|
||||
pyinstaller -y --add-data "$($Env:pythonLocation)\__yolo_v3_qr_detector;__yolo_v3_qr_detector" --add-binary "$($Env:pythonLocation)\Lib\site-packages\pyzbar\libiconv.dll;pyzbar" --add-binary "$($Env:pythonLocation)\Lib\site-packages\pyzbar\libzbar-64.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\msvcr120.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\msvcp120.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\vcamp120.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\vcomp120.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\vccorlib120.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120u.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120chs.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120cht.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120deu.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120enu.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120esn.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120fra.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120ita.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120jpn.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120kor.dll;pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120rus.dll;pyzbar" --onefile --version-file build\win_file_version_info.txt --name extract_otp_secrets.exe src\extract_otp_secrets.py
|
||||
- os: macos-11
|
||||
pyinstaller -y --add-data "$($Env:pythonLocation)\__yolo_v3_qr_detector:__yolo_v3_qr_detector" --add-binary "$($Env:pythonLocation)\Lib\site-packages\pyzbar\libiconv.dll:pyzbar" --add-binary "$($Env:pythonLocation)\Lib\site-packages\pyzbar\libzbar-64.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\msvcr120.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\msvcp120.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\vcamp120.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\vcomp120.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\vccorlib120.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120u.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120chs.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120cht.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120deu.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120enu.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120esn.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120fra.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120ita.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120jpn.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120kor.dll:pyzbar" --add-binary "$($Env:WinDir)\system32\mfc120rus.dll:pyzbar" --onefile --version-file build\win_file_version_info.txt --name extract_otp_secrets.exe src\extract_otp_secrets.py
|
||||
- os: macos-12
|
||||
TARGET: macos
|
||||
# https://pyinstaller.org/en/stable/spec-files.html#spec-file-options-for-a-macos-bundle
|
||||
EXE: extract_otp_secrets
|
||||
@@ -268,11 +270,11 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set macos macos_python_path
|
||||
# TODO use variable for Python version
|
||||
run: echo "macos_python_path=/Library/Frameworks/Python.framework/Versions/3.11" >> $GITHUB_ENV
|
||||
- name: Set up Python 3.11
|
||||
run: echo "macos_python_path=/Library/Frameworks/Python.framework/Versions/3.12" >> $GITHUB_ENV
|
||||
- name: Set up Python 3.12
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.11
|
||||
python-version: 3.12
|
||||
check-latest: true
|
||||
- name: Install zbar shared lib for QReader (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
@@ -302,6 +304,7 @@ jobs:
|
||||
run: |
|
||||
dist/${{ matrix.EXE }} -V
|
||||
dist/${{ matrix.EXE }} -h
|
||||
dist/${{ matrix.EXE }} --debug
|
||||
dist/${{ matrix.EXE }} example_export.png
|
||||
dist/${{ matrix.EXE }} --qr ZBAR example_export.png
|
||||
dist/${{ matrix.EXE }} --qr QREADER example_export.png
|
||||
@@ -314,12 +317,12 @@ jobs:
|
||||
dist/${{ matrix.EXE }} - < example_export.txt
|
||||
- name: Load Release URL File from release job
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: release_url
|
||||
- name: Load Release Id File from release job
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: release_id
|
||||
- name: Display structure of files
|
||||
@@ -332,12 +335,12 @@ jobs:
|
||||
echo "release_id=$(cat release_id.txt)" >> $GITHUB_OUTPUT
|
||||
echo "upload_url=https://uploads.github.com/repos/scito/extract_otp_secrets/releases/$(cat release_id.txt)/assets?name=" >> $GITHUB_OUTPUT
|
||||
- name: Upload EXE to artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.EXE }}
|
||||
path: dist/${{ matrix.EXE }}
|
||||
- name: Upload DMG to artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
if: runner.os == 'macOS'
|
||||
with:
|
||||
name: ${{ matrix.DMG }}
|
||||
@@ -362,7 +365,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Load Release Id File from release job
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: release_id
|
||||
- name: Set meta data
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -27,6 +27,11 @@ file_version_info.txt
|
||||
assets/*
|
||||
extract_otp_secrets_linux_arm64.spec
|
||||
extract_otp_secrets_linux_x86_64_bullseye.spec
|
||||
extract_otp_secrets_linux_x86_64_bookworm.spec
|
||||
extract_otp_secrets_linux_x86_64.spec
|
||||
extract_otp_secrets.spec
|
||||
test.txt
|
||||
extract_otp_secrets.build/
|
||||
extract_otp_secrets.dist/
|
||||
extract_otp_secrets.onefile-build/
|
||||
extract_otp_secrets.bin
|
||||
|
||||
2
Pipfile
2
Pipfile
@@ -7,7 +7,6 @@ name = "pypi"
|
||||
colorama = ">=0.4.6"
|
||||
opencv-contrib-python = "*"
|
||||
# for macOS: opencv-contrib-python = "<=4.7.0"
|
||||
# for PYTHON <= 3.7: typing_extensions = "*"
|
||||
pillow = "*"
|
||||
pyzbar = "*"
|
||||
protobuf = "*"
|
||||
@@ -20,6 +19,7 @@ flake8 = "*"
|
||||
gfm-toc = "*"
|
||||
mypy = "*"
|
||||
mypy-protobuf = "*"
|
||||
nuitka = "*"
|
||||
pylint = "*"
|
||||
pytest = "*"
|
||||
pytest-cov = "*"
|
||||
|
||||
818
Pipfile.lock
generated
818
Pipfile.lock
generated
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "42b14c5eae25b0924354520fe0a26a8d826c905f4613d717f3bfa52e98ed5e8e"
|
||||
"sha256": "d9664aaa55d180a006624f7c65977a97f23b7c25444e2b2abe1f85ceb0e3337b"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@@ -22,176 +22,170 @@
|
||||
"sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'",
|
||||
"version": "==0.4.6"
|
||||
},
|
||||
"numpy": {
|
||||
"hashes": [
|
||||
"sha256:003a9f530e880cb2cd177cba1af7220b9aa42def9c4afc2a2fc3ee6be7eb2b22",
|
||||
"sha256:150947adbdfeceec4e5926d956a06865c1c690f2fd902efede4ca6fe2e657c3f",
|
||||
"sha256:2620e8592136e073bd12ee4536149380695fbe9ebeae845b81237f986479ffc9",
|
||||
"sha256:2eabd64ddb96a1239791da78fa5f4e1693ae2dadc82a76bc76a14cbb2b966e96",
|
||||
"sha256:4173bde9fa2a005c2c6e2ea8ac1618e2ed2c1c6ec8a7657237854d42094123a0",
|
||||
"sha256:4199e7cfc307a778f72d293372736223e39ec9ac096ff0a2e64853b866a8e18a",
|
||||
"sha256:4cecaed30dc14123020f77b03601559fff3e6cd0c048f8b5289f4eeabb0eb281",
|
||||
"sha256:557d42778a6869c2162deb40ad82612645e21d79e11c1dc62c6e82a2220ffb04",
|
||||
"sha256:63e45511ee4d9d976637d11e6c9864eae50e12dc9598f531c035265991910468",
|
||||
"sha256:6524630f71631be2dabe0c541e7675db82651eb998496bbe16bc4f77f0772253",
|
||||
"sha256:76807b4063f0002c8532cfeac47a3068a69561e9c8715efdad3c642eb27c0756",
|
||||
"sha256:7de8fdde0003f4294655aa5d5f0a89c26b9f22c0a58790c38fae1ed392d44a5a",
|
||||
"sha256:889b2cc88b837d86eda1b17008ebeb679d82875022200c6e8e4ce6cf549b7acb",
|
||||
"sha256:92011118955724465fb6853def593cf397b4a1367495e0b59a7e69d40c4eb71d",
|
||||
"sha256:97cf27e51fa078078c649a51d7ade3c92d9e709ba2bfb97493007103c741f1d0",
|
||||
"sha256:9a23f8440561a633204a67fb44617ce2a299beecf3295f0d13c495518908e910",
|
||||
"sha256:a51725a815a6188c662fb66fb32077709a9ca38053f0274640293a14fdd22978",
|
||||
"sha256:a77d3e1163a7770164404607b7ba3967fb49b24782a6ef85d9b5f54126cc39e5",
|
||||
"sha256:adbdce121896fd3a17a77ab0b0b5eedf05a9834a18699db6829a64e1dfccca7f",
|
||||
"sha256:c29e6bd0ec49a44d7690ecb623a8eac5ab8a923bce0bea6293953992edf3a76a",
|
||||
"sha256:c72a6b2f4af1adfe193f7beb91ddf708ff867a3f977ef2ec53c0ffb8283ab9f5",
|
||||
"sha256:d0a2db9d20117bf523dde15858398e7c0858aadca7c0f088ac0d6edd360e9ad2",
|
||||
"sha256:e3ab5d32784e843fc0dd3ab6dcafc67ef806e6b6828dc6af2f689be0eb4d781d",
|
||||
"sha256:e428c4fbfa085f947b536706a2fc349245d7baa8334f0c5723c56a10595f9b95",
|
||||
"sha256:e8d2859428712785e8a8b7d2b3ef0a1d1565892367b32f915c4a4df44d0e64f5",
|
||||
"sha256:eef70b4fc1e872ebddc38cddacc87c19a3709c0e3e5d20bf3954c147b1dd941d",
|
||||
"sha256:f64bb98ac59b3ea3bf74b02f13836eb2e24e48e0ab0145bbda646295769bd780",
|
||||
"sha256:f9006288bcf4895917d02583cf3411f98631275bc67cce355a7f39f8c14338fa"
|
||||
"sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b",
|
||||
"sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818",
|
||||
"sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20",
|
||||
"sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0",
|
||||
"sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010",
|
||||
"sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a",
|
||||
"sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea",
|
||||
"sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c",
|
||||
"sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71",
|
||||
"sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110",
|
||||
"sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be",
|
||||
"sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a",
|
||||
"sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a",
|
||||
"sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5",
|
||||
"sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed",
|
||||
"sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd",
|
||||
"sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c",
|
||||
"sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e",
|
||||
"sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0",
|
||||
"sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c",
|
||||
"sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a",
|
||||
"sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b",
|
||||
"sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0",
|
||||
"sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6",
|
||||
"sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2",
|
||||
"sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a",
|
||||
"sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30",
|
||||
"sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218",
|
||||
"sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5",
|
||||
"sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07",
|
||||
"sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2",
|
||||
"sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4",
|
||||
"sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764",
|
||||
"sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef",
|
||||
"sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3",
|
||||
"sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"
|
||||
],
|
||||
"markers": "python_version >= '3.10'",
|
||||
"version": "==1.24.2"
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==1.26.4"
|
||||
},
|
||||
"opencv-contrib-python": {
|
||||
"hashes": [
|
||||
"sha256:1a48c2f24440cfd6e49c84dbe39c39feff5efbc90be8299c76e7141973d403b6",
|
||||
"sha256:2b8e3a1a7af31ebed28487d161ca4be0edd0b0e241667c6e9c842ac683313b2f",
|
||||
"sha256:2f0c32b0f2f55255632a44bdcfa185f88c7fb6d2616869942aff9d5a39df4997",
|
||||
"sha256:35e9a3809da10a47189c06d4d78b8e7821b9a3578dec8cbddf6ee1675bd83557",
|
||||
"sha256:3a00e12546e5578f6bb7ed408c37fcfea533d74e9691cfaf40926f6b43295577",
|
||||
"sha256:6d1c993811f92ddd7919314ada7b9be1f23db1c73f1384915c834dee8549c0b9",
|
||||
"sha256:7a08f9d1f9dd52de63a7bb448ab7d6d4a1a85b767c2358501d968d1e4d95098d",
|
||||
"sha256:7a75f1775790106e54bcfb101c0e00e1f801a57d9baebc82d0b6758fc83a4ca0",
|
||||
"sha256:86f4b60b9536948f16d2170ba3a9b22d3955a957dc61a9bc56e53692c6db2c7e",
|
||||
"sha256:9829e6efedde1d1b8419c5bd4d62d289ecbf44ae35b843c6da9e3cbcba1a9a8a",
|
||||
"sha256:abc6adfa8694f71a4caffa922b279bd9d96954a37eee40b147f613c64310b411",
|
||||
"sha256:b4033a164b2e2ea0049ba8c1194dab82dca680953ac36f33d1cc2c060906555f",
|
||||
"sha256:e3967b1f3d74b8c70be724dbc07921faec87e8806cc87b2db5e7057815d6a08c",
|
||||
"sha256:e770e9f653a0e5e72b973adb8213fae2df4642730ba1faf31e73a54287a4d5d4"
|
||||
"sha256:4ce33844dbdf4bcbb0bd1ea7249367ffccab82de09f531ad25ac258aca5f813c",
|
||||
"sha256:760e76c535da81e50f5a5a0acd85bada376f505736875eb446811b4b76fb9bb5",
|
||||
"sha256:86078d3653ec3107877536c9178622b1f98b51acf59e554ddbc552785cba55fa",
|
||||
"sha256:89ca1508dd895ae42176640bdd503cac82772f6efa25120738a469a6a69de321",
|
||||
"sha256:b52e381144f774b486729ccee69911bdc7d16b5ced4830502e906ad803373ab0",
|
||||
"sha256:fdd9b14028f74af8dbb69f90e6e4a956ce2eb5b59947df28ba0b79d337431477",
|
||||
"sha256:ff1c00b06e2c3f4ad47de64fa9c527d67f7c6fce93f513b64163d41bea7c41b2"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.7.0.68"
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==4.9.0.80"
|
||||
},
|
||||
"opencv-python": {
|
||||
"hashes": [
|
||||
"sha256:3a00e12546e5578f6bb7ed408c37fcfea533d74e9691cfaf40926f6b43295577",
|
||||
"sha256:6d1c993811f92ddd7919314ada7b9be1f23db1c73f1384915c834dee8549c0b9",
|
||||
"sha256:7a08f9d1f9dd52de63a7bb448ab7d6d4a1a85b767c2358501d968d1e4d95098d",
|
||||
"sha256:86f4b60b9536948f16d2170ba3a9b22d3955a957dc61a9bc56e53692c6db2c7e",
|
||||
"sha256:9829e6efedde1d1b8419c5bd4d62d289ecbf44ae35b843c6da9e3cbcba1a9a8a",
|
||||
"sha256:abc6adfa8694f71a4caffa922b279bd9d96954a37eee40b147f613c64310b411",
|
||||
"sha256:e770e9f653a0e5e72b973adb8213fae2df4642730ba1faf31e73a54287a4d5d4"
|
||||
"sha256:1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1",
|
||||
"sha256:3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0",
|
||||
"sha256:71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3",
|
||||
"sha256:7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a",
|
||||
"sha256:7e5f7aa4486651a6ebfa8ed4b594b65bd2d2f41beeb4241a3e4b1b85acbbbadb",
|
||||
"sha256:dcf000c36dd1651118a2462257e3a9e76db789a78432e1f303c7bac54f63ef6c",
|
||||
"sha256:e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==4.7.0.68"
|
||||
"version": "==4.9.0.80"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
"sha256:013016af6b3a12a2f40b704677f8b51f72cb007dac785a9933d5c86a72a7fe33",
|
||||
"sha256:0845adc64fe9886db00f5ab68c4a8cd933ab749a87747555cec1c95acea64b0b",
|
||||
"sha256:0884ba7b515163a1a05440a138adeb722b8a6ae2c2b33aea93ea3118dd3a899e",
|
||||
"sha256:09b89ddc95c248ee788328528e6a2996e09eaccddeeb82a5356e92645733be35",
|
||||
"sha256:0dd4c681b82214b36273c18ca7ee87065a50e013112eea7d78c7a1b89a739153",
|
||||
"sha256:0e51f608da093e5d9038c592b5b575cadc12fd748af1479b5e858045fff955a9",
|
||||
"sha256:0f3269304c1a7ce82f1759c12ce731ef9b6e95b6df829dccd9fe42912cc48569",
|
||||
"sha256:16a8df99701f9095bea8a6c4b3197da105df6f74e6176c5b410bc2df2fd29a57",
|
||||
"sha256:19005a8e58b7c1796bc0167862b1f54a64d3b44ee5d48152b06bb861458bc0f8",
|
||||
"sha256:1b4b4e9dda4f4e4c4e6896f93e84a8f0bcca3b059de9ddf67dac3c334b1195e1",
|
||||
"sha256:28676836c7796805914b76b1837a40f76827ee0d5398f72f7dcc634bae7c6264",
|
||||
"sha256:2968c58feca624bb6c8502f9564dd187d0e1389964898f5e9e1fbc8533169157",
|
||||
"sha256:3f4cc516e0b264c8d4ccd6b6cbc69a07c6d582d8337df79be1e15a5056b258c9",
|
||||
"sha256:3fa1284762aacca6dc97474ee9c16f83990b8eeb6697f2ba17140d54b453e133",
|
||||
"sha256:43521ce2c4b865d385e78579a082b6ad1166ebed2b1a2293c3be1d68dd7ca3b9",
|
||||
"sha256:451f10ef963918e65b8869e17d67db5e2f4ab40e716ee6ce7129b0cde2876eab",
|
||||
"sha256:46c259e87199041583658457372a183636ae8cd56dbf3f0755e0f376a7f9d0e6",
|
||||
"sha256:46f39cab8bbf4a384ba7cb0bc8bae7b7062b6a11cfac1ca4bc144dea90d4a9f5",
|
||||
"sha256:519e14e2c49fcf7616d6d2cfc5c70adae95682ae20f0395e9280db85e8d6c4df",
|
||||
"sha256:53dcb50fbdc3fb2c55431a9b30caeb2f7027fcd2aeb501459464f0214200a503",
|
||||
"sha256:54614444887e0d3043557d9dbc697dbb16cfb5a35d672b7a0fcc1ed0cf1c600b",
|
||||
"sha256:575d8912dca808edd9acd6f7795199332696d3469665ef26163cd090fa1f8bfa",
|
||||
"sha256:5dd5a9c3091a0f414a963d427f920368e2b6a4c2f7527fdd82cde8ef0bc7a327",
|
||||
"sha256:5f532a2ad4d174eb73494e7397988e22bf427f91acc8e6ebf5bb10597b49c493",
|
||||
"sha256:60e7da3a3ad1812c128750fc1bc14a7ceeb8d29f77e0a2356a8fb2aa8925287d",
|
||||
"sha256:653d7fb2df65efefbcbf81ef5fe5e5be931f1ee4332c2893ca638c9b11a409c4",
|
||||
"sha256:6663977496d616b618b6cfa43ec86e479ee62b942e1da76a2c3daa1c75933ef4",
|
||||
"sha256:6abfb51a82e919e3933eb137e17c4ae9c0475a25508ea88993bb59faf82f3b35",
|
||||
"sha256:6c6b1389ed66cdd174d040105123a5a1bc91d0aa7059c7261d20e583b6d8cbd2",
|
||||
"sha256:6d9dfb9959a3b0039ee06c1a1a90dc23bac3b430842dcb97908ddde05870601c",
|
||||
"sha256:765cb54c0b8724a7c12c55146ae4647e0274a839fb6de7bcba841e04298e1011",
|
||||
"sha256:7a21222644ab69ddd9967cfe6f2bb420b460dae4289c9d40ff9a4896e7c35c9a",
|
||||
"sha256:7ac7594397698f77bce84382929747130765f66406dc2cd8b4ab4da68ade4c6e",
|
||||
"sha256:7cfc287da09f9d2a7ec146ee4d72d6ea1342e770d975e49a8621bf54eaa8f30f",
|
||||
"sha256:83125753a60cfc8c412de5896d10a0a405e0bd88d0470ad82e0869ddf0cb3848",
|
||||
"sha256:847b114580c5cc9ebaf216dd8c8dbc6b00a3b7ab0131e173d7120e6deade1f57",
|
||||
"sha256:87708d78a14d56a990fbf4f9cb350b7d89ee8988705e58e39bdf4d82c149210f",
|
||||
"sha256:8a2b5874d17e72dfb80d917213abd55d7e1ed2479f38f001f264f7ce7bae757c",
|
||||
"sha256:8f127e7b028900421cad64f51f75c051b628db17fb00e099eb148761eed598c9",
|
||||
"sha256:94cdff45173b1919350601f82d61365e792895e3c3a3443cf99819e6fbf717a5",
|
||||
"sha256:99d92d148dd03fd19d16175b6d355cc1b01faf80dae93c6c3eb4163709edc0a9",
|
||||
"sha256:9a3049a10261d7f2b6514d35bbb7a4dfc3ece4c4de14ef5876c4b7a23a0e566d",
|
||||
"sha256:9d9a62576b68cd90f7075876f4e8444487db5eeea0e4df3ba298ee38a8d067b0",
|
||||
"sha256:9e5f94742033898bfe84c93c831a6f552bb629448d4072dd312306bab3bd96f1",
|
||||
"sha256:a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e",
|
||||
"sha256:a2e0f87144fcbbe54297cae708c5e7f9da21a4646523456b00cc956bd4c65815",
|
||||
"sha256:a4dfdae195335abb4e89cc9762b2edc524f3c6e80d647a9a81bf81e17e3fb6f0",
|
||||
"sha256:a96e6e23f2b79433390273eaf8cc94fec9c6370842e577ab10dabdcc7ea0a66b",
|
||||
"sha256:aabdab8ec1e7ca7f1434d042bf8b1e92056245fb179790dc97ed040361f16bfd",
|
||||
"sha256:b222090c455d6d1a64e6b7bb5f4035c4dff479e22455c9eaa1bdd4c75b52c80c",
|
||||
"sha256:b52ff4f4e002f828ea6483faf4c4e8deea8d743cf801b74910243c58acc6eda3",
|
||||
"sha256:b70756ec9417c34e097f987b4d8c510975216ad26ba6e57ccb53bc758f490dab",
|
||||
"sha256:b8c2f6eb0df979ee99433d8b3f6d193d9590f735cf12274c108bd954e30ca858",
|
||||
"sha256:b9b752ab91e78234941e44abdecc07f1f0d8f51fb62941d32995b8161f68cfe5",
|
||||
"sha256:ba6612b6548220ff5e9df85261bddc811a057b0b465a1226b39bfb8550616aee",
|
||||
"sha256:bd752c5ff1b4a870b7661234694f24b1d2b9076b8bf337321a814c612665f343",
|
||||
"sha256:c3c4ed2ff6760e98d262e0cc9c9a7f7b8a9f61aa4d47c58835cdaf7b0b8811bb",
|
||||
"sha256:c5c1362c14aee73f50143d74389b2c158707b4abce2cb055b7ad37ce60738d47",
|
||||
"sha256:cb362e3b0976dc994857391b776ddaa8c13c28a16f80ac6522c23d5257156bed",
|
||||
"sha256:d197df5489004db87d90b918033edbeee0bd6df3848a204bca3ff0a903bef837",
|
||||
"sha256:d3b56206244dc8711f7e8b7d6cad4663917cd5b2d950799425076681e8766286",
|
||||
"sha256:d5b2f8a31bd43e0f18172d8ac82347c8f37ef3e0b414431157718aa234991b28",
|
||||
"sha256:d7081c084ceb58278dd3cf81f836bc818978c0ccc770cbbb202125ddabec6628",
|
||||
"sha256:db74f5562c09953b2c5f8ec4b7dfd3f5421f31811e97d1dbc0a7c93d6e3a24df",
|
||||
"sha256:df41112ccce5d47770a0c13651479fbcd8793f34232a2dd9faeccb75eb5d0d0d",
|
||||
"sha256:e1339790c083c5a4de48f688b4841f18df839eb3c9584a770cbd818b33e26d5d",
|
||||
"sha256:e621b0246192d3b9cb1dc62c78cfa4c6f6d2ddc0ec207d43c0dedecb914f152a",
|
||||
"sha256:e8c5cf126889a4de385c02a2c3d3aba4b00f70234bfddae82a5eaa3ee6d5e3e6",
|
||||
"sha256:e9d7747847c53a16a729b6ee5e737cf170f7a16611c143d95aa60a109a59c336",
|
||||
"sha256:eaef5d2de3c7e9b21f1e762f289d17b726c2239a42b11e25446abf82b26ac132",
|
||||
"sha256:ed3e4b4e1e6de75fdc16d3259098de7c6571b1a6cc863b1a49e7d3d53e036070",
|
||||
"sha256:ef21af928e807f10bf4141cad4746eee692a0dd3ff56cfb25fce076ec3cc8abe",
|
||||
"sha256:f09598b416ba39a8f489c124447b007fe865f786a89dbfa48bb5cf395693132a",
|
||||
"sha256:f0caf4a5dcf610d96c3bd32932bfac8aee61c96e60481c2a0ea58da435e25acd",
|
||||
"sha256:f6e78171be3fb7941f9910ea15b4b14ec27725865a73c15277bc39f5ca4f8391",
|
||||
"sha256:f715c32e774a60a337b2bb8ad9839b4abf75b267a0f18806f6f4f5f1688c4b5a",
|
||||
"sha256:fb5c1ad6bad98c57482236a21bf985ab0ef42bd51f7ad4e4538e89a997624e12"
|
||||
"sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8",
|
||||
"sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39",
|
||||
"sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac",
|
||||
"sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869",
|
||||
"sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e",
|
||||
"sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04",
|
||||
"sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9",
|
||||
"sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e",
|
||||
"sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe",
|
||||
"sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef",
|
||||
"sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56",
|
||||
"sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa",
|
||||
"sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f",
|
||||
"sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f",
|
||||
"sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e",
|
||||
"sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a",
|
||||
"sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2",
|
||||
"sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2",
|
||||
"sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5",
|
||||
"sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a",
|
||||
"sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2",
|
||||
"sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213",
|
||||
"sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563",
|
||||
"sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591",
|
||||
"sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c",
|
||||
"sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2",
|
||||
"sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb",
|
||||
"sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757",
|
||||
"sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0",
|
||||
"sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452",
|
||||
"sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad",
|
||||
"sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01",
|
||||
"sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f",
|
||||
"sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5",
|
||||
"sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61",
|
||||
"sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e",
|
||||
"sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b",
|
||||
"sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068",
|
||||
"sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9",
|
||||
"sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588",
|
||||
"sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483",
|
||||
"sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f",
|
||||
"sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67",
|
||||
"sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7",
|
||||
"sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311",
|
||||
"sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6",
|
||||
"sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72",
|
||||
"sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6",
|
||||
"sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129",
|
||||
"sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13",
|
||||
"sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67",
|
||||
"sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c",
|
||||
"sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516",
|
||||
"sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e",
|
||||
"sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e",
|
||||
"sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364",
|
||||
"sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023",
|
||||
"sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1",
|
||||
"sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04",
|
||||
"sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d",
|
||||
"sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a",
|
||||
"sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7",
|
||||
"sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb",
|
||||
"sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4",
|
||||
"sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e",
|
||||
"sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1",
|
||||
"sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48",
|
||||
"sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==9.4.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==10.2.0"
|
||||
},
|
||||
"protobuf": {
|
||||
"hashes": [
|
||||
"sha256:1669cb7524221a8e2d9008d0842453dbefdd0fcdd64d67672f657244867635fb",
|
||||
"sha256:29288813aacaa302afa2381db1d6e0482165737b0afdf2811df5fa99185c457b",
|
||||
"sha256:47d31bdf58222dd296976aa1646c68c6ee80b96d22e0a3c336c9174e253fd35e",
|
||||
"sha256:652d8dfece122a24d98eebfef30e31e455d300efa41999d1182e015984ac5930",
|
||||
"sha256:7c535d126e7dcc714105ab20b418c4fedbd28f8b8afc42b7350b1e317bbbcc71",
|
||||
"sha256:86c3d20428b007537ba6792b475c0853bba7f66b1f60e610d913b77d94b486e4",
|
||||
"sha256:a33a273d21852f911b8bda47f39f4383fe7c061eb1814db2c76c9875c89c2491",
|
||||
"sha256:ab4d043865dd04e6b09386981fe8f80b39a1e46139fb4a3c206229d6b9f36ff6",
|
||||
"sha256:b2fea9dc8e3c0f32c38124790ef16cba2ee0628fe2022a52e435e1117bfef9b1",
|
||||
"sha256:c27f371f0159feb70e6ea52ed7e768b3f3a4c5676c1900a7e51a24740381650e",
|
||||
"sha256:c3325803095fb4c2a48649c321d2fbde59f8fbfcb9bfc7a86df27d112831c571",
|
||||
"sha256:e474b63bab0a2ea32a7b26a4d8eec59e33e709321e5e16fb66e766b61b82a95e",
|
||||
"sha256:e894e9ae603e963f0842498c4cd5d39c6a60f0d7e4c103df50ee939564298658"
|
||||
"sha256:38aa5f535721d5bb99861166c445c4105c4e285c765fbb2ac10f116e32dcd46d",
|
||||
"sha256:3c388ea6ddfe735f8cf69e3f7dc7611e73107b60bdfcf5d0f024c3ccd3794e23",
|
||||
"sha256:7ee014c2c87582e101d6b54260af03b6596728505c79f17c8586e7523aaa8f8c",
|
||||
"sha256:8ca2a1d97c290ec7b16e4e5dff2e5ae150cc1582f55b5ab300d45cb0dfa90e51",
|
||||
"sha256:9b557c317ebe6836835ec4ef74ec3e994ad0894ea424314ad3552bc6e8835b4e",
|
||||
"sha256:b9ba3ca83c2e31219ffbeb9d76b63aad35a3eb1544170c55336993d7a18ae72c",
|
||||
"sha256:d693d2504ca96750d92d9de8a103102dd648fda04540495535f0fec7577ed8fc",
|
||||
"sha256:da612f2720c0183417194eeaa2523215c4fcc1a1949772dc65f05047e08d5932",
|
||||
"sha256:e6039957449cb918f331d32ffafa8eb9255769c96aa0560d9a5bf0b4e00a2a33",
|
||||
"sha256:f7417703f841167e5a27d48be13389d52ad705ec09eade63dfc3180a959215d7",
|
||||
"sha256:fbfe61e7ee8c1860855696e3ac6cfd1b01af5498facc6834fcc345c9684fb2ca"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.22.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==5.26.1"
|
||||
},
|
||||
"pypng": {
|
||||
"hashes": [
|
||||
@@ -215,6 +209,7 @@
|
||||
"sha256:9dd969454827e127dbd93696b20747239e6d540e082937c90f14ac95b30f5845"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==7.4.2"
|
||||
},
|
||||
"qreader": {
|
||||
@@ -226,113 +221,108 @@
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb",
|
||||
"sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"
|
||||
"sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475",
|
||||
"sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==4.5.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.10.0"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
"astroid": {
|
||||
"hashes": [
|
||||
"sha256:0e0e3709d64fbffd3037e4ff403580550f14471fd3eaae9fa11cc9a5c7901153",
|
||||
"sha256:a3cf9f02c53dd259144a7e8f3ccd75d67c9a8c716ef183e0c1f291bc5d7bb3cf"
|
||||
"sha256:951798f922990137ac090c53af473db7ab4e70c770e6d7fae0cec59f74411819",
|
||||
"sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4"
|
||||
],
|
||||
"markers": "python_full_version >= '3.7.2'",
|
||||
"version": "==2.14.2"
|
||||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836",
|
||||
"sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==22.2.0"
|
||||
"markers": "python_full_version >= '3.8.0'",
|
||||
"version": "==3.1.0"
|
||||
},
|
||||
"build": {
|
||||
"hashes": [
|
||||
"sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171",
|
||||
"sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269"
|
||||
"sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d",
|
||||
"sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.10.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.2.1"
|
||||
},
|
||||
"coverage": {
|
||||
"extras": [
|
||||
"toml"
|
||||
],
|
||||
"hashes": [
|
||||
"sha256:04481245ef966fbd24ae9b9e537ce899ae584d521dfbe78f89cad003c38ca2ab",
|
||||
"sha256:0c45948f613d5d18c9ec5eaa203ce06a653334cf1bd47c783a12d0dd4fd9c851",
|
||||
"sha256:10188fe543560ec4874f974b5305cd1a8bdcfa885ee00ea3a03733464c4ca265",
|
||||
"sha256:218fe982371ac7387304153ecd51205f14e9d731b34fb0568181abaf7b443ba0",
|
||||
"sha256:29571503c37f2ef2138a306d23e7270687c0efb9cab4bd8038d609b5c2393a3a",
|
||||
"sha256:2a60d6513781e87047c3e630b33b4d1e89f39836dac6e069ffee28c4786715f5",
|
||||
"sha256:2bf1d5f2084c3932b56b962a683074a3692bce7cabd3aa023c987a2a8e7612f6",
|
||||
"sha256:3164d31078fa9efe406e198aecd2a02d32a62fecbdef74f76dad6a46c7e48311",
|
||||
"sha256:32df215215f3af2c1617a55dbdfb403b772d463d54d219985ac7cd3bf124cada",
|
||||
"sha256:33d1ae9d4079e05ac4cc1ef9e20c648f5afabf1a92adfaf2ccf509c50b85717f",
|
||||
"sha256:33ff26d0f6cc3ca8de13d14fde1ff8efe1456b53e3f0273e63cc8b3c84a063d8",
|
||||
"sha256:38da2db80cc505a611938d8624801158e409928b136c8916cd2e203970dde4dc",
|
||||
"sha256:3b155caf3760408d1cb903b21e6a97ad4e2bdad43cbc265e3ce0afb8e0057e73",
|
||||
"sha256:3b946bbcd5a8231383450b195cfb58cb01cbe7f8949f5758566b881df4b33baf",
|
||||
"sha256:3baf5f126f30781b5e93dbefcc8271cb2491647f8283f20ac54d12161dff080e",
|
||||
"sha256:4b14d5e09c656de5038a3f9bfe5228f53439282abcab87317c9f7f1acb280352",
|
||||
"sha256:51b236e764840a6df0661b67e50697aaa0e7d4124ca95e5058fa3d7cbc240b7c",
|
||||
"sha256:63ffd21aa133ff48c4dff7adcc46b7ec8b565491bfc371212122dd999812ea1c",
|
||||
"sha256:6a43c7823cd7427b4ed763aa7fb63901ca8288591323b58c9cd6ec31ad910f3c",
|
||||
"sha256:755e89e32376c850f826c425ece2c35a4fc266c081490eb0a841e7c1cb0d3bda",
|
||||
"sha256:7a726d742816cb3a8973c8c9a97539c734b3a309345236cd533c4883dda05b8d",
|
||||
"sha256:7c7c0d0827e853315c9bbd43c1162c006dd808dbbe297db7ae66cd17b07830f0",
|
||||
"sha256:7ed681b0f8e8bcbbffa58ba26fcf5dbc8f79e7997595bf071ed5430d8c08d6f3",
|
||||
"sha256:7ee5c9bb51695f80878faaa5598040dd6c9e172ddcf490382e8aedb8ec3fec8d",
|
||||
"sha256:8361be1c2c073919500b6601220a6f2f98ea0b6d2fec5014c1d9cfa23dd07038",
|
||||
"sha256:8ae125d1134bf236acba8b83e74c603d1b30e207266121e76484562bc816344c",
|
||||
"sha256:9817733f0d3ea91bea80de0f79ef971ae94f81ca52f9b66500c6a2fea8e4b4f8",
|
||||
"sha256:98b85dd86514d889a2e3dd22ab3c18c9d0019e696478391d86708b805f4ea0fa",
|
||||
"sha256:9ccb092c9ede70b2517a57382a601619d20981f56f440eae7e4d7eaafd1d1d09",
|
||||
"sha256:9d58885215094ab4a86a6aef044e42994a2bd76a446dc59b352622655ba6621b",
|
||||
"sha256:b643cb30821e7570c0aaf54feaf0bfb630b79059f85741843e9dc23f33aaca2c",
|
||||
"sha256:bc7c85a150501286f8b56bd8ed3aa4093f4b88fb68c0843d21ff9656f0009d6a",
|
||||
"sha256:beeb129cacea34490ffd4d6153af70509aa3cda20fdda2ea1a2be870dfec8d52",
|
||||
"sha256:c31b75ae466c053a98bf26843563b3b3517b8f37da4d47b1c582fdc703112bc3",
|
||||
"sha256:c4e4881fa9e9667afcc742f0c244d9364d197490fbc91d12ac3b5de0bf2df146",
|
||||
"sha256:c5b15ed7644ae4bee0ecf74fee95808dcc34ba6ace87e8dfbf5cb0dc20eab45a",
|
||||
"sha256:d12d076582507ea460ea2a89a8c85cb558f83406c8a41dd641d7be9a32e1274f",
|
||||
"sha256:d248cd4a92065a4d4543b8331660121b31c4148dd00a691bfb7a5cdc7483cfa4",
|
||||
"sha256:d47dd659a4ee952e90dc56c97d78132573dc5c7b09d61b416a9deef4ebe01a0c",
|
||||
"sha256:d4a5a5879a939cb84959d86869132b00176197ca561c664fc21478c1eee60d75",
|
||||
"sha256:da9b41d4539eefd408c46725fb76ecba3a50a3367cafb7dea5f250d0653c1040",
|
||||
"sha256:db61a79c07331e88b9a9974815c075fbd812bc9dbc4dc44b366b5368a2936063",
|
||||
"sha256:ddb726cb861c3117a553f940372a495fe1078249ff5f8a5478c0576c7be12050",
|
||||
"sha256:ded59300d6330be27bc6cf0b74b89ada58069ced87c48eaf9344e5e84b0072f7",
|
||||
"sha256:e2617759031dae1bf183c16cef8fcfb3de7617f394c813fa5e8e46e9b82d4222",
|
||||
"sha256:e5cdbb5cafcedea04924568d990e20ce7f1945a1dd54b560f879ee2d57226912",
|
||||
"sha256:ec8e767f13be637d056f7e07e61d089e555f719b387a7070154ad80a0ff31801",
|
||||
"sha256:ef382417db92ba23dfb5864a3fc9be27ea4894e86620d342a116b243ade5d35d",
|
||||
"sha256:f2cba5c6db29ce991029b5e4ac51eb36774458f0a3b8d3137241b32d1bb91f06",
|
||||
"sha256:f5b4198d85a3755d27e64c52f8c95d6333119e49fd001ae5798dac872c95e0f8",
|
||||
"sha256:ffeeb38ee4a80a30a6877c5c4c359e5498eec095878f1581453202bfacc8fbc2"
|
||||
"sha256:00838a35b882694afda09f85e469c96367daa3f3f2b097d846a7216993d37f4c",
|
||||
"sha256:0513b9508b93da4e1716744ef6ebc507aff016ba115ffe8ecff744d1322a7b63",
|
||||
"sha256:09c3255458533cb76ef55da8cc49ffab9e33f083739c8bd4f58e79fecfe288f7",
|
||||
"sha256:09ef9199ed6653989ebbcaacc9b62b514bb63ea2f90256e71fea3ed74bd8ff6f",
|
||||
"sha256:09fa497a8ab37784fbb20ab699c246053ac294d13fc7eb40ec007a5043ec91f8",
|
||||
"sha256:0f9f50e7ef2a71e2fae92774c99170eb8304e3fdf9c8c3c7ae9bab3e7229c5cf",
|
||||
"sha256:137eb07173141545e07403cca94ab625cc1cc6bc4c1e97b6e3846270e7e1fea0",
|
||||
"sha256:1f384c3cc76aeedce208643697fb3e8437604b512255de6d18dae3f27655a384",
|
||||
"sha256:201bef2eea65e0e9c56343115ba3814e896afe6d36ffd37bab783261db430f76",
|
||||
"sha256:38dd60d7bf242c4ed5b38e094baf6401faa114fc09e9e6632374388a404f98e7",
|
||||
"sha256:3b799445b9f7ee8bf299cfaed6f5b226c0037b74886a4e11515e569b36fe310d",
|
||||
"sha256:3ea79bb50e805cd6ac058dfa3b5c8f6c040cb87fe83de10845857f5535d1db70",
|
||||
"sha256:40209e141059b9370a2657c9b15607815359ab3ef9918f0196b6fccce8d3230f",
|
||||
"sha256:41c9c5f3de16b903b610d09650e5e27adbfa7f500302718c9ffd1c12cf9d6818",
|
||||
"sha256:54eb8d1bf7cacfbf2a3186019bcf01d11c666bd495ed18717162f7eb1e9dd00b",
|
||||
"sha256:598825b51b81c808cb6f078dcb972f96af96b078faa47af7dfcdf282835baa8d",
|
||||
"sha256:5fc1de20b2d4a061b3df27ab9b7c7111e9a710f10dc2b84d33a4ab25065994ec",
|
||||
"sha256:623512f8ba53c422fcfb2ce68362c97945095b864cda94a92edbaf5994201083",
|
||||
"sha256:690db6517f09336559dc0b5f55342df62370a48f5469fabf502db2c6d1cffcd2",
|
||||
"sha256:69eb372f7e2ece89f14751fbcbe470295d73ed41ecd37ca36ed2eb47512a6ab9",
|
||||
"sha256:73bfb9c09951125d06ee473bed216e2c3742f530fc5acc1383883125de76d9cd",
|
||||
"sha256:742a76a12aa45b44d236815d282b03cfb1de3b4323f3e4ec933acfae08e54ade",
|
||||
"sha256:7c95949560050d04d46b919301826525597f07b33beba6187d04fa64d47ac82e",
|
||||
"sha256:8130a2aa2acb8788e0b56938786c33c7c98562697bf9f4c7d6e8e5e3a0501e4a",
|
||||
"sha256:8a2b2b78c78293782fd3767d53e6474582f62443d0504b1554370bde86cc8227",
|
||||
"sha256:8ce1415194b4a6bd0cdcc3a1dfbf58b63f910dcb7330fe15bdff542c56949f87",
|
||||
"sha256:9ca28a302acb19b6af89e90f33ee3e1906961f94b54ea37de6737b7ca9d8827c",
|
||||
"sha256:a4cdc86d54b5da0df6d3d3a2f0b710949286094c3a6700c21e9015932b81447e",
|
||||
"sha256:aa5b1c1bfc28384f1f53b69a023d789f72b2e0ab1b3787aae16992a7ca21056c",
|
||||
"sha256:aadacf9a2f407a4688d700e4ebab33a7e2e408f2ca04dbf4aef17585389eff3e",
|
||||
"sha256:ae71e7ddb7a413dd60052e90528f2f65270aad4b509563af6d03d53e979feafd",
|
||||
"sha256:b14706df8b2de49869ae03a5ccbc211f4041750cd4a66f698df89d44f4bd30ec",
|
||||
"sha256:b1a93009cb80730c9bca5d6d4665494b725b6e8e157c1cb7f2db5b4b122ea562",
|
||||
"sha256:b2991665420a803495e0b90a79233c1433d6ed77ef282e8e152a324bbbc5e0c8",
|
||||
"sha256:b2c5edc4ac10a7ef6605a966c58929ec6c1bd0917fb8c15cb3363f65aa40e677",
|
||||
"sha256:b4d33f418f46362995f1e9d4f3a35a1b6322cb959c31d88ae56b0298e1c22357",
|
||||
"sha256:b91cbc4b195444e7e258ba27ac33769c41b94967919f10037e6355e998af255c",
|
||||
"sha256:c74880fc64d4958159fbd537a091d2a585448a8f8508bf248d72112723974cbd",
|
||||
"sha256:c901df83d097649e257e803be22592aedfd5182f07b3cc87d640bbb9afd50f49",
|
||||
"sha256:cac99918c7bba15302a2d81f0312c08054a3359eaa1929c7e4b26ebe41e9b286",
|
||||
"sha256:cc4f1358cb0c78edef3ed237ef2c86056206bb8d9140e73b6b89fbcfcbdd40e1",
|
||||
"sha256:ccd341521be3d1b3daeb41960ae94a5e87abe2f46f17224ba5d6f2b8398016cf",
|
||||
"sha256:ce4b94265ca988c3f8e479e741693d143026632672e3ff924f25fab50518dd51",
|
||||
"sha256:cf271892d13e43bc2b51e6908ec9a6a5094a4df1d8af0bfc360088ee6c684409",
|
||||
"sha256:d5ae728ff3b5401cc320d792866987e7e7e880e6ebd24433b70a33b643bb0384",
|
||||
"sha256:d71eec7d83298f1af3326ce0ff1d0ea83c7cb98f72b577097f9083b20bdaf05e",
|
||||
"sha256:d898fe162d26929b5960e4e138651f7427048e72c853607f2b200909794ed978",
|
||||
"sha256:d89d7b2974cae412400e88f35d86af72208e1ede1a541954af5d944a8ba46c57",
|
||||
"sha256:dfa8fe35a0bb90382837b238fff375de15f0dcdb9ae68ff85f7a63649c98527e",
|
||||
"sha256:e0be5efd5127542ef31f165de269f77560d6cdef525fffa446de6f7e9186cfb2",
|
||||
"sha256:fdfafb32984684eb03c2d83e1e51f64f0906b11e64482df3c5db936ce3839d48",
|
||||
"sha256:ff7687ca3d7028d8a5f0ebae95a6e4827c5616b31a4ee1192bdfde697db110d4"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==7.1.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==7.4.4"
|
||||
},
|
||||
"dill": {
|
||||
"hashes": [
|
||||
"sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0",
|
||||
"sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"
|
||||
"sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca",
|
||||
"sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"
|
||||
],
|
||||
"markers": "python_version >= '3.11'",
|
||||
"version": "==0.3.6"
|
||||
"version": "==0.3.8"
|
||||
},
|
||||
"flake8": {
|
||||
"hashes": [
|
||||
"sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7",
|
||||
"sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"
|
||||
"sha256:33f96621059e65eec474169085dc92bf26e7b2d47366b70be2f67ab80dc25132",
|
||||
"sha256:a6dfbb75e03252917f2473ea9653f7cd799c3064e54d4c8140044c5c065f53c3"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.0.0"
|
||||
"markers": "python_full_version >= '3.8.1'",
|
||||
"version": "==7.0.0"
|
||||
},
|
||||
"gfm-toc": {
|
||||
"hashes": [
|
||||
@@ -352,53 +342,11 @@
|
||||
},
|
||||
"isort": {
|
||||
"hashes": [
|
||||
"sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504",
|
||||
"sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"
|
||||
"sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109",
|
||||
"sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"
|
||||
],
|
||||
"markers": "python_full_version >= '3.8.0'",
|
||||
"version": "==5.12.0"
|
||||
},
|
||||
"lazy-object-proxy": {
|
||||
"hashes": [
|
||||
"sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382",
|
||||
"sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82",
|
||||
"sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9",
|
||||
"sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494",
|
||||
"sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46",
|
||||
"sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30",
|
||||
"sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63",
|
||||
"sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4",
|
||||
"sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae",
|
||||
"sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be",
|
||||
"sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701",
|
||||
"sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd",
|
||||
"sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006",
|
||||
"sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a",
|
||||
"sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586",
|
||||
"sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8",
|
||||
"sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821",
|
||||
"sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07",
|
||||
"sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b",
|
||||
"sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171",
|
||||
"sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b",
|
||||
"sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2",
|
||||
"sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7",
|
||||
"sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4",
|
||||
"sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8",
|
||||
"sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e",
|
||||
"sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f",
|
||||
"sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda",
|
||||
"sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4",
|
||||
"sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e",
|
||||
"sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671",
|
||||
"sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11",
|
||||
"sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455",
|
||||
"sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734",
|
||||
"sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb",
|
||||
"sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.9.0"
|
||||
"version": "==5.13.2"
|
||||
},
|
||||
"mccabe": {
|
||||
"hashes": [
|
||||
@@ -410,35 +358,37 @@
|
||||
},
|
||||
"mypy": {
|
||||
"hashes": [
|
||||
"sha256:0af4f0e20706aadf4e6f8f8dc5ab739089146b83fd53cb4a7e0e850ef3de0bb6",
|
||||
"sha256:15b5a824b58c7c822c51bc66308e759243c32631896743f030daf449fe3677f3",
|
||||
"sha256:17455cda53eeee0a4adb6371a21dd3dbf465897de82843751cf822605d152c8c",
|
||||
"sha256:2013226d17f20468f34feddd6aae4635a55f79626549099354ce641bc7d40262",
|
||||
"sha256:24189f23dc66f83b839bd1cce2dfc356020dfc9a8bae03978477b15be61b062e",
|
||||
"sha256:27a0f74a298769d9fdc8498fcb4f2beb86f0564bcdb1a37b58cbbe78e55cf8c0",
|
||||
"sha256:28cea5a6392bb43d266782983b5a4216c25544cd7d80be681a155ddcdafd152d",
|
||||
"sha256:448de661536d270ce04f2d7dddaa49b2fdba6e3bd8a83212164d4174ff43aa65",
|
||||
"sha256:48525aec92b47baed9b3380371ab8ab6e63a5aab317347dfe9e55e02aaad22e8",
|
||||
"sha256:5bc8d6bd3b274dd3846597855d96d38d947aedba18776aa998a8d46fabdaed76",
|
||||
"sha256:5deb252fd42a77add936b463033a59b8e48eb2eaec2976d76b6878d031933fe4",
|
||||
"sha256:5f546ac34093c6ce33f6278f7c88f0f147a4849386d3bf3ae193702f4fe31407",
|
||||
"sha256:5fdd63e4f50e3538617887e9aee91855368d9fc1dea30da743837b0df7373bc4",
|
||||
"sha256:65b122a993d9c81ea0bfde7689b3365318a88bde952e4dfa1b3a8b4ac05d168b",
|
||||
"sha256:71a808334d3f41ef011faa5a5cd8153606df5fc0b56de5b2e89566c8093a0c9a",
|
||||
"sha256:920169f0184215eef19294fa86ea49ffd4635dedfdea2b57e45cb4ee85d5ccaf",
|
||||
"sha256:93a85495fb13dc484251b4c1fd7a5ac370cd0d812bbfc3b39c1bafefe95275d5",
|
||||
"sha256:a2948c40a7dd46c1c33765718936669dc1f628f134013b02ff5ac6c7ef6942bf",
|
||||
"sha256:c6c2ccb7af7154673c591189c3687b013122c5a891bb5651eca3db8e6c6c55bd",
|
||||
"sha256:c96b8a0c019fe29040d520d9257d8c8f122a7343a8307bf8d6d4a43f5c5bfcc8",
|
||||
"sha256:d42a98e76070a365a1d1c220fcac8aa4ada12ae0db679cb4d910fabefc88b994",
|
||||
"sha256:dbeb24514c4acbc78d205f85dd0e800f34062efcc1f4a4857c57e4b4b8712bff",
|
||||
"sha256:e60d0b09f62ae97a94605c3f73fd952395286cf3e3b9e7b97f60b01ddfbbda88",
|
||||
"sha256:e64f48c6176e243ad015e995de05af7f22bbe370dbb5b32bd6988438ec873919",
|
||||
"sha256:e831662208055b006eef68392a768ff83596035ffd6d846786578ba1714ba8f6",
|
||||
"sha256:eda5c8b9949ed411ff752b9a01adda31afe7eae1e53e946dbdf9db23865e66c4"
|
||||
"sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6",
|
||||
"sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913",
|
||||
"sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129",
|
||||
"sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc",
|
||||
"sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974",
|
||||
"sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374",
|
||||
"sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150",
|
||||
"sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03",
|
||||
"sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9",
|
||||
"sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02",
|
||||
"sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89",
|
||||
"sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2",
|
||||
"sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d",
|
||||
"sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3",
|
||||
"sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612",
|
||||
"sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e",
|
||||
"sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3",
|
||||
"sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e",
|
||||
"sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd",
|
||||
"sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04",
|
||||
"sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed",
|
||||
"sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185",
|
||||
"sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf",
|
||||
"sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b",
|
||||
"sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4",
|
||||
"sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f",
|
||||
"sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.0.1"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.9.0"
|
||||
},
|
||||
"mypy-extensions": {
|
||||
"hashes": [
|
||||
@@ -450,78 +400,94 @@
|
||||
},
|
||||
"mypy-protobuf": {
|
||||
"hashes": [
|
||||
"sha256:7d75a079651b105076776a35a5405e3fa773b8a167118f1b712e443e9a6c18a2",
|
||||
"sha256:da33dfde7547ff57e5ba5564126cbfa114f14413b2fa50759b1fa5de1e4ab511"
|
||||
"sha256:0d0548c6b9a6faf14ce1a9ce2831c403a5c1f2a9363e85b1e2c51d5d57aa8393",
|
||||
"sha256:21f270da0a9792a9dac76b0df463c027e561664ab6973c59be4e4d064dfe67dc"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.4.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==3.5.0"
|
||||
},
|
||||
"nuitka": {
|
||||
"hashes": [
|
||||
"sha256:31c5c49f41dfebfc5c58fa5cdab7db9963a4b1693f4d55bed86e2a1e39f890f2"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.1.4"
|
||||
},
|
||||
"ordered-set": {
|
||||
"hashes": [
|
||||
"sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562",
|
||||
"sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==4.1.0"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2",
|
||||
"sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"
|
||||
"sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
|
||||
"sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==23.0"
|
||||
"version": "==24.0"
|
||||
},
|
||||
"platformdirs": {
|
||||
"hashes": [
|
||||
"sha256:8a1228abb1ef82d788f74139988b137e78692984ec7b08eaa6c65f1723af28f9",
|
||||
"sha256:b1d5eb14f221506f50d6604a561f4c5786d9e80355219694a1b244bcd96f4567"
|
||||
"sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068",
|
||||
"sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.0.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.2.0"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
|
||||
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
|
||||
"sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981",
|
||||
"sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.0.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.4.0"
|
||||
},
|
||||
"protobuf": {
|
||||
"hashes": [
|
||||
"sha256:1669cb7524221a8e2d9008d0842453dbefdd0fcdd64d67672f657244867635fb",
|
||||
"sha256:29288813aacaa302afa2381db1d6e0482165737b0afdf2811df5fa99185c457b",
|
||||
"sha256:47d31bdf58222dd296976aa1646c68c6ee80b96d22e0a3c336c9174e253fd35e",
|
||||
"sha256:652d8dfece122a24d98eebfef30e31e455d300efa41999d1182e015984ac5930",
|
||||
"sha256:7c535d126e7dcc714105ab20b418c4fedbd28f8b8afc42b7350b1e317bbbcc71",
|
||||
"sha256:86c3d20428b007537ba6792b475c0853bba7f66b1f60e610d913b77d94b486e4",
|
||||
"sha256:a33a273d21852f911b8bda47f39f4383fe7c061eb1814db2c76c9875c89c2491",
|
||||
"sha256:ab4d043865dd04e6b09386981fe8f80b39a1e46139fb4a3c206229d6b9f36ff6",
|
||||
"sha256:b2fea9dc8e3c0f32c38124790ef16cba2ee0628fe2022a52e435e1117bfef9b1",
|
||||
"sha256:c27f371f0159feb70e6ea52ed7e768b3f3a4c5676c1900a7e51a24740381650e",
|
||||
"sha256:c3325803095fb4c2a48649c321d2fbde59f8fbfcb9bfc7a86df27d112831c571",
|
||||
"sha256:e474b63bab0a2ea32a7b26a4d8eec59e33e709321e5e16fb66e766b61b82a95e",
|
||||
"sha256:e894e9ae603e963f0842498c4cd5d39c6a60f0d7e4c103df50ee939564298658"
|
||||
"sha256:38aa5f535721d5bb99861166c445c4105c4e285c765fbb2ac10f116e32dcd46d",
|
||||
"sha256:3c388ea6ddfe735f8cf69e3f7dc7611e73107b60bdfcf5d0f024c3ccd3794e23",
|
||||
"sha256:7ee014c2c87582e101d6b54260af03b6596728505c79f17c8586e7523aaa8f8c",
|
||||
"sha256:8ca2a1d97c290ec7b16e4e5dff2e5ae150cc1582f55b5ab300d45cb0dfa90e51",
|
||||
"sha256:9b557c317ebe6836835ec4ef74ec3e994ad0894ea424314ad3552bc6e8835b4e",
|
||||
"sha256:b9ba3ca83c2e31219ffbeb9d76b63aad35a3eb1544170c55336993d7a18ae72c",
|
||||
"sha256:d693d2504ca96750d92d9de8a103102dd648fda04540495535f0fec7577ed8fc",
|
||||
"sha256:da612f2720c0183417194eeaa2523215c4fcc1a1949772dc65f05047e08d5932",
|
||||
"sha256:e6039957449cb918f331d32ffafa8eb9255769c96aa0560d9a5bf0b4e00a2a33",
|
||||
"sha256:f7417703f841167e5a27d48be13389d52ad705ec09eade63dfc3180a959215d7",
|
||||
"sha256:fbfe61e7ee8c1860855696e3ac6cfd1b01af5498facc6834fcc345c9684fb2ca"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.22.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==5.26.1"
|
||||
},
|
||||
"pycodestyle": {
|
||||
"hashes": [
|
||||
"sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053",
|
||||
"sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"
|
||||
"sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f",
|
||||
"sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.10.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.11.1"
|
||||
},
|
||||
"pyflakes": {
|
||||
"hashes": [
|
||||
"sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf",
|
||||
"sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"
|
||||
"sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f",
|
||||
"sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.1"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==3.2.0"
|
||||
},
|
||||
"pylint": {
|
||||
"hashes": [
|
||||
"sha256:13b2c805a404a9bf57d002cd5f054ca4d40b0b87542bdaba5e05321ae8262c84",
|
||||
"sha256:ff22dde9c2128cd257c145cfd51adeff0be7df4d80d669055f24a962b351bbe4"
|
||||
"sha256:507a5b60953874766d8a366e8e8c7af63e058b26345cfcb5f91f89d987fd6b74",
|
||||
"sha256:6a69beb4a6f63debebaab0a3477ecd0f559aa726af4954fc948c51f7a2549e23"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.16.2"
|
||||
"markers": "python_full_version >= '3.8.0'",
|
||||
"version": "==3.1.0"
|
||||
},
|
||||
"pyproject-hooks": {
|
||||
"hashes": [
|
||||
@@ -533,145 +499,133 @@
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:c7c6ca206e93355074ae32f7403e8ea12163b1163c976fee7d4d84027c162be5",
|
||||
"sha256:d45e0952f3727241918b8fd0f376f5ff6b301cc0777c6f9a556935c92d8a7d42"
|
||||
"sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7",
|
||||
"sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==7.2.1"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==8.1.1"
|
||||
},
|
||||
"pytest-cov": {
|
||||
"hashes": [
|
||||
"sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b",
|
||||
"sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"
|
||||
"sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652",
|
||||
"sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.0.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==5.0.0"
|
||||
},
|
||||
"pytest-mock": {
|
||||
"hashes": [
|
||||
"sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b",
|
||||
"sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"
|
||||
"sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f",
|
||||
"sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.10.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==3.14.0"
|
||||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:95f00380ef2ffa41d9bba85d95b27689d923c93dfbafed4aecd7cf988a25e012",
|
||||
"sha256:bb6d8e508de562768f2027902929f8523932fcd1fb784e6d573d2cafac995a48"
|
||||
"sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e",
|
||||
"sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==67.3.2"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==69.2.0"
|
||||
},
|
||||
"setuptools-git-versioning": {
|
||||
"hashes": [
|
||||
"sha256:648481f7e1e9e12ccd2b069d616b909a338b4223956319649351751cbc0207f4",
|
||||
"sha256:fde1a7cb3b2566979e5651cfca0d33cd5a82771711cd38a056216391936cf0ff"
|
||||
"sha256:75e3e8c4528fa21ca2417a1f222fdaaa4d2ca7d8536c44affad827c6ec9ba0d4",
|
||||
"sha256:a57873f91687bf5fe97d28f65fa8c2d03bfe633cf7373c365bb83a87975a0de6"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.13.1"
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.13.6"
|
||||
},
|
||||
"tomlkit": {
|
||||
"hashes": [
|
||||
"sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b",
|
||||
"sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"
|
||||
"sha256:5cd82d48a3dd89dee1f9d64420aa20ae65cfbd00668d6f094d7578a78efbb77b",
|
||||
"sha256:7ca1cfc12232806517a8515047ba66a19369e71edf2439d0f5824f91032b6cc3"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.11.6"
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==0.12.4"
|
||||
},
|
||||
"types-protobuf": {
|
||||
"hashes": [
|
||||
"sha256:39167012ead0bc5920b6322a1e4dc2d088f66a34b84cce39bb88500e49ac955a",
|
||||
"sha256:8c105b906569e9d53ba033465880d9ef17a59bf3ba8ab656d24c9eadb9d8a056"
|
||||
"sha256:8e039486df058141cb221ab99f88c5878c08cca4376db1d84f63279860aa09cd",
|
||||
"sha256:c80426f9fb9b21aee514691e96ab32a5cd694a82e2ac07964b352c3e7e0182bc"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.21.0.6"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.24.0.20240311"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb",
|
||||
"sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"
|
||||
"sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475",
|
||||
"sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==4.5.0"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.10.0"
|
||||
},
|
||||
"wheel": {
|
||||
"hashes": [
|
||||
"sha256:965f5259b566725405b05e7cf774052044b1ed30119b5d586b2703aafe8719ac",
|
||||
"sha256:b60533f3f5d530e971d6737ca6d58681ee434818fab630c83a734bb10c083ce8"
|
||||
"sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85",
|
||||
"sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.38.4"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.43.0"
|
||||
},
|
||||
"wrapt": {
|
||||
"zstandard": {
|
||||
"hashes": [
|
||||
"sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3",
|
||||
"sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b",
|
||||
"sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4",
|
||||
"sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2",
|
||||
"sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656",
|
||||
"sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3",
|
||||
"sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff",
|
||||
"sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310",
|
||||
"sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a",
|
||||
"sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57",
|
||||
"sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069",
|
||||
"sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383",
|
||||
"sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe",
|
||||
"sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87",
|
||||
"sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d",
|
||||
"sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b",
|
||||
"sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907",
|
||||
"sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f",
|
||||
"sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0",
|
||||
"sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28",
|
||||
"sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1",
|
||||
"sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853",
|
||||
"sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc",
|
||||
"sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3",
|
||||
"sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3",
|
||||
"sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164",
|
||||
"sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1",
|
||||
"sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c",
|
||||
"sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1",
|
||||
"sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7",
|
||||
"sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1",
|
||||
"sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320",
|
||||
"sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed",
|
||||
"sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1",
|
||||
"sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248",
|
||||
"sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c",
|
||||
"sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456",
|
||||
"sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77",
|
||||
"sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef",
|
||||
"sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1",
|
||||
"sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7",
|
||||
"sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86",
|
||||
"sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4",
|
||||
"sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d",
|
||||
"sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d",
|
||||
"sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8",
|
||||
"sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5",
|
||||
"sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471",
|
||||
"sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00",
|
||||
"sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68",
|
||||
"sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3",
|
||||
"sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d",
|
||||
"sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735",
|
||||
"sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d",
|
||||
"sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569",
|
||||
"sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7",
|
||||
"sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59",
|
||||
"sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5",
|
||||
"sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb",
|
||||
"sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b",
|
||||
"sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f",
|
||||
"sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462",
|
||||
"sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015",
|
||||
"sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"
|
||||
"sha256:11f0d1aab9516a497137b41e3d3ed4bbf7b2ee2abc79e5c8b010ad286d7464bd",
|
||||
"sha256:1958100b8a1cc3f27fa21071a55cb2ed32e9e5df4c3c6e661c193437f171cba2",
|
||||
"sha256:1a90ba9a4c9c884bb876a14be2b1d216609385efb180393df40e5172e7ecf356",
|
||||
"sha256:1d43501f5f31e22baf822720d82b5547f8a08f5386a883b32584a185675c8fbf",
|
||||
"sha256:23d2b3c2b8e7e5a6cb7922f7c27d73a9a615f0a5ab5d0e03dd533c477de23004",
|
||||
"sha256:2612e9bb4977381184bb2463150336d0f7e014d6bb5d4a370f9a372d21916f69",
|
||||
"sha256:275df437ab03f8c033b8a2c181e51716c32d831082d93ce48002a5227ec93019",
|
||||
"sha256:2ac9957bc6d2403c4772c890916bf181b2653640da98f32e04b96e4d6fb3252a",
|
||||
"sha256:2b11ea433db22e720758cba584c9d661077121fcf60ab43351950ded20283440",
|
||||
"sha256:2fdd53b806786bd6112d97c1f1e7841e5e4daa06810ab4b284026a1a0e484c0b",
|
||||
"sha256:33591d59f4956c9812f8063eff2e2c0065bc02050837f152574069f5f9f17775",
|
||||
"sha256:36a47636c3de227cd765e25a21dc5dace00539b82ddd99ee36abae38178eff9e",
|
||||
"sha256:39b2853efc9403927f9065cc48c9980649462acbdf81cd4f0cb773af2fd734bc",
|
||||
"sha256:3db41c5e49ef73641d5111554e1d1d3af106410a6c1fb52cf68912ba7a343a0d",
|
||||
"sha256:445b47bc32de69d990ad0f34da0e20f535914623d1e506e74d6bc5c9dc40bb09",
|
||||
"sha256:466e6ad8caefb589ed281c076deb6f0cd330e8bc13c5035854ffb9c2014b118c",
|
||||
"sha256:48f260e4c7294ef275744210a4010f116048e0c95857befb7462e033f09442fe",
|
||||
"sha256:4ac59d5d6910b220141c1737b79d4a5aa9e57466e7469a012ed42ce2d3995e88",
|
||||
"sha256:53866a9d8ab363271c9e80c7c2e9441814961d47f88c9bc3b248142c32141d94",
|
||||
"sha256:589402548251056878d2e7c8859286eb91bd841af117dbe4ab000e6450987e08",
|
||||
"sha256:68953dc84b244b053c0d5f137a21ae8287ecf51b20872eccf8eaac0302d3e3b0",
|
||||
"sha256:6c25b8eb733d4e741246151d895dd0308137532737f337411160ff69ca24f93a",
|
||||
"sha256:7034d381789f45576ec3f1fa0e15d741828146439228dc3f7c59856c5bcd3292",
|
||||
"sha256:73a1d6bd01961e9fd447162e137ed949c01bdb830dfca487c4a14e9742dccc93",
|
||||
"sha256:8226a33c542bcb54cd6bd0a366067b610b41713b64c9abec1bc4533d69f51e70",
|
||||
"sha256:888196c9c8893a1e8ff5e89b8f894e7f4f0e64a5af4d8f3c410f0319128bb2f8",
|
||||
"sha256:88c5b4b47a8a138338a07fc94e2ba3b1535f69247670abfe422de4e0b344aae2",
|
||||
"sha256:8a1b2effa96a5f019e72874969394edd393e2fbd6414a8208fea363a22803b45",
|
||||
"sha256:93e1856c8313bc688d5df069e106a4bc962eef3d13372020cc6e3ebf5e045202",
|
||||
"sha256:9501f36fac6b875c124243a379267d879262480bf85b1dbda61f5ad4d01b75a3",
|
||||
"sha256:959665072bd60f45c5b6b5d711f15bdefc9849dd5da9fb6c873e35f5d34d8cfb",
|
||||
"sha256:a1d67d0d53d2a138f9e29d8acdabe11310c185e36f0a848efa104d4e40b808e4",
|
||||
"sha256:a493d470183ee620a3df1e6e55b3e4de8143c0ba1b16f3ded83208ea8ddfd91d",
|
||||
"sha256:a7ccf5825fd71d4542c8ab28d4d482aace885f5ebe4b40faaa290eed8e095a4c",
|
||||
"sha256:a88b7df61a292603e7cd662d92565d915796b094ffb3d206579aaebac6b85d5f",
|
||||
"sha256:a97079b955b00b732c6f280d5023e0eefe359045e8b83b08cf0333af9ec78f26",
|
||||
"sha256:d22fdef58976457c65e2796e6730a3ea4a254f3ba83777ecfc8592ff8d77d303",
|
||||
"sha256:d75f693bb4e92c335e0645e8845e553cd09dc91616412d1d4650da835b5449df",
|
||||
"sha256:d8593f8464fb64d58e8cb0b905b272d40184eac9a18d83cf8c10749c3eafcd7e",
|
||||
"sha256:d8fff0f0c1d8bc5d866762ae95bd99d53282337af1be9dc0d88506b340e74b73",
|
||||
"sha256:de20a212ef3d00d609d0b22eb7cc798d5a69035e81839f549b538eff4105d01c",
|
||||
"sha256:e9e9d4e2e336c529d4c435baad846a181e39a982f823f7e4495ec0b0ec8538d2",
|
||||
"sha256:f058a77ef0ece4e210bb0450e68408d4223f728b109764676e1a13537d056bb0",
|
||||
"sha256:f1a4b358947a65b94e2501ce3e078bbc929b039ede4679ddb0460829b12f7375",
|
||||
"sha256:f9b2cde1cd1b2a10246dbc143ba49d942d14fb3d2b4bccf4618d475c65464912",
|
||||
"sha256:fe3390c538f12437b859d815040763abc728955a52ca6ff9c5d4ac707c4ad98e"
|
||||
],
|
||||
"markers": "python_version >= '3.11'",
|
||||
"version": "==1.14.1"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.22.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
56
README.md
56
README.md
@@ -5,7 +5,7 @@
|
||||

|
||||
[](https://github.com/scito/extract_otp_secrets/blob/master/LICENSE)
|
||||
[](https://github.com/scito/extract_otp_secrets/releases/latest)
|
||||

|
||||

|
||||
[](https://hub.docker.com/repository/docker/scit0/extract_otp_secrets/general)
|
||||
[](https://github.com/scito/extract_otp_secrets/releases/latest)
|
||||
[](https://github.com/scito/extract_otp_secrets/releases/latest)
|
||||
@@ -14,7 +14,7 @@
|
||||
[](https://stand-with-ukraine.pp.ua)
|
||||
<!-- 
|
||||
[](https://github.com/scito/extract_otp_secrets/blob/master/Pipfile.lock)
|
||||
-->
|
||||
-->
|
||||
|
||||
<!-- [](https://GitHub.com/scito/extract_otp_secrets/releases/) -->
|
||||
|
||||
@@ -90,8 +90,8 @@ The secrets can be exported to JSON or CSV, or printed as QR codes to console or
|
||||
## Download and run binary executable (🆕 since v2.1)
|
||||
|
||||
1. Download executable for your platform from [latest release](https://github.com/scito/extract_otp_secrets/releases/latest), see assets
|
||||
2. Linux and macOS: Set executable bit for the downloaded file, e.g in terminal with `chmod +x extract_otp_secrets_OS_vX.X.X`
|
||||
3. Start executable by clicking or from command line (macOS: startable only from command line, see [below](#macOS-application))
|
||||
2. Linux and macOS: Set executable bit for the downloaded file, e.g in terminal with `chmod +x extract_otp_secrets_X.Y.Z_OS_ARCH`
|
||||
3. Start executable by clicking or from command line (macOS: startable only from command line, see [below](#macos))
|
||||
|
||||
:heavy_check_mark: Everything is just packed in one executable.
|
||||
:heavy_check_mark: No installation needed, neither Python nor any dependencies have to be installed.
|
||||
@@ -117,19 +117,17 @@ The secrets can be exported to JSON or CSV, or printed as QR codes to console or
|
||||
However, the bare executable can be executed from the command line:
|
||||
|
||||
1. Download executable for macOS platform from [latest release](https://github.com/scito/extract_otp_secrets/releases/latest), see assets
|
||||
2. Open Terminal application
|
||||
3. Change to Downloads: `cd $HOME/Downloads`
|
||||
4. Set executable bit for the downloaded file: `chmod +x extract_otp_secrets_OS_vX.X.X`
|
||||
5. Start executable from command line: `./extract_otp_secrets_OS_vX.X.X`
|
||||
2. Open `Terminal` application
|
||||
3. Change to Downloads folder in Terminal: `cd $HOME/Downloads`
|
||||
4. Remove quarantine bit for the downloaded file: `xattr -r -d com.apple.quarantine extract_otp_secrets_X.Y.Z_macos_x86_64`
|
||||
5. Set executable bit for the downloaded file: `chmod +x extract_otp_secrets_X.Y.Z_macos_x86_64`
|
||||
6. Start executable from command line: `./extract_otp_secrets_X.Y.Z_macos_x86_64`
|
||||
|
||||
#### Apple Silicon (ARM)
|
||||
:information_source: Replace `X.Y.Z` in above commands with the version number of your downloaded file, e.g. `extract_otp_secrets_2.4.0_macos_x86_64`
|
||||
|
||||
Currently, there is no build for M1 and M2 Apple Silicon processors due to lack of hardware. However, the binary executable should be runnable by Rosetta2 emulation.
|
||||
:information_source: If Rosetta2 emulation is installed, these steps work also for M1 and M2 Apple Silicon processors and the program can be executed directly.
|
||||
|
||||
```
|
||||
arch -x86_64 extract_otp_secrets_OS_vX.X.X
|
||||
```
|
||||
:warning: This command is untested due to lack of hardware.
|
||||
> :warning: It seems the GUI mode is not working in Terminal on macOS. In tests no [GUI window](#usage) was opened. (Remarks and hints about macOS are welcome since I do not know macOS.)
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -215,7 +213,7 @@ For a detailed installation documentation of [pyzbar](https://github.com/Natural
|
||||
|
||||
#### Linux (Fedora)
|
||||
|
||||
sudo dnf install libzbar0
|
||||
sudo dnf install zbar
|
||||
|
||||
#### Linux (Arch Linux)
|
||||
|
||||
@@ -237,7 +235,7 @@ OpenCV requires [Visual C++ redistributable 2015](https://www.microsoft.com/en-u
|
||||
|
||||
## Program help: arguments and options
|
||||
|
||||
<pre>usage: extract_otp_secrets.py [-h] [--csv FILE] [--keepass FILE] [--json FILE] [--txt FILE] [--printqr] [--saveqr DIR] [--camera NUMBER] [--qr {ZBAR,QREADER,QREADER_DEEP,CV2,CV2_WECHAT}] [-i] [--no-color] [--version] [-d | -v | -q] [infile ...]
|
||||
<pre>usage: extract_otp_secrets.py [-h] [--csv FILE] [--keepass FILE] [--json FILE] [--txt FILE] [--urls FILE] [--printqr] [--saveqr DIR] [--camera NUMBER] [--qr {ZBAR,QREADER,QREADER_DEEP,CV2,CV2_WECHAT}] [-i] [--no-color] [--version] [-d | -v | -q] [infile ...]
|
||||
|
||||
Extracts one time password (OTP) secrets from QR codes exported by two-factor authentication (2FA) apps
|
||||
If no infiles are provided, a GUI window starts and QR codes are captured from the camera.
|
||||
@@ -248,10 +246,11 @@ positional arguments:
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--csv FILE, -c FILE export csv file or - for stdout
|
||||
--csv FILE, -c FILE export csv file, or - for stdout
|
||||
--keepass FILE, -k FILE export totp/hotp csv file(s) for KeePass, - for stdout
|
||||
--json FILE, -j FILE export json file or - for stdout
|
||||
--txt FILE, -t FILE export txt file or - for stdout
|
||||
--urls FILE, -u FILE export file with list of otpauth urls, or - for stdout
|
||||
--printqr, -p print QR code(s) as text to the terminal
|
||||
--saveqr DIR, -s DIR save QR code(s) as images to directory
|
||||
--camera NUMBER, -C NUMBER camera number of system (default camera: 0)
|
||||
@@ -350,8 +349,8 @@ python extract_otp_secrets.py = < example_export.png</pre>
|
||||
* Prints errors and warnings to stderr (🆕 since v2.0)
|
||||
* Prints colored output (🆕 since v2.0)
|
||||
* Startable as executable (script, Python, and all dependencies packed in one executable) (🆕 since v2.1)
|
||||
* extract_otp_secrets_linux_x86_64 (requires glibc >= 2.28)
|
||||
* extract_otp_secrets_linux_arm64 (requires glibc >= 2.28)
|
||||
* extract_otp_secrets_linux_x86_64 (requires glibc >= 2.31)
|
||||
* extract_otp_secrets_linux_arm64 (requires glibc >= 2.31)
|
||||
* extract_otp_secrets_win_x86_64.exe
|
||||
* extract_otp_secrets_macos_x86_64 (optional [libzbar](#installation-of-optional-shared-system-libraries-recommended) needs to be installed manually if needed)
|
||||
* extract_otp_secrets_macos_x86_64.dmg N/A, see [why](#macos)
|
||||
@@ -370,7 +369,7 @@ python extract_otp_secrets.py = < example_export.png</pre>
|
||||
* macOS
|
||||
* Windows
|
||||
* Uses UTF-8 on all platforms
|
||||
* Supports Python >= 3.7
|
||||
* Supports Python >= 3.8
|
||||
* Installation of shared system libraries is optional (🆕 since v2.3)
|
||||
* Provides a debug mode (-d) for analyzing import problems
|
||||
* Written in modern Python using type hints and following best practices
|
||||
@@ -688,11 +687,18 @@ Build extract_otp_secrets project
|
||||
Options:
|
||||
-i Interactive mode, all steps must be confirmed
|
||||
-C Ignore version check of protobuf/protoc
|
||||
-D Do not build docker
|
||||
-G Do not start extract_otp_secrets.py in GUI mode
|
||||
-e Build exe
|
||||
-n Build nuitka exe
|
||||
-L Do not build local (exes)
|
||||
-d Build docker
|
||||
-a Build arm
|
||||
-X Do not build x86_64
|
||||
-B Do not build base
|
||||
-V Do not run pipenv
|
||||
-g Start extract_otp_secrets.py in GUI mode
|
||||
-c Clean everything
|
||||
-r Generate result files
|
||||
-h, --help Help
|
||||
-h, --help Show help and quit
|
||||
```
|
||||
|
||||
## Technical background
|
||||
@@ -704,7 +710,7 @@ Command for regeneration of Python code from proto3 message definition file (onl
|
||||
|
||||
protoc --plugin=protoc-gen-mypy=path/to/protoc-gen-mypy --python_out=src/protobuf_generated_python --mypy_out=src/protobuf_generated_python src/google_auth.proto
|
||||
|
||||
The generated protobuf Python code was generated by protoc 22.0 (https://github.com/protocolbuffers/protobuf/releases/tag/v22.0).
|
||||
The generated protobuf Python code was generated by protoc 26.1 (https://github.com/protocolbuffers/protobuf/releases/tag/v26.1).
|
||||
|
||||
For Python type hint generation the [mypy-protobuf](https://github.com/nipunn1313/mypy-protobuf) package is used.
|
||||
|
||||
@@ -748,7 +754,7 @@ FileNotFoundError: Could not find module 'libiconv.dll' (or one of its dependenc
|
||||
## Related projects
|
||||
|
||||
* [ZBar](https://github.com/mchehab/zbar) is an open source software suite for reading bar codes from various sources, including webcams.
|
||||
* [Aegis Authenticator](https://github.com/beemdevelopment/Aegis) is a free, secure and open source 2FA app for Android.
|
||||
* [Aegis Authenticator](https://github.com/beemdevelopment/Aegis) is a free, secure and open source 2FA app for Android. This app can scan Google export QR codes and export the secrets, e.g. as JSON. However, a second device is required.
|
||||
* [pyzbar](https://github.com/NaturalHistoryMuseum/pyzbar) is a good QR code reader Python module
|
||||
* [OpenCV](https://docs.opencv.org/4.x/) (CV2) Open Source Computer Vision library with [opencv-python](https://github.com/opencv/opencv-python)
|
||||
* [Python QReader](https://github.com/Eric-Canas/QReader) Python QR code readers
|
||||
|
||||
751
build.sh
751
build.sh
@@ -77,8 +77,15 @@ interactive=false
|
||||
ignore_version_check=true
|
||||
clean=false
|
||||
clean_flag=""
|
||||
build_docker=true
|
||||
run_gui=true
|
||||
build_base=true
|
||||
build_arm=false
|
||||
build_x86_64=true
|
||||
build_docker=false
|
||||
build_local=true
|
||||
build_exe=false
|
||||
build_nuitka_exe=false
|
||||
run_pipenv=true
|
||||
run_gui=false
|
||||
generate_result_files=false
|
||||
PYTHONHASHSEED=31
|
||||
|
||||
@@ -92,14 +99,21 @@ while test $# -gt 0; do
|
||||
echo "Options:"
|
||||
echo "-i Interactive mode, all steps must be confirmed"
|
||||
echo "-C Ignore version check of protobuf/protoc"
|
||||
echo "-D Do not build docker"
|
||||
echo "-G Do not start extract_otp_secrets.py in GUI mode"
|
||||
echo "-e Build exe"
|
||||
echo "-n Build nuitka exe"
|
||||
echo "-L Do not build local (exe)"
|
||||
echo "-d Build docker"
|
||||
echo "-a Build arm"
|
||||
echo "-X Do not build x86_64"
|
||||
echo "-B Do not build base"
|
||||
echo "-V Do not run pipenv"
|
||||
echo "-g Start extract_otp_secrets.py in GUI mode"
|
||||
echo "-c Clean everything"
|
||||
echo "-r Generate result files"
|
||||
echo "-h, --help Help"
|
||||
echo "-h, --help Show help and quit"
|
||||
quit
|
||||
;;
|
||||
-a)
|
||||
-i)
|
||||
interactive=true
|
||||
shift
|
||||
;;
|
||||
@@ -107,12 +121,41 @@ while test $# -gt 0; do
|
||||
ignore_version_check=false
|
||||
shift
|
||||
;;
|
||||
-D)
|
||||
build_docker=false
|
||||
-B)
|
||||
build_base=false
|
||||
shift
|
||||
;;
|
||||
-G)
|
||||
run_gui=false
|
||||
-L)
|
||||
build_local=false
|
||||
build_base=false
|
||||
shift
|
||||
;;
|
||||
-a)
|
||||
build_arm=true
|
||||
shift
|
||||
;;
|
||||
-X)
|
||||
build_x86_64=false
|
||||
shift
|
||||
;;
|
||||
-e)
|
||||
build_exe=true
|
||||
shift
|
||||
;;
|
||||
-n)
|
||||
build_nuitka_exe=true
|
||||
shift
|
||||
;;
|
||||
-d)
|
||||
build_docker=true
|
||||
shift
|
||||
;;
|
||||
-V)
|
||||
run_pipenv=false
|
||||
shift
|
||||
;;
|
||||
-g)
|
||||
run_gui=true
|
||||
shift
|
||||
;;
|
||||
-r)
|
||||
@@ -174,288 +217,242 @@ if $clean; then
|
||||
cmd="sudo pipenv --rm || true"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
cmd="$PIP install --use-pep517 -U -r requirements-dev.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
|
||||
echo -e "\n\nChecking Protoc version..."
|
||||
VERSION=$(curl -sL https://github.com/protocolbuffers/protobuf/releases/latest | grep -E "<title>" | perl -pe's%.*Protocol Buffers v(\d+\.\d+(\.\d+)?).*%\1%')
|
||||
BASEVERSION=4
|
||||
echo
|
||||
|
||||
OLDVERSION=$(cat $BIN/$DEST/.VERSION.txt || echo "")
|
||||
echo -e "\nProtoc remote version $VERSION\n"
|
||||
echo -e "Protoc local version: $OLDVERSION\n"
|
||||
|
||||
if [ "$OLDVERSION" != "$VERSION" ] || ! $ignore_version_check; then
|
||||
echo "Upgrade protoc from $OLDVERSION to $VERSION"
|
||||
|
||||
NAME="protoc-$VERSION"
|
||||
ARCHIVE="$NAME.zip"
|
||||
|
||||
mkdir -p $DOWNLOADS
|
||||
# https://github.com/protocolbuffers/protobuf/releases/download/v21.6/protoc-21.6-linux-x86_64.zip
|
||||
cmd="wget --trust-server-names https://github.com/protocolbuffers/protobuf/releases/download/v$VERSION/protoc-$VERSION-linux-x86_64.zip -O $DOWNLOADS/$ARCHIVE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="echo -e '\nSize [Byte]'; stat --printf='%s\n' $DOWNLOADS/$ARCHIVE; echo -e '\nMD5'; md5sum $DOWNLOADS/$ARCHIVE; echo -e '\nSHA256'; sha256sum $DOWNLOADS/$ARCHIVE;"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="mkdir -p $BIN/$NAME; unzip $DOWNLOADS/$ARCHIVE -d $BIN/$NAME"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="echo $VERSION > $BIN/$NAME/.VERSION.txt; echo $VERSION > $BIN/$NAME/.VERSION_$VERSION.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="[ -d $BIN/$DEST.old ] && rm -rf $BIN/$DEST.old || echo 'No old dir to delete'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="[ -d $BIN/$DEST ] && mv -iT $BIN/$DEST $BIN/$DEST.old || echo 'No previous dir to keep'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="mv -iT $BIN/$NAME $BIN/$DEST"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="rm $DOWNLOADS/$ARCHIVE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="$BIN/$DEST/bin/protoc --plugin=protoc-gen-mypy=$HOME/.local/bin/protoc-gen-mypy --python_out=src/protobuf_generated_python --mypy_out=src/protobuf_generated_python --proto_path=src google_auth.proto"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Update README.md
|
||||
|
||||
cmd="perl -i -pe 's%proto(buf|c)([- ])(\d\.)?$OLDVERSION%proto\$1\$2\${3}$VERSION%g' README.md && perl -i -pe 's%(protobuf/releases/tag/v)$OLDVERSION%\${1}$VERSION%g' README.md"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
else
|
||||
echo -e "\nVersion has not changed. Quit"
|
||||
fi
|
||||
|
||||
|
||||
# Upgrade pip requirements
|
||||
|
||||
cmd="pip install -U pip"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
$PIP --version
|
||||
|
||||
cmd="$PIP install --use-pep517 -U -r requirements.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Lint
|
||||
|
||||
LINT_OUT_FILE="tests/reports/flake8_results.txt"
|
||||
cmd="$FLAKE8 . --count --select=E9,F63,F7,F82 --show-source --statistics | tee $LINT_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="$FLAKE8 . --count --exit-zero --max-complexity=10 --max-line-length=200 --statistics --exclude=.git,__pycache__,docs/source/conf.py,old,build,dist,protobuf_generated_python | tee -a $LINT_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Type checking
|
||||
|
||||
TYPE_CHECK_OUT_FILE="tests/reports/mypy_results.txt"
|
||||
cmd="$MYPY --install-types --non-interactive src/*.py tests/*.py"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# change to src as python -m mypy adds the current dir Python sys.path
|
||||
# execute in a subshell in order not to loose the exit code and not to change the dir in the currrent shell
|
||||
cmd="$MYPY --strict src/*.py tests/*.py | tee $TYPE_CHECK_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
|
||||
# Generate results files
|
||||
|
||||
if $generate_result_files; then
|
||||
cmd="for color in '' '-n'; do for level in '' '-v' '-vv' '-vvv'; do $PYTHON src/extract_otp_secrets.py example_export.txt \$color \$level > tests/data/print_verbose_output\$color\$level.txt; done; done"
|
||||
cmd="mkdir -p dist"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
# pip -e install
|
||||
|
||||
cmd="$PIP install -U -e ."
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="extract_otp_secrets example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="extract_otp_secrets - < example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Test (needs module)
|
||||
|
||||
cmd="$PYTHON src/extract_otp_secrets.py example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="$PYTHON src/extract_otp_secrets.py - < example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
COVERAGE_OUT_FILE="tests/reports/pytest-coverage.txt"
|
||||
cmd="pytest --cov=extract_otp_secrets_test --junitxml=tests/reports/pytest.xml --cov-report html:tests/reports/html --cov-report=term-missing tests/ | tee $COVERAGE_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Pipenv
|
||||
|
||||
cmd="$PIP install -U pipenv"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
$PIPENV --version
|
||||
|
||||
cmd="$PIPENV update && $PIPENV --rm && $PIPENV install"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
$PIPENV run python --version
|
||||
|
||||
cmd="$PIPENV run pytest --cov=extract_otp_secrets_test tests/"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build wheel
|
||||
|
||||
cmd="$PIP wheel ."
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build executable
|
||||
|
||||
cmd="LOCAL_GLIBC_VERSION=$(ldd --version | sed '1!d' | sed -E 's/.* ([[:digit:]]+\.[[:digit:]]+)$/\1/')"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
echo "local glibc: $LOCAL_GLIBC_VERSION"
|
||||
|
||||
cmd="pyinstaller -y --specpath installer --add-data $HOME/.local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile $clean_flag src/extract_otp_secrets.py"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets -h"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Generate README.md TOC
|
||||
|
||||
cmd="gfm-toc -s 2 -e 3 -t -o README.md > docs/README_TOC.md"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Update Code Coverage in README.md
|
||||
|
||||
# https://github.com/marketplace/actions/pytest-coverage-comment
|
||||
# Coverage-95%25-yellowgreen
|
||||
echo -e "Update code coverage in README.md"
|
||||
TOTAL_COVERAGE=$(cat $COVERAGE_OUT_FILE | grep 'TOTAL' | perl -ne 'print "$&" if /\b(\d{1,3})%/') && perl -i -pe "s/coverage-(\d{1,3}%)25-/coverage-${TOTAL_COVERAGE}25-/" README.md
|
||||
|
||||
if $build_docker; then
|
||||
# Build docker
|
||||
|
||||
# Build Dockerfile_only_txt (Alpine)
|
||||
cmd="docker build . -t extract_otp_secrets_only_txt -t extract_otp_secrets:only-txt -t extract_otp_secrets:alpine -f docker/Dockerfile_only_txt --pull --build-arg RUN_TESTS=false"
|
||||
if $build_local; then
|
||||
cmd="$PIP install --use-pep517 -U -r requirements-dev.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -v \"$(pwd)\":/files:ro extract_otp_secrets_only_txt example_export.txt"
|
||||
echo -e "\n\nChecking Protoc version..."
|
||||
VERSION=$(curl -sL https://github.com/protocolbuffers/protobuf/releases/latest | grep -E "<title>" | perl -pe's%.*Protocol Buffers v(\d+\.\d+(\.\d+)?).*%\1%')
|
||||
BASEVERSION=4
|
||||
echo
|
||||
|
||||
OLDVERSION=$(cat $BIN/$DEST/.VERSION.txt || echo "")
|
||||
echo -e "\nProtoc remote version $VERSION\n"
|
||||
echo -e "Protoc local version: $OLDVERSION\n"
|
||||
|
||||
if [ "$OLDVERSION" != "$VERSION" ] || ! $ignore_version_check; then
|
||||
echo "Upgrade protoc from $OLDVERSION to $VERSION"
|
||||
|
||||
NAME="protoc-$VERSION"
|
||||
ARCHIVE="$NAME.zip"
|
||||
|
||||
mkdir -p $DOWNLOADS
|
||||
# https://github.com/protocolbuffers/protobuf/releases/download/v21.6/protoc-21.6-linux-x86_64.zip
|
||||
cmd="wget --trust-server-names https://github.com/protocolbuffers/protobuf/releases/download/v$VERSION/protoc-$VERSION-linux-x86_64.zip -O $DOWNLOADS/$ARCHIVE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="echo -e '\nSize [Byte]'; stat --printf='%s\n' $DOWNLOADS/$ARCHIVE; echo -e '\nMD5'; md5sum $DOWNLOADS/$ARCHIVE; echo -e '\nSHA256'; sha256sum $DOWNLOADS/$ARCHIVE;"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="mkdir -p $BIN/$NAME; unzip $DOWNLOADS/$ARCHIVE -d $BIN/$NAME"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="echo $VERSION > $BIN/$NAME/.VERSION.txt; echo $VERSION > $BIN/$NAME/.VERSION_$VERSION.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="[ -d $BIN/$DEST.old ] && rm -rf $BIN/$DEST.old || echo 'No old dir to delete'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="[ -d $BIN/$DEST ] && mv -iT $BIN/$DEST $BIN/$DEST.old || echo 'No previous dir to keep'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="mv -iT $BIN/$NAME $BIN/$DEST"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="rm $DOWNLOADS/$ARCHIVE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="$BIN/$DEST/bin/protoc --plugin=protoc-gen-mypy=$HOME/.local/bin/protoc-gen-mypy --python_out=src/protobuf_generated_python --mypy_out=src/protobuf_generated_python --proto_path=src google_auth.proto"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Update README.md
|
||||
|
||||
cmd="perl -i -pe 's%proto(buf|c)([- ])(\d\.)?$OLDVERSION%proto\$1\$2\${3}$VERSION%g' README.md && perl -i -pe 's%(protobuf/releases/tag/v)$OLDVERSION%\${1}$VERSION%g' README.md"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
else
|
||||
echo -e "\nVersion has not changed. Quit"
|
||||
fi
|
||||
|
||||
# Upgrade pip requirements
|
||||
|
||||
cmd="pip install -U pip"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets_only_txt - < example_export.txt"
|
||||
$PIP --version
|
||||
|
||||
cmd="$PIP install --use-pep517 -U -r requirements.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v \"$(pwd)\":/files:ro extract_otp_secrets_only_txt extract_otp_secrets_test.py -k 'not qreader' -vvv --relaxed"
|
||||
if $build_base; then
|
||||
# Lint
|
||||
|
||||
LINT_OUT_FILE="tests/reports/flake8_results.txt"
|
||||
cmd="$FLAKE8 . --count --select=E9,F63,F7,F82 --show-source --statistics | tee $LINT_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="$FLAKE8 . --count --exit-zero --max-complexity=10 --max-line-length=200 --statistics --exclude=.git,__pycache__,docs/source/conf.py,old,build,dist,protobuf_generated_python | tee -a $LINT_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Type checking
|
||||
|
||||
TYPE_CHECK_OUT_FILE="tests/reports/mypy_results.txt"
|
||||
cmd="$MYPY --install-types --non-interactive src/*.py tests/*.py"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# change to src as python -m mypy adds the current dir Python sys.path
|
||||
# execute in a subshell in order not to loose the exit code and not to change the dir in the currrent shell
|
||||
cmd="$MYPY --strict src/*.py tests/*.py | tee $TYPE_CHECK_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
|
||||
# Generate results files
|
||||
|
||||
if $generate_result_files; then
|
||||
cmd="for color in '' '-n'; do for level in '' '-v' '-vv' '-vvv'; do $PYTHON src/extract_otp_secrets.py example_export.txt \$color \$level > tests/data/print_verbose_output\$color\$level.txt; done; done"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
# pip -e install
|
||||
|
||||
cmd="$PIP install -U -e ."
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="extract_otp_secrets example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="extract_otp_secrets - < example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Test (needs module)
|
||||
|
||||
cmd="$PYTHON src/extract_otp_secrets.py example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="$PYTHON src/extract_otp_secrets.py - < example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
COVERAGE_OUT_FILE="tests/reports/pytest-coverage.txt"
|
||||
cmd="pytest --cov=extract_otp_secrets_test --junitxml=tests/reports/pytest.xml --cov-report html:tests/reports/html --cov-report=term-missing tests/ | tee $COVERAGE_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Pipenv
|
||||
|
||||
if $run_pipenv; then
|
||||
cmd="$PIP install -U pipenv"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
$PIPENV --version
|
||||
|
||||
cmd="$PIPENV --rm && $PIPENV update && $PIPENV install"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
$PIPENV run python --version
|
||||
|
||||
cmd="$PIPENV run pytest --cov=extract_otp_secrets_test tests/"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
# Build wheel
|
||||
|
||||
cmd="$PIP wheel ."
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
# Build executable
|
||||
if $build_exe; then
|
||||
cmd="LOCAL_GLIBC_VERSION=$(ldd --version | sed '1!d' | sed -E 's/.* ([[:digit:]]+\.[[:digit:]]+)$/\1/')"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
echo "local glibc: $LOCAL_GLIBC_VERSION"
|
||||
|
||||
cmd="pyinstaller -y --specpath installer --add-data $HOME/.local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile $clean_flag src/extract_otp_secrets.py"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets -h"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets --qr ZBAR example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
# Build compiled executable
|
||||
|
||||
if $build_nuitka_exe; then
|
||||
cmd="LOCAL_GLIBC_VERSION=$(ldd --version | sed '1!d' | sed -E 's/.* ([[:digit:]]+\.[[:digit:]]+)$/\1/')"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
echo "local glibc: $LOCAL_GLIBC_VERSION"
|
||||
|
||||
cmd="$PIP install -U pyqt5"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="$PYTHON -m nuitka --enable-plugin=tk-inter --enable-plugin=pyqt5 --include-data-dir=$HOME/.local/__yolo_v3_qr_detector/=__yolo_v3_qr_detector/ --onefile --output-dir=build/nuitka --output-filename=extract_otp_secrets_compiled src/extract_otp_secrets.py"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="cp build/nuitka/extract_otp_secrets_compiled dist/"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets_compiled -h"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets_compiled --qr ZBAR example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
# Generate README.md TOC
|
||||
|
||||
cmd="gfm-toc -s 2 -e 3 -t -o README.md > docs/README_TOC.md"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build extract_otp_secrets (Debian Bullseye)
|
||||
cmd="docker build . -t extract_otp_secrets -t extract_otp_secrets:bullseye --pull -f docker/Dockerfile --build-arg RUN_TESTS=false"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
# Update Code Coverage in README.md
|
||||
|
||||
cmd="docker run --rm -v \"$(pwd)\":/files:ro extract_otp_secrets example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="cat example_export.txt | docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets - -c - > example_output.csv"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets = < example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v \"$(pwd)\":/files:ro extract_otp_secrets"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build extract_otp_secrets (Debian Buster)
|
||||
cmd="docker build . -t extract_otp_secrets:buster --pull -f docker/Dockerfile --build-arg RUN_TESTS=false --build-arg BASE_IMAGE=python:3.11-slim-buster"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -v \"$(pwd)\":/files:ro extract_otp_secrets:buster example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="cat example_export.txt | docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets:buster - -c - > example_output.csv"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets:buster = < example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v \"$(pwd)\":/files:ro extract_otp_secrets:buster"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build executable from Docker latest
|
||||
# sed "1!d" is workaround for head -n 1 since it head procduces exit code != 0
|
||||
BULLSEYE_GLIBC_VERSION=$(docker run --entrypoint /bin/bash --rm extract_otp_secrets -c 'ldd --version | sed "1!d" | sed -E "s/.* ([[:digit:]]+\.[[:digit:]]+)$/\1/"')
|
||||
echo "Bullseye glibc: $BULLSEYE_GLIBC_VERSION"
|
||||
|
||||
cmd="docker run --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets -c 'apt-get update && apt-get -y install binutils && pip install -U pip && pip install -U -r /files/requirements.txt && pip install pyinstaller && PYTHONHASHSEED=31 && pyinstaller -y --specpath installer --add-data /usr/local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile --name extract_otp_secrets_linux_x86_64_bullseye --distpath /files/dist/ /files/src/extract_otp_secrets.py'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets_linux_x86_64_bullseye -h"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build executable from Docker buster
|
||||
BUSTER_GLIBC_VERSION=$(docker run --entrypoint /bin/bash --rm extract_otp_secrets:buster -c 'ldd --version | sed "1!d" | sed -E "s/.* ([[:digit:]]+\.[[:digit:]]+)$/\1/"')
|
||||
echo "Bullseye glibc: $BUSTER_GLIBC_VERSION"
|
||||
|
||||
cmd="docker run --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets:buster -c 'apt-get update && apt-get -y install binutils && pip install -U pip && pip install -U -r /files/requirements.txt && pip install pyinstaller && PYTHONHASHSEED=31 && pyinstaller -y --specpath installer --add-data /usr/local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile --name extract_otp_secrets_linux_x86_64 --distpath /files/dist/ /files/src/extract_otp_secrets.py'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets_linux_x86_64 -h"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
# https://github.com/marketplace/actions/pytest-coverage-comment
|
||||
# Coverage-95%25-yellowgreen
|
||||
echo -e "Update code coverage in README.md"
|
||||
TOTAL_COVERAGE=$(cat $COVERAGE_OUT_FILE | grep 'TOTAL' | perl -ne 'print "$&" if /\b(\d{1,3})%/') && perl -i -pe "s/coverage-(\d{1,3}%)25-/coverage-${TOTAL_COVERAGE}25-/" README.md
|
||||
|
||||
# create Windows win_file_version_info.txt
|
||||
cmd="VERSION_STR=$(setuptools-git-versioning) VERSION_MAJOR=$(cut -d '.' -f 1 <<< "$(setuptools-git-versioning)") VERSION_MINOR=$(cut -d '.' -f 2 <<< "$(setuptools-git-versioning)") VERSION_PATCH=$(cut -d '.' -f 3 <<< "$(setuptools-git-versioning)") VERSION_BUILD=$(($(git rev-list --count $(git tag | sort -V -r | sed '1!d')..HEAD))) COPYRIGHT_YEARS='2020-2023' envsubst < installer/win_file_version_info_template.txt > build/win_file_version_info.txt"
|
||||
@@ -466,27 +463,189 @@ if $build_docker; then
|
||||
cmd="VERSION_STR=$(setuptools-git-versioning) COPYRIGHT_YEARS='2020-2023' envsubst < installer/extract_otp_secrets_macos_template.spec > build/extract_otp_secrets_macos.spec"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
# build linux/arm64
|
||||
# Build extract_otp_secrets (Debian Buster)
|
||||
cmd="docker buildx build --platform=linux/arm64 . -t extract_otp_secrets:buster --pull -f docker/Dockerfile --build-arg RUN_TESTS=false --build-arg BASE_IMAGE=python:3.11-slim-buster"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
if $build_docker; then
|
||||
# Build docker
|
||||
|
||||
cmd="docker run --pull always --rm --privileged multiarch/qemu-user-static --reset -p yes"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
if $build_x86_64; then
|
||||
# Build Dockerfile_only_txt (Alpine)
|
||||
cmd="docker build . -t extract_otp_secrets_only_txt -t extract_otp_secrets:only-txt -t extract_otp_secrets:alpine -f docker/Dockerfile_only_txt --pull --build-arg RUN_TESTS=false"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --platform linux/arm64 --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets:buster -c 'apt-get update && apt-get -y install binutils && pip install -U pip && pip install -U -r /files/requirements.txt && pip install pyinstaller && PYTHONHASHSEED=31 && pyinstaller --specpath installer -y --add-data /usr/local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile --name extract_otp_secrets_linux_arm64 --distpath /files/dist/ /files/src/extract_otp_secrets.py'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
cmd="docker run --rm -v \"$(pwd)\":/files:ro extract_otp_secrets_only_txt example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="PLATFORM='linux/arm64' && EXE='dist/extract_otp_secrets_linux_arm64' && docker run --platform \"\$PLATFORM\" --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets:buster -c \"\$EXE -V && \$EXE -h && \$EXE example_export.png && \$EXE - < example_export.txt && \$EXE --qr ZBAR example_export.png && \$EXE --qr QREADER example_export.png && \$EXE --qr QREADER_DEEP example_export.png && \$EXE --qr CV2 example_export.png && \$EXE --qr CV2_WECHAT example_export.png\""
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
cmd="docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets_only_txt - < example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v \"$(pwd)\":/files:ro extract_otp_secrets_only_txt extract_otp_secrets_test.py -k 'not qreader' -vvv --relaxed"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build extract_otp_secrets (Debian Bookworm)
|
||||
cmd="docker build . -t extract_otp_secrets -t extract_otp_secrets:bookworm --pull -f docker/Dockerfile --build-arg RUN_TESTS=false"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -v \"$(pwd)\":/files:ro extract_otp_secrets example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="cat example_export.txt | docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets - -c - > example_output.csv"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets = < example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v \"$(pwd)\":/files:ro extract_otp_secrets"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build extract_otp_secrets (Debian Bullseye)
|
||||
cmd="docker build . -t extract_otp_secrets:bullseye -t extract_otp_secrets:bullseye-x86_64 --pull -f docker/Dockerfile --build-arg RUN_TESTS=false --build-arg BASE_IMAGE=python:3.12-slim-bullseye"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -v \"$(pwd)\":/files:ro extract_otp_secrets:bullseye example_export.txt"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="cat example_export.txt | docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets:bullseye - -c - > example_output.csv"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets:bullseye = < example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --entrypoint /extract/run_pytest.sh --rm -v \"$(pwd)\":/files:ro extract_otp_secrets:bullseye"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build executable from Docker latest
|
||||
# sed "1!d" is workaround for head -n 1 since it head procduces exit code != 0
|
||||
BOOKWORM_GLIBC_VERSION=$(docker run --entrypoint /bin/bash --rm extract_otp_secrets -c 'ldd --version | sed "1!d" | sed -E "s/.* ([[:digit:]]+\.[[:digit:]]+)$/\1/"')
|
||||
echo "Bookworm glibc: $BOOKWORM_GLIBC_VERSION"
|
||||
fi
|
||||
|
||||
if $build_arm; then
|
||||
# build linux/arm64
|
||||
cmd="docker run --pull always --rm --privileged multiarch/qemu-user-static --reset -p yes"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build extract_otp_secrets (Debian Bullseye)
|
||||
cmd="docker buildx build --platform=linux/arm64 . -t extract_otp_secrets:bullseye-arm64 --pull -f docker/Dockerfile --build-arg RUN_TESTS=false --build-arg BASE_IMAGE=python:3.12-slim-bullseye"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
if $build_exe; then
|
||||
if $build_x86_64; then
|
||||
cmd="docker run --platform linux/amd64 --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets -c 'apt-get update && apt-get -y install binutils && pip install -U pip && pip install -U -r /files/requirements.txt && pip install pyinstaller && PYTHONHASHSEED=31 && pyinstaller -y --specpath installer --add-data /usr/local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile --name extract_otp_secrets_linux_x86_64_bookworm --distpath /files/dist/ /files/src/extract_otp_secrets.py'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets_linux_x86_64_bookworm -h || echo 'Could not run exe; see error message above'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets_linux_x86_64_bookworm --qr ZBAR example_export.png || echo 'Could not run exe; see error message above'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build executable from Docker bullseye
|
||||
BULLSEYE_GLIBC_VERSION=$(docker run --entrypoint /bin/bash --rm extract_otp_secrets:bullseye -c 'ldd --version | sed "1!d" | sed -E "s/.* ([[:digit:]]+\.[[:digit:]]+)$/\1/"')
|
||||
echo "Bullseye glibc: $BULLSEYE_GLIBC_VERSION"
|
||||
|
||||
cmd="docker run --platform linux/amd64 --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets:bullseye -c 'apt-get update && apt-get -y install binutils && pip install -U pip && pip install -U -r /files/requirements.txt && pip install pyinstaller && PYTHONHASHSEED=31 && pyinstaller -y --specpath installer --add-data /usr/local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile --name extract_otp_secrets_linux_x86_64 --distpath /files/dist/ /files/src/extract_otp_secrets.py'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets_linux_x86_64 -h"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="dist/extract_otp_secrets_linux_x86_64 --qr ZBAR example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
if $build_arm; then
|
||||
# build linux/arm64
|
||||
cmd="docker run --platform linux/arm64 --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets:bullseye-arm64 -c 'apt-get update && apt-get -y install binutils && pip install -U pip && pip install -U -r /files/requirements.txt && pip install pyinstaller && PYTHONHASHSEED=31 && pyinstaller --specpath installer -y --add-data /usr/local/__yolo_v3_qr_detector/:__yolo_v3_qr_detector/ --onefile --name extract_otp_secrets_linux_arm64 --distpath /files/dist/ /files/src/extract_otp_secrets.py'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="PLATFORM='linux/arm64' && EXE='dist/extract_otp_secrets_linux_arm64' && docker run --platform \"\$PLATFORM\" --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets:bullseye-arm64 -c \"\$EXE -V && \$EXE -h && \$EXE example_export.png && \$EXE - < example_export.txt && \$EXE --qr ZBAR example_export.png && \$EXE --qr QREADER example_export.png && \$EXE --qr QREADER_DEEP example_export.png && \$EXE --qr CV2 example_export.png && \$EXE --qr CV2_WECHAT example_export.png\""
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
fi
|
||||
|
||||
if $build_nuitka_exe; then
|
||||
if $build_x86_64; then
|
||||
cmd="docker run --platform linux/amd64 --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets -c 'apt-get update && apt-get -y install binutils build-essential patchelf && pip install -U pip && pip install -U -r /files/requirements.txt && pip install nuitka pyqt5 && PYTHONHASHSEED=31 && python -m nuitka --enable-plugin=tk-inter --enable-plugin=pyqt5 --include-data-dir=/usr/local/__yolo_v3_qr_detector/=__yolo_v3_qr_detector/ --onefile --output-dir=/files/build/docker/nuitka --output-filename=extract_otp_secrets_linux_x86_64_bookworm_compiled /files/src/extract_otp_secrets.py'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="build/docker/nuitka/extract_otp_secrets_linux_x86_64_bookworm_compiled -h"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="build/docker/nuitka/extract_otp_secrets_linux_x86_64_bookworm_compiled --qr ZBAR example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="cp build/docker/nuitka/extract_otp_secrets_linux_x86_64_bookworm_compiled dist/"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
# Build executable from Docker bullseye
|
||||
BULLSEYE_GLIBC_VERSION=$(docker run --entrypoint /bin/bash --rm extract_otp_secrets:bullseye -c 'ldd --version | sed "1!d" | sed -E "s/.* ([[:digit:]]+\.[[:digit:]]+)$/\1/"')
|
||||
echo "Bookworm glibc: $BULLSEYE_GLIBC_VERSION"
|
||||
|
||||
cmd="docker run --platform linux/amd64 --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets:bullseye -c 'apt-get update && apt-get -y install binutils build-essential patchelf && pip install -U pip && pip install -U -r /files/requirements.txt && pip install nuitka pyqt5 && PYTHONHASHSEED=31 && python -m nuitka --enable-plugin=tk-inter --enable-plugin=pyqt5 --include-data-dir=/usr/local/__yolo_v3_qr_detector/=__yolo_v3_qr_detector/ --onefile --output-dir=/files/build/docker/nuitka --output-filename=extract_otp_secrets_linux_x86_64_bullseye_compiled /files/src/extract_otp_secrets.py'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="build/docker/nuitka/extract_otp_secrets_linux_x86_64_bullseye_compiled -h"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="build/docker/nuitka/extract_otp_secrets_linux_x86_64_bullseye_compiled --qr ZBAR example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="cp build/docker/nuitka/extract_otp_secrets_linux_x86_64_bullseye_compiled dist/"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
if $build_arm; then
|
||||
# build linux/arm64
|
||||
cmd="docker run --platform linux/arm64 --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets:bullseye-arm64 -c 'apt-get update && apt-get -y install binutils build-essential patchelf qt5-default && pip install -U pip && pip install -U -r /files/requirements.txt && pip install nuitka pyqt5 && PYTHONHASHSEED=31 && python -m nuitka --enable-plugin=tk-inter --enable-plugin=pyqt5 --include-data-dir=/usr/local/__yolo_v3_qr_detector/=__yolo_v3_qr_detector/ --onefile --output-dir=/files/build/docker/nuitka --output-filename=extract_otp_secrets_linux_arm64_compiled /files/src/extract_otp_secrets.py'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="PLATFORM='linux/arm64' && EXE='build/docker/nuitka/extract_otp_secrets_linux_arm64_compiled' && docker run --platform \"\$PLATFORM\" --entrypoint /bin/bash --rm -v \"$(pwd)\":/files -w /files extract_otp_secrets:bullseye-arm64 -c \"\$EXE -V && \$EXE -h && \$EXE example_export.png && \$EXE - < example_export.txt && \$EXE --qr ZBAR example_export.png && \$EXE --qr QREADER example_export.png && \$EXE --qr QREADER_DEEP example_export.png && \$EXE --qr CV2 example_export.png && \$EXE --qr CV2_WECHAT example_export.png\""
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="cp build/docker/nuitka/extract_otp_secrets_linux_arm64_compiled dist/"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Run GUI from Docker
|
||||
if $run_gui; then
|
||||
if $build_x86_64 && $run_gui; then
|
||||
cmd="docker run --rm -v "$(pwd)":/files:ro --device=\"/dev/video0:/dev/video0\" --env=\"DISPLAY\" -v /tmp/.X11-unix:/tmp/.X11-unix:ro extract_otp_secrets &"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
@@ -499,14 +658,18 @@ if $run_gui; then
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
line=$(printf '#%.0s' $(eval echo {1..$(( ($COLUMNS - 10) / 2))}))
|
||||
echo -e "\n${blueBold}$line RESULTS $line${reset}"
|
||||
if $build_base; then
|
||||
line=$(printf '#%.0s' $(eval echo {1..$(( ($COLUMNS - 10) / 2))}))
|
||||
echo -e "\n${blueBold}$line RESULTS $line${reset}"
|
||||
|
||||
cmd="cat $TYPE_CHECK_OUT_FILE $LINT_OUT_FILE $COVERAGE_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
cmd="cat $TYPE_CHECK_OUT_FILE $LINT_OUT_FILE $COVERAGE_OUT_FILE"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
line=$(printf '#%.0s' $(eval echo {1..$(( ($COLUMNS - 10) / 2))}))
|
||||
echo -e "\n${greenBold}$line SUCCESS $line${reset}"
|
||||
|
||||
git status
|
||||
|
||||
quit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# --build-arg BASE_IMAGE=python:3.11-slim-buster
|
||||
ARG BASE_IMAGE=python:3.11-slim-bullseye
|
||||
ARG BASE_IMAGE=python:3.12-slim-bookworm
|
||||
FROM $BASE_IMAGE
|
||||
|
||||
# https://docs.docker.com/engine/reference/builder/
|
||||
@@ -23,7 +23,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libzbar0 \
|
||||
python3-tk \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& pip install --no-cache-dir -U -r requirements.txt \
|
||||
&& pip install --no-cache-dir -U pip -r requirements.txt \
|
||||
&& if [ "$RUN_TESTS" = "true" ]; then /extract/run_pytest.sh; else echo "Not running tests..."; fi \
|
||||
&& echo 'test -s /extract/.alias && . /extract/.alias || true' >> ~/.bashrc
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ARG BASE_IMAGE=python:3.11-alpine
|
||||
ARG BASE_IMAGE=python:3.12-alpine
|
||||
FROM $BASE_IMAGE
|
||||
|
||||
# https://docs.docker.com/engine/reference/builder/
|
||||
@@ -30,6 +30,7 @@ RUN apk add --no-cache \
|
||||
zlib-dev \
|
||||
; fi \
|
||||
&& pip install --no-cache-dir -U \
|
||||
pip \
|
||||
colorama \
|
||||
Pillow \
|
||||
protobuf \
|
||||
|
||||
3
docs/meta.md
Normal file
3
docs/meta.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#scito/extract_otp_secrets&Date)
|
||||
@@ -1,8 +1,11 @@
|
||||
[build-system]
|
||||
requires = [
|
||||
"setuptools>=64.0.0", "wheel>=0.37.0", "pip",
|
||||
"pip",
|
||||
"nuitka",
|
||||
# https://setuptools-git-versioning.readthedocs.io/en/latest/differences.html
|
||||
"setuptools>=64.0.0",
|
||||
"setuptools-git-versioning",
|
||||
"wheel>=0.37.0",
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
@@ -44,9 +47,6 @@ dependencies = [
|
||||
"pyzbar",
|
||||
"qrcode",
|
||||
"qreader<2.0.0",
|
||||
# workaround for PYTHON <= 3.7: compatibility
|
||||
"typing_extensions; python_version<='3.7'",
|
||||
"importlib_metadata; python_version<='3.7'",
|
||||
]
|
||||
description = "Extracts one time password (OTP) secrets from QR codes exported by two-factor authentication (2FA) apps such as 'Google Authenticator'"
|
||||
dynamic = ["version"]
|
||||
|
||||
@@ -3,6 +3,7 @@ flake8
|
||||
gfm-toc
|
||||
mypy
|
||||
mypy-protobuf
|
||||
nuitka
|
||||
pyinstaller
|
||||
pylint
|
||||
pytest
|
||||
|
||||
@@ -43,35 +43,24 @@ import re
|
||||
import sys
|
||||
import urllib.parse as urlparse
|
||||
from enum import Enum, IntEnum
|
||||
from typing import Any, List, Optional, Sequence, TextIO, Tuple, Union, TYPE_CHECKING
|
||||
from importlib.metadata import PackageNotFoundError, version
|
||||
from typing import (Any, Final, List, Optional, Sequence, TextIO, Tuple,
|
||||
TypedDict, Union)
|
||||
|
||||
import colorama
|
||||
from pkg_resources import DistributionNotFound, get_distribution
|
||||
from qrcode import QRCode # type: ignore
|
||||
|
||||
import protobuf_generated_python.google_auth_pb2 as pb
|
||||
|
||||
# workaround for PYTHON <= 3.7: compatibility
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import Final, TypedDict
|
||||
else:
|
||||
from typing_extensions import Final, TypedDict
|
||||
|
||||
# workaround for PYTHON <= 3.7: compatibility
|
||||
if sys.version_info >= (3, 8):
|
||||
from importlib.metadata import PackageNotFoundError, version
|
||||
else:
|
||||
from importlib_metadata import PackageNotFoundError, version
|
||||
|
||||
|
||||
debug_mode = '-d' in sys.argv[1:] or '--debug' in sys.argv[1:]
|
||||
quiet = '-q' in sys.argv[1:] or '--quiet' in sys.argv[1:]
|
||||
headless: bool = False
|
||||
|
||||
|
||||
try:
|
||||
import cv2 # type: ignore # TODO use cv2 types if available
|
||||
import numpy as np # TODO use numpy types if available
|
||||
import cv2
|
||||
import numpy as np
|
||||
import cv2.typing
|
||||
|
||||
try:
|
||||
import tkinter
|
||||
@@ -87,9 +76,8 @@ try:
|
||||
except Exception as e:
|
||||
if not quiet:
|
||||
print(f"""
|
||||
WARN: Cannot import pyzbar or qreader module. This problem is probably due to the missing zbar shared library.
|
||||
On Linux and macOS libzbar0 must be installed.
|
||||
See in README.md for the installation of the libzbar0.
|
||||
WARN: Cannot import pyzbar module. This problem is probably due to the missing zbar shared library. (The zbar library is optional.)
|
||||
See in README.md for the installation of the zbar shared library.
|
||||
Exception: {e}\n""", file=sys.stderr)
|
||||
zbar_available = False
|
||||
if debug_mode:
|
||||
@@ -105,9 +93,8 @@ Exception: {e}\n""", file=sys.stderr)
|
||||
FONT_SCALE: Final[float] = 1.3
|
||||
FONT_THICKNESS: Final[int] = 1
|
||||
FONT_LINE_STYLE: Final[int] = cv2.LINE_AA
|
||||
FONT_COLOR: Final[ColorBGR] = (255, 0, 0)
|
||||
FONT_COLOR: Final[ColorBGR] = 255, 0, 0
|
||||
BOX_THICKNESS: Final[int] = 5
|
||||
# workaround for PYTHON <= 3.7: must use () for assignments
|
||||
WINDOW_X: Final[int] = 0
|
||||
WINDOW_Y: Final[int] = 1
|
||||
WINDOW_WIDTH: Final[int] = 2
|
||||
@@ -116,10 +103,10 @@ Exception: {e}\n""", file=sys.stderr)
|
||||
TEXT_HEIGHT: Final[int] = 1
|
||||
BORDER: Final[int] = 5
|
||||
START_Y: Final[int] = 20
|
||||
START_POS_TEXT: Final[Point] = (BORDER, START_Y)
|
||||
NORMAL_COLOR: Final[ColorBGR] = (255, 0, 255)
|
||||
SUCCESS_COLOR: Final[ColorBGR] = (0, 255, 0)
|
||||
FAILURE_COLOR: Final[ColorBGR] = (0, 0, 255)
|
||||
START_POS_TEXT: Final[Point] = BORDER, START_Y
|
||||
NORMAL_COLOR: Final[ColorBGR] = 255, 0, 255
|
||||
SUCCESS_COLOR: Final[ColorBGR] = 0, 255, 0
|
||||
FAILURE_COLOR: Final[ColorBGR] = 0, 0, 255
|
||||
CHAR_DX: Final[int] = (lambda text: cv2.getTextSize(text, FONT, FONT_SCALE, FONT_THICKNESS)[0][TEXT_WIDTH] // len(text))("28 QR codes capturedMMM")
|
||||
FONT_DY: Final[int] = cv2.getTextSize("M", FONT, FONT_SCALE, FONT_THICKNESS)[0][TEXT_HEIGHT] + 5
|
||||
WINDOW_NAME: Final[str] = "Extract OTP Secrets: Capture QR Codes from Camera"
|
||||
@@ -132,12 +119,12 @@ except ImportError as e:
|
||||
if debug_mode:
|
||||
raise e
|
||||
|
||||
# Workaround for PYTHON <= 3.9: Union[int, None] used instead of int | None
|
||||
# Workaround for PYTHON <= 3.9: Generally Union[int, None] used instead of int | None
|
||||
|
||||
# Types
|
||||
Args = argparse.Namespace
|
||||
OtpUrl = str
|
||||
# workaround for PYTHON <= 3.7: Otp = TypedDict('Otp', {'name': str, 'secret': str, 'issuer': str, 'type': str, 'counter': int | None, 'url': OtpUrl})
|
||||
# Workaround for PYTHON <= 3.9: Otp = TypedDict('Otp', {'name': str, 'secret': str, 'issuer': str, 'type': str, 'counter': int | None, 'url': OtpUrl})
|
||||
Otp = TypedDict('Otp', {'name': str, 'secret': str, 'issuer': str, 'type': str, 'counter': Union[int, None], 'url': OtpUrl})
|
||||
# workaround for PYTHON <= 3.9: Otps = list[Otp]
|
||||
Otps = List[Otp]
|
||||
@@ -201,6 +188,7 @@ def main(sys_args: list[str]) -> None:
|
||||
write_keepass_csv(args.keepass, otps)
|
||||
write_json(args.json, otps)
|
||||
write_txt(args.txt, otps, True)
|
||||
write_urls(args.urls, otps)
|
||||
|
||||
|
||||
# workaround for PYTHON <= 3.9 use: pb.MigrationPayload | None
|
||||
@@ -277,9 +265,7 @@ def extract_otp_from_otp_url(otpauth_migration_url: str, otps: Otps, urls_count:
|
||||
def parse_args(sys_args: list[str]) -> Args:
|
||||
global verbose, quiet, colored
|
||||
|
||||
# For PYTHON <= 3.7: Use :=
|
||||
name = os.path.basename(sys.argv[0])
|
||||
cmd = f"python {name}" if name.endswith('.py') else f"{name}"
|
||||
cmd = f"python {name}" if (name := os.path.basename(sys.argv[0])).endswith('.py') else f"{name}"
|
||||
description_text = "Extracts one time password (OTP) secrets from QR codes exported by two-factor authentication (2FA) apps"
|
||||
if cv2_available:
|
||||
description_text += "\nIf no infiles are provided, a GUI window starts and QR codes are captured from the camera."
|
||||
@@ -295,10 +281,11 @@ def parse_args(sys_args: list[str]) -> Args:
|
||||
epilog=example_text)
|
||||
arg_parser.add_argument('infile', help="""a) file or - for stdin with 'otpauth-migration://...' URLs separated by newlines, lines starting with # are ignored;
|
||||
b) image file containing a QR code or = for stdin for an image containing a QR code""", nargs='*' if cv2_available else '+')
|
||||
arg_parser.add_argument('--csv', '-c', help='export csv file or - for stdout', metavar=('FILE'))
|
||||
arg_parser.add_argument('--csv', '-c', help='export csv file, or - for stdout', metavar=('FILE'))
|
||||
arg_parser.add_argument('--keepass', '-k', help='export totp/hotp csv file(s) for KeePass, - for stdout', metavar=('FILE'))
|
||||
arg_parser.add_argument('--json', '-j', help='export json file or - for stdout', metavar=('FILE'))
|
||||
arg_parser.add_argument('--txt', '-t', help='export txt file or - for stdout', metavar=('FILE'))
|
||||
arg_parser.add_argument('--urls', '-u', help='export file with list of otpauth urls, or - for stdout', metavar=('FILE'))
|
||||
arg_parser.add_argument('--printqr', '-p', help='print QR code(s) as text to the terminal', action='store_true')
|
||||
arg_parser.add_argument('--saveqr', '-s', help='save QR code(s) as images to directory', metavar=('DIR'))
|
||||
if cv2_available:
|
||||
@@ -316,13 +303,14 @@ b) image file containing a QR code or = for stdin for an image containing a QR c
|
||||
output_group.add_argument('-q', '--quiet', help='no stdout output, except output set by -', action='store_true')
|
||||
args = arg_parser.parse_args(sys_args)
|
||||
colored = not args.no_color
|
||||
if args.csv == '-' or args.json == '-' or args.keepass == '-' or args.txt == '-':
|
||||
if args.csv == '-' or args.json == '-' or args.keepass == '-' or args.txt == '-' or args.urls == '-':
|
||||
args.quiet = args.q = True
|
||||
|
||||
verbose = args.verbose if args.verbose else LogLevel.NORMAL
|
||||
if args.debug:
|
||||
verbose = LogLevel.DEBUG
|
||||
log_debug('Debug mode start')
|
||||
log_debug(args)
|
||||
quiet = True if args.quiet else False
|
||||
if verbose: print(f"QReader installed: {cv2_available}")
|
||||
if cv2_available:
|
||||
@@ -379,7 +367,7 @@ def extract_otps_from_camera(args: Args) -> Otps:
|
||||
if QRMode.CV2:
|
||||
otp_url, raw_pts, _ = cv2_qr.detectAndDecode(img)
|
||||
else:
|
||||
otp_url, raw_pts = cv2_qr_wechat.detectAndDecode(img)
|
||||
otp_url, raw_pts = cv2_qr_wechat.detectAndDecode(img) # type: ignore # use proper cv2 types
|
||||
if raw_pts is not None:
|
||||
if otp_url:
|
||||
new_otps_count = extract_otps_from_otp_url(otp_url, otp_urls, otps, args)
|
||||
@@ -393,7 +381,7 @@ def extract_otps_from_camera(args: Args) -> Otps:
|
||||
|
||||
cv2_print_text(img, f"Mode: {qr_mode.name} (Hit SPACE to change)", 0, TextPosition.LEFT, FONT_COLOR, 20)
|
||||
cv2_print_text(img, "Press ESC to quit", 1, TextPosition.LEFT, FONT_COLOR, 17)
|
||||
cv2_print_text(img, "Press C/J/K/T to save as csv/json/keepass/txt file", 2, TextPosition.LEFT, FONT_COLOR, None)
|
||||
cv2_print_text(img, "Press c,j,k,t,u to save as csv/json/keepass/txt/urls file", 2, TextPosition.LEFT, FONT_COLOR, None)
|
||||
|
||||
cv2_print_text(img, f"{len(otp_urls)} QR code{'s'[:len(otp_urls) != 1]} captured", 0, TextPosition.RIGHT, FONT_COLOR)
|
||||
cv2_print_text(img, f"{len(otps)} otp{'s'[:len(otps) != 1]} extracted", 1, TextPosition.RIGHT, FONT_COLOR)
|
||||
@@ -420,16 +408,15 @@ def get_color(new_otps_count: int, otp_url: str) -> ColorBGR:
|
||||
return NORMAL_COLOR
|
||||
|
||||
|
||||
# TODO use cv2 types if available
|
||||
def cv2_draw_box(img: Any, raw_pts: Any, color: ColorBGR) -> Any:
|
||||
# TODO use proper cv2 types if available
|
||||
def cv2_draw_box(img: cv2.typing.MatLike, raw_pts: cv2.typing.MatLike | list[tuple[Any, Any]], color: ColorBGR) -> np.ndarray[Any, np.dtype[np.int32]]:
|
||||
pts = np.array([raw_pts], np.int32)
|
||||
pts = pts.reshape((-1, 1, 2))
|
||||
cv2.polylines(img, [pts], True, color, BOX_THICKNESS)
|
||||
return pts
|
||||
|
||||
|
||||
# TODO use cv2 types if available
|
||||
def cv2_print_text(img: Any, text: str, line_number: int, position: TextPosition, color: ColorBGR, opposite_len: Optional[int] = None) -> None:
|
||||
def cv2_print_text(img: cv2.typing.MatLike, text: str, line_number: int, position: TextPosition, color: ColorBGR, opposite_len: Optional[int] = None) -> None:
|
||||
window_dim = cv2.getWindowImageRect(WINDOW_NAME)
|
||||
out_text = text
|
||||
if opposite_len:
|
||||
@@ -500,6 +487,18 @@ def cv2_handle_pressed_keys(qr_mode: QRMode, otps: Otps) -> Tuple[bool, QRMode]:
|
||||
tk_root.update()
|
||||
if len(file_name) > 0:
|
||||
write_txt(file_name, otps, True)
|
||||
elif (key == ord('u') or key == ord('U')) and is_not_headless():
|
||||
if has_no_otps_show_warning(otps):
|
||||
pass
|
||||
else:
|
||||
file_name = tkinter.filedialog.asksaveasfilename(
|
||||
title="Save extracted otp secrets as list of urls",
|
||||
defaultextension='.txt',
|
||||
filetypes=[('Text', '*.txt'), ('All', '*.*')]
|
||||
)
|
||||
tk_root.update()
|
||||
if len(file_name) > 0:
|
||||
write_urls(file_name, otps)
|
||||
elif key == 32:
|
||||
qr_mode = next_valid_qr_mode(qr_mode, zbar_available)
|
||||
if verbose >= LogLevel.MORE_VERBOSE: print(f"QR reading mode: {qr_mode}")
|
||||
@@ -680,6 +679,10 @@ def print_otp(otp: Otp, out: Optional[TextIO] = None) -> None:
|
||||
print(otp['url'], file=out)
|
||||
|
||||
|
||||
def write_url(otp: Otp, out: Optional[TextIO] = None) -> None:
|
||||
print(otp['url'], file=out)
|
||||
|
||||
|
||||
def save_qr_image(otp: Otp, dir: str, j: int) -> str:
|
||||
if not (os.path.exists(dir)): os.makedirs(dir, exist_ok=True)
|
||||
pattern = re.compile(r'[\W_]+')
|
||||
@@ -713,6 +716,14 @@ def write_txt(file: str, otps: Otps, write_qr: bool = False) -> None:
|
||||
print(file=outfile)
|
||||
|
||||
|
||||
def write_urls(file: str, otps: Otps) -> None:
|
||||
if file and len(file) > 0 and len(otps) > 0:
|
||||
with open_file_or_stdout(file) as outfile:
|
||||
for otp in otps:
|
||||
write_url(otp, outfile)
|
||||
if not quiet: print(f"Exported {len(otps)} otp{'s'[:len(otps) != 1]} to otpauth url list file {file}")
|
||||
|
||||
|
||||
def write_csv(file: str, otps: Otps) -> None:
|
||||
if file and len(file) > 0 and len(otps) > 0:
|
||||
with open_file_or_stdout_for_csv(file) as outfile:
|
||||
@@ -736,8 +747,8 @@ def write_keepass_csv(file: str, otps: Otps) -> None:
|
||||
if has_hotp:
|
||||
count_hotp_entries = write_keepass_htop_csv(otp_filename_hotp, otps)
|
||||
if not quiet:
|
||||
if count_totp_entries: print(f"Exported {count_totp_entries} totp entrie{'s'[:count_totp_entries != 1]} to keepass csv file {otp_filename_totp}")
|
||||
if count_hotp_entries: print(f"Exported {count_hotp_entries} hotp entrie{'s'[:count_hotp_entries != 1]} to keepass csv file {otp_filename_hotp}")
|
||||
if has_totp and count_totp_entries: print(f"Exported {count_totp_entries} totp entrie{'s'[:count_totp_entries != 1]} to keepass csv file {otp_filename_totp}")
|
||||
if has_hotp and count_hotp_entries: print(f"Exported {count_hotp_entries} hotp entrie{'s'[:count_hotp_entries != 1]} to keepass csv file {otp_filename_hotp}")
|
||||
|
||||
|
||||
def write_keepass_totp_csv(file: str, otps: Otps) -> int:
|
||||
@@ -899,19 +910,7 @@ def get_raw_version() -> str:
|
||||
return __version__
|
||||
except PackageNotFoundError:
|
||||
# package is not installed
|
||||
pass
|
||||
|
||||
# In some cases importlib cannot properly detect package version, for example it was compiled into executable file, so it uses some custom import mechanism.
|
||||
# Instead, use pkg_resources which is included in setuptools (but has a significant runtime cost)
|
||||
|
||||
try:
|
||||
__version__ = get_distribution("package-name").version
|
||||
return __version__
|
||||
except DistributionNotFound:
|
||||
# package is not installed
|
||||
pass
|
||||
|
||||
return ''
|
||||
return ''
|
||||
|
||||
|
||||
# workaround for PYTHON <= 3.9 use: BaseException | None
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: google_auth.proto
|
||||
# Protobuf Python Version: 5.26.1
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf.internal import builder as _builder
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf.internal import builder as _builder
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
@@ -18,9 +19,8 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11google_auth.pr
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'google_auth_pb2', _globals)
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
|
||||
DESCRIPTOR._options = None
|
||||
if not _descriptor._USE_C_DESCRIPTORS:
|
||||
DESCRIPTOR._loaded_options = None
|
||||
_globals['_MIGRATIONPAYLOAD']._serialized_start=22
|
||||
_globals['_MIGRATIONPAYLOAD']._serialized_end=461
|
||||
_globals['_MIGRATIONPAYLOAD_OTPPARAMETERS']._serialized_start=176
|
||||
|
||||
@@ -28,7 +28,7 @@ class MigrationPayload(google.protobuf.message.Message):
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _AlgorithmEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[MigrationPayload._Algorithm.ValueType], builtins.type): # noqa: F821
|
||||
class _AlgorithmEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[MigrationPayload._Algorithm.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
ALGO_INVALID: MigrationPayload._Algorithm.ValueType # 0
|
||||
ALGO_SHA1: MigrationPayload._Algorithm.ValueType # 1
|
||||
@@ -41,7 +41,7 @@ class MigrationPayload(google.protobuf.message.Message):
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _OtpTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[MigrationPayload._OtpType.ValueType], builtins.type): # noqa: F821
|
||||
class _OtpTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[MigrationPayload._OtpType.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
OTP_INVALID: MigrationPayload._OtpType.ValueType # 0
|
||||
OTP_HOTP: MigrationPayload._OtpType.ValueType # 1
|
||||
|
||||
6
tests/data/url_list_output.txt
Normal file
6
tests/data/url_list_output.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
otpauth://totp/pi%40raspberrypi?secret=7KSQL2JTUDIS5EF65KLMRQIIGY&issuer=raspberrypi
|
||||
otpauth://totp/pi%40raspberrypi?secret=7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||
otpauth://totp/pi%40raspberrypi?secret=7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||
otpauth://totp/pi%40raspberrypi?secret=7KSQL2JTUDIS5EF65KLMRQIIGY&issuer=raspberrypi
|
||||
otpauth://hotp/hotp%20demo?secret=7KSQL2JTUDIS5EF65KLMRQIIGY&counter=4
|
||||
otpauth://totp/encoding%3A%20%C2%BF%C3%A4%C3%84%C3%A9%C3%89%3F%20%28demo%29?secret=7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||
@@ -39,7 +39,7 @@ from utils import (count_files_in_dir, file_exits, read_binary_file_as_stream,
|
||||
import extract_otp_secrets
|
||||
|
||||
try:
|
||||
import cv2 # type: ignore
|
||||
import cv2
|
||||
from extract_otp_secrets import SUCCESS_COLOR, FAILURE_COLOR, FONT, FONT_SCALE, FONT_COLOR, FONT_THICKNESS, FONT_LINE_STYLE
|
||||
except ImportError:
|
||||
# ignore
|
||||
@@ -418,6 +418,37 @@ def test_extract_txt_stdout_only_comments(capsys: pytest.CaptureFixture[str]) ->
|
||||
assert captured.err == ''
|
||||
|
||||
|
||||
def test_extract_urls(capsys: pytest.CaptureFixture[str], tmp_path: pathlib.Path) -> None:
|
||||
# Arrange
|
||||
output_file = str(tmp_path / 'test_example_url_list.txt')
|
||||
|
||||
# Act
|
||||
extract_otp_secrets.main(['-q', '-u', output_file, 'example_export.txt'])
|
||||
|
||||
# Assert
|
||||
expected_txt = read_file_to_str('tests/data/url_list_output.txt')
|
||||
actual_txt = read_file_to_str(output_file)
|
||||
|
||||
assert actual_txt == expected_txt
|
||||
|
||||
captured = capsys.readouterr()
|
||||
|
||||
assert captured.out == ''
|
||||
assert captured.err == ''
|
||||
|
||||
|
||||
def test_extract_urls_stdout(capsys: pytest.CaptureFixture[str]) -> None:
|
||||
# Act
|
||||
extract_otp_secrets.main(['-u', '-', 'example_export.txt'])
|
||||
|
||||
# Assert
|
||||
expected_txt = read_file_to_str('tests/data/url_list_output.txt')
|
||||
captured = capsys.readouterr()
|
||||
|
||||
assert captured.out == expected_txt
|
||||
assert captured.err == ''
|
||||
|
||||
|
||||
def test_extract_not_encoded_plus(capsys: pytest.CaptureFixture[str]) -> None:
|
||||
# Act
|
||||
extract_otp_secrets.main(['tests/data/test_plus_problem_export.txt'])
|
||||
|
||||
Reference in New Issue
Block a user