Skip to content

Commit 5169aaf

Browse files
PYCO-93: Fix lint findings
Changes ------- * Replaces two `assert self._cert_path is not None` lines in Credential with explicit if-raise guards, since `python -O` strips asserts and bandit B101 flags them. * Wraps the dispatched-header lookup in the test helper with str() so mypy stops returning Any from the str-typed function. * Adds `[mypy-cryptography.*] ignore_missing_imports = True` to mypy.ini. The cryptography package doesn't ship stubs for the pkcs12 / serialization namespace. * Adds `# type: ignore[import-not-found]` to `import tomli` in couchbase_analytics_version.py, matching the existing ignore on `import tomli_w` two lines below. The pre-commit mypy hook runs in an isolated env that doesn't include tomli.
1 parent 58d290f commit 5169aaf

7 files changed

Lines changed: 1190 additions & 1084 deletions

File tree

acouchbase_analytics/tests/credential_t.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def _authorization_header(client: Any) -> str:
103103
req = Request('POST', request_url)
104104
flow = auth.auth_flow(req)
105105
dispatched = next(flow)
106-
return dispatched.headers.get('Authorization', '')
106+
return str(dispatched.headers.get('Authorization', ''))
107107

108108

109109
class CredentialTestSuite:

couchbase_analytics/common/credential.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,15 +275,18 @@ def _apply_to_ssl_context(self, ctx: ssl.SSLContext) -> None:
275275
# No-op for password/JWT credentials.
276276
if self._kind != 'cert':
277277
return
278-
assert self._cert_path is not None # for mypy; set in _init_certificate
278+
cert_path = self._cert_path
279+
if cert_path is None:
280+
# Unreachable: _init_certificate always sets _cert_path when _kind=='cert'.
281+
raise RuntimeError('_cert_path is unset for a cert credential.')
279282
if self._key_path is None:
280283
# PKCS#12 bundle: cert_path holds the .p12 file.
281284
self._load_pkcs12_into_context(ctx)
282285
return
283286
# PEM cert + PEM key. password is forwarded to OpenSSL so it can
284287
# decrypt the key file if it's encrypted; ignored for plain keys.
285288
ctx.load_cert_chain(
286-
certfile=self._cert_path,
289+
certfile=cert_path,
287290
keyfile=self._key_path,
288291
password=self._cert_password,
289292
)
@@ -296,18 +299,21 @@ def _load_pkcs12_into_context(self, ctx: ssl.SSLContext) -> None:
296299
pkcs12,
297300
)
298301

299-
assert self._cert_path is not None # for mypy; set in _init_certificate
300-
with open(self._cert_path, 'rb') as f:
302+
cert_path = self._cert_path
303+
if cert_path is None:
304+
# Unreachable: _init_certificate always sets _cert_path when _kind=='cert'.
305+
raise RuntimeError('_cert_path is unset for a PKCS#12 credential.')
306+
with open(cert_path, 'rb') as f:
301307
data = f.read()
302308
password_bytes = self._cert_password.encode('utf-8') if self._cert_password is not None else None
303309
try:
304310
key, cert, additional_certs = pkcs12.load_key_and_certificates(data, password_bytes)
305311
except ValueError as e:
306312
# cryptography raises ValueError for both wrong password and malformed
307313
# input. Wrap with the path so the cluster log identifies which file.
308-
raise ValueError(f'Failed to load PKCS#12 file at {self._cert_path}: {e}') from e
314+
raise ValueError(f'Failed to load PKCS#12 file at {cert_path}: {e}') from e
309315
if key is None or cert is None:
310-
raise ValueError(f'PKCS#12 file at {self._cert_path} does not contain a private key + certificate pair.')
316+
raise ValueError(f'PKCS#12 file at {cert_path} does not contain a private key + certificate pair.')
311317

312318
# ssl.SSLContext.load_cert_chain only accepts file paths, so we write
313319
# the chain plus the decrypted key into a single PEM tempfile, hand

couchbase_analytics/tests/credential_t.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def _authorization_header(client: Any) -> str:
103103
req = Request('POST', request_url)
104104
flow = auth.auth_flow(req)
105105
dispatched = next(flow)
106-
return dispatched.headers.get('Authorization', '')
106+
return str(dispatched.headers.get('Authorization', ''))
107107

108108

109109
class CredentialTestSuite:

couchbase_analytics_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def gen_version(
193193

194194
# uv does not support a dynamic project version (yet), this is a workaround in the interim
195195
def update_pyproject_version(pyproject_path: str, new_version: str) -> bool:
196-
import tomli
196+
import tomli # type: ignore[import-not-found,unused-ignore]
197197
import tomli_w # type: ignore[import-not-found]
198198

199199
if not os.path.exists(pyproject_path):

mypy.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ exclude = (?x)(
66
| tests/utils/
77
)
88

9+
[mypy-cryptography.*]
10+
ignore_missing_imports = True
11+
912
[mypy-ijson.*]
1013
ignore_missing_imports = True
1114

requirements.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ idna==3.10
2626
# httpx
2727
ijson==3.4.0
2828
# via -r requirements.in
29-
pycparser==2.23 ; python_full_version < '3.10' and implementation_name != 'PyPy' and platform_python_implementation != 'PyPy'
30-
# via cffi
31-
pycparser==3.0 ; python_full_version >= '3.10' and implementation_name != 'PyPy' and platform_python_implementation != 'PyPy'
29+
pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy'
3230
# via cffi
3331
sniffio==1.3.1
3432
# via

0 commit comments

Comments
 (0)