mirror of
https://github.com/scito/extract_otp_secrets.git
synced 2025-12-12 17:59:48 +01:00
remove Python 3.7 workarounds, fixes #103
This commit is contained in:
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.x", "3.11", "3.10", "3.9", "3.8", "3.7"]
|
python-version: ["3.x", "3.11", "3.10", "3.9", "3.8"]
|
||||||
platform: [ubuntu-latest, macos-latest, windows-latest]
|
platform: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
# exclude:
|
# exclude:
|
||||||
|
|
||||||
|
|||||||
1
Pipfile
1
Pipfile
@@ -7,7 +7,6 @@ name = "pypi"
|
|||||||
colorama = ">=0.4.6"
|
colorama = ">=0.4.6"
|
||||||
opencv-contrib-python = "*"
|
opencv-contrib-python = "*"
|
||||||
# for macOS: opencv-contrib-python = "<=4.7.0"
|
# for macOS: opencv-contrib-python = "<=4.7.0"
|
||||||
# for PYTHON <= 3.7: typing_extensions = "*"
|
|
||||||
pillow = "*"
|
pillow = "*"
|
||||||
pyzbar = "*"
|
pyzbar = "*"
|
||||||
protobuf = "*"
|
protobuf = "*"
|
||||||
|
|||||||
12
Pipfile.lock
generated
12
Pipfile.lock
generated
@@ -52,7 +52,7 @@
|
|||||||
"sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357",
|
"sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357",
|
||||||
"sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"
|
"sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.8'",
|
"markers": "python_version >= '3.10'",
|
||||||
"version": "==1.25.2"
|
"version": "==1.25.2"
|
||||||
},
|
},
|
||||||
"opencv-contrib-python": {
|
"opencv-contrib-python": {
|
||||||
@@ -489,7 +489,7 @@
|
|||||||
"sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0",
|
"sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0",
|
||||||
"sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"
|
"sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"
|
||||||
],
|
],
|
||||||
"markers": "python_full_version >= '3.8.0'",
|
"markers": "python_version >= '3.8'",
|
||||||
"version": "==2.11.0"
|
"version": "==2.11.0"
|
||||||
},
|
},
|
||||||
"pyflakes": {
|
"pyflakes": {
|
||||||
@@ -497,7 +497,7 @@
|
|||||||
"sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774",
|
"sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774",
|
||||||
"sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"
|
"sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"
|
||||||
],
|
],
|
||||||
"markers": "python_full_version >= '3.8.0'",
|
"markers": "python_version >= '3.8'",
|
||||||
"version": "==3.1.0"
|
"version": "==3.1.0"
|
||||||
},
|
},
|
||||||
"pylint": {
|
"pylint": {
|
||||||
@@ -582,11 +582,11 @@
|
|||||||
},
|
},
|
||||||
"wheel": {
|
"wheel": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:55a0f0a5a84869bce5ba775abfd9c462e3a6b1b7b7ec69d72c0b83d673a5114d",
|
"sha256:12b911f083e876e10c595779709f8a88a59f45aacc646492a67fe9ef796c1b47",
|
||||||
"sha256:7e9be3bbd0078f6147d82ed9ed957e323e7708f57e134743d2edef3a7b7972a9"
|
"sha256:473219bd4cbedc62cea0cb309089b593e47c15c4a2531015f94e4e3b9a0f6981"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.41.0"
|
"version": "==0.41.1"
|
||||||
},
|
},
|
||||||
"wrapt": {
|
"wrapt": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||

|

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

|

|
||||||
[](https://hub.docker.com/repository/docker/scit0/extract_otp_secrets/general)
|
[](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)
|
||||||
[](https://github.com/scito/extract_otp_secrets/releases/latest)
|
[](https://github.com/scito/extract_otp_secrets/releases/latest)
|
||||||
@@ -367,7 +367,7 @@ python extract_otp_secrets.py = < example_export.png</pre>
|
|||||||
* macOS
|
* macOS
|
||||||
* Windows
|
* Windows
|
||||||
* Uses UTF-8 on all platforms
|
* Uses UTF-8 on all platforms
|
||||||
* Supports Python >= 3.7
|
* Supports Python >= 3.8
|
||||||
* Installation of shared system libraries is optional (🆕 since v2.3)
|
* Installation of shared system libraries is optional (🆕 since v2.3)
|
||||||
* Provides a debug mode (-d) for analyzing import problems
|
* Provides a debug mode (-d) for analyzing import problems
|
||||||
* Written in modern Python using type hints and following best practices
|
* Written in modern Python using type hints and following best practices
|
||||||
|
|||||||
@@ -47,9 +47,6 @@ dependencies = [
|
|||||||
"pyzbar",
|
"pyzbar",
|
||||||
"qrcode",
|
"qrcode",
|
||||||
"qreader<2.0.0",
|
"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'"
|
description = "Extracts one time password (OTP) secrets from QR codes exported by two-factor authentication (2FA) apps such as 'Google Authenticator'"
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
|
|||||||
@@ -43,26 +43,15 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
import urllib.parse as urlparse
|
import urllib.parse as urlparse
|
||||||
from enum import Enum, IntEnum
|
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
|
import colorama
|
||||||
from qrcode import QRCode # type: ignore
|
from qrcode import QRCode # type: ignore
|
||||||
|
|
||||||
import protobuf_generated_python.google_auth_pb2 as pb
|
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:]
|
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:]
|
quiet = '-q' in sys.argv[1:] or '--quiet' in sys.argv[1:]
|
||||||
headless: bool = False
|
headless: bool = False
|
||||||
@@ -103,9 +92,8 @@ Exception: {e}\n""", file=sys.stderr)
|
|||||||
FONT_SCALE: Final[float] = 1.3
|
FONT_SCALE: Final[float] = 1.3
|
||||||
FONT_THICKNESS: Final[int] = 1
|
FONT_THICKNESS: Final[int] = 1
|
||||||
FONT_LINE_STYLE: Final[int] = cv2.LINE_AA
|
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
|
BOX_THICKNESS: Final[int] = 5
|
||||||
# workaround for PYTHON <= 3.7: must use () for assignments
|
|
||||||
WINDOW_X: Final[int] = 0
|
WINDOW_X: Final[int] = 0
|
||||||
WINDOW_Y: Final[int] = 1
|
WINDOW_Y: Final[int] = 1
|
||||||
WINDOW_WIDTH: Final[int] = 2
|
WINDOW_WIDTH: Final[int] = 2
|
||||||
@@ -114,10 +102,10 @@ Exception: {e}\n""", file=sys.stderr)
|
|||||||
TEXT_HEIGHT: Final[int] = 1
|
TEXT_HEIGHT: Final[int] = 1
|
||||||
BORDER: Final[int] = 5
|
BORDER: Final[int] = 5
|
||||||
START_Y: Final[int] = 20
|
START_Y: Final[int] = 20
|
||||||
START_POS_TEXT: Final[Point] = (BORDER, START_Y)
|
START_POS_TEXT: Final[Point] = BORDER, START_Y
|
||||||
NORMAL_COLOR: Final[ColorBGR] = (255, 0, 255)
|
NORMAL_COLOR: Final[ColorBGR] = 255, 0, 255
|
||||||
SUCCESS_COLOR: Final[ColorBGR] = (0, 255, 0)
|
SUCCESS_COLOR: Final[ColorBGR] = 0, 255, 0
|
||||||
FAILURE_COLOR: Final[ColorBGR] = (0, 0, 255)
|
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")
|
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
|
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"
|
WINDOW_NAME: Final[str] = "Extract OTP Secrets: Capture QR Codes from Camera"
|
||||||
@@ -130,12 +118,12 @@ except ImportError as e:
|
|||||||
if debug_mode:
|
if debug_mode:
|
||||||
raise e
|
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
|
# Types
|
||||||
Args = argparse.Namespace
|
Args = argparse.Namespace
|
||||||
OtpUrl = str
|
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})
|
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]
|
# workaround for PYTHON <= 3.9: Otps = list[Otp]
|
||||||
Otps = List[Otp]
|
Otps = List[Otp]
|
||||||
@@ -275,9 +263,7 @@ def extract_otp_from_otp_url(otpauth_migration_url: str, otps: Otps, urls_count:
|
|||||||
def parse_args(sys_args: list[str]) -> Args:
|
def parse_args(sys_args: list[str]) -> Args:
|
||||||
global verbose, quiet, colored
|
global verbose, quiet, colored
|
||||||
|
|
||||||
# For PYTHON <= 3.7: Use :=
|
cmd = f"python {name}" if (name := os.path.basename(sys.argv[0])).endswith('.py') else f"{name}"
|
||||||
name = os.path.basename(sys.argv[0])
|
|
||||||
cmd = f"python {name}" if name.endswith('.py') else f"{name}"
|
|
||||||
description_text = "Extracts one time password (OTP) secrets from QR codes exported by two-factor authentication (2FA) apps"
|
description_text = "Extracts one time password (OTP) secrets from QR codes exported by two-factor authentication (2FA) apps"
|
||||||
if cv2_available:
|
if cv2_available:
|
||||||
description_text += "\nIf no infiles are provided, a GUI window starts and QR codes are captured from the camera."
|
description_text += "\nIf no infiles are provided, a GUI window starts and QR codes are captured from the camera."
|
||||||
@@ -324,7 +310,7 @@ b) image file containing a QR code or = for stdin for an image containing a QR c
|
|||||||
quiet = True if args.quiet else False
|
quiet = True if args.quiet else False
|
||||||
if verbose: print(f"QReader installed: {cv2_available}")
|
if verbose: print(f"QReader installed: {cv2_available}")
|
||||||
if cv2_available:
|
if cv2_available:
|
||||||
if verbose >= LogLevel.VERBOSE: print(f"CV2 version: -") # TODO {cv2.__version__}
|
if verbose >= LogLevel.VERBOSE: print(f"CV2 version: {cv2.__version__}") # type: ignore # cv2.__version__ is not available
|
||||||
if verbose: print(f"QR reading mode: {args.qr}\n")
|
if verbose: print(f"QR reading mode: {args.qr}\n")
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|||||||
Reference in New Issue
Block a user