Skip to content

Commit c8cc274

Browse files
flake8 and pylint
1 parent f1706c9 commit c8cc274

File tree

6 files changed

+228
-91
lines changed

6 files changed

+228
-91
lines changed

.flake8

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ per-file-ignores =
110110
# additionally test docstrings don't need param lists (DAR, DCO020):
111111
tests/**.py: DAR, DCO020, S101, S105, S108, S404, S603, WPS202, WPS210, WPS430, WPS436, WPS441, WPS442, WPS450
112112

113+
tests/_temporary_private_inject_api_test.py: DAR, DCO020, S101, S105, S108, S404, S603, WPS202, WPS210, WPS226, WPS430, WPS436, WPS441, WPS442, WPS450, WWPS202
114+
113115
src/awx_plugins/interfaces/_temporary_private_inject_api.py: ANN001,ANN201,B950,C901,CCR001,D103,E800,LN001,LN002,Q003,WPS110,WPS111,WPS118,WPS125,WPS204,WPS210,WPS211,WPS213,WPS221,WPS226,WPS231,WPS232,WPS319,WPS323,WPS336,WPS337,WPS361,WPS421,WPS429,WPS430,WPS431,WPS436,WPS442,WPS503,WPS507,WPS516,WPS226
114116

115117

.pylintrc.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ disable = [
422422
"useless-import-alias", # MyPy requires the opposite
423423
"wrong-import-order", # isort-handled: https://github.com/pylint-dev/pylint/issues/9977
424424
"wrong-import-position", # isort-handled: https://github.com/pylint-dev/pylint/issues/9977
425+
"relative-beyond-top-level", # Developer preference
425426
]
426427

427428
# Enable the message, report, category or checker with the given id(s). You can

src/awx_plugins/interfaces/_temporary_private_api.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
)
1313

1414

15-
InputSchemaValueType = list[dict[str, str | bool]]
16-
InputSchemaType = dict[str, InputSchemaValueType]
17-
15+
InputDefinitionValueType = list[dict[str, str | bool]]
16+
InputDefinitionType = dict[str, InputDefinitionValueType]
17+
InjectorDefinitionType = dict[str, dict[str, str]]
1818

1919
try:
2020
# pylint: disable-next=unused-import
@@ -37,10 +37,10 @@ class ManagedCredentialType: # type: ignore[no-redef] # noqa: WPS440
3737
kind: str
3838
"""Plugin category."""
3939

40-
inputs: InputSchemaType
40+
inputs: InputDefinitionType
4141
"""UI input fields schema."""
4242

43-
injectors: dict[str, dict[str, str]] | None = None
43+
injectors: InjectorDefinitionType | None = None
4444
"""Injector hook parameters."""
4545

4646
managed: bool = False
@@ -54,6 +54,7 @@ class ManagedCredentialType: # type: ignore[no-redef] # noqa: WPS440
5454
] | None = None
5555
"""Function to call as an alternative to the templated injection."""
5656

57+
# pylint: disable-next=R0913,R0917
5758
def inject_credential( # noqa: WPS211
5859
self: 'ManagedCredentialType',
5960
credential: Credential,
@@ -69,7 +70,8 @@ def inject_credential( # noqa: WPS211
6970
inject_credential is called directly. Once the above awx
7071
import hack is removed the duplication can be removed.
7172
"""
72-
from ._temporary_private_inject_api import ( # noqa: WPS433, WPS436
73+
# pylint: disable-next=C0415,E0402
74+
from ._temporary_private_inject_api import ( # noqa: WPS433,WPS436
7375
inject_credential,
7476
)
7577
inject_credential(

src/awx_plugins/interfaces/_temporary_private_inject_api.py

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Injection makes use of plugins."""
1+
"""Injectors exercise plugins."""
22

33
import os
44
import re
@@ -18,6 +18,15 @@
1818
)
1919

2020

21+
# pylint: disable-next=too-few-public-methods
22+
class TowerNamespace:
23+
"""Dummy class."""
24+
25+
26+
TowerNamespaceValueType = TowerNamespace | GenericOptionalPrimitiveType
27+
ExtraVarsType = dict[str, str] | list[str] | str
28+
29+
2130
HIDDEN_PASSWORD = '*' * 10
2231
SENSITIVE_ENV_VAR_NAMES = 'API|TOKEN|KEY|SECRET|PASS'
2332

@@ -61,7 +70,7 @@ def build_safe_env(
6170
:returns: Sanitized environment variables.
6271
"""
6372
safe_env = dict(env)
64-
for env_k, env_val in safe_env.items():
73+
for env_k, env_v in safe_env.items():
6574
is_special = (
6675
env_k == 'AWS_ACCESS_KEY_ID'
6776
or (
@@ -72,23 +81,29 @@ def build_safe_env(
7281
)
7382
if is_special:
7483
continue
75-
elif HIDDEN_PASSWORD_RE.search(env_k):
84+
if HIDDEN_PASSWORD_RE.search(env_k):
7685
safe_env[env_k] = HIDDEN_PASSWORD
77-
elif isinstance(env_val, str) and HIDDEN_URL_PASSWORD_RE.match(env_val):
86+
elif isinstance(env_v, str) and HIDDEN_URL_PASSWORD_RE.match(env_v):
7887
safe_env[env_k] = HIDDEN_URL_PASSWORD_RE.sub(
79-
HIDDEN_PASSWORD, env_val,
88+
HIDDEN_PASSWORD, env_v,
8089
)
8190
return safe_env
8291

8392

8493
def secret_fields(cred_type: ManagedCredentialType) -> list[str]:
94+
"""List of fields that are sensitive from the credential type.
95+
96+
:param cred_type: Where the secret field descriptions live
97+
:return: list of secret field names
98+
"""
8599
return [
86100
str(field['id'])
87101
for field in cred_type.inputs.get('fields', [])
88102
if field.get('secret', False) is True
89103
]
90104

91105

106+
# pylint: disable-next=too-many-arguments,too-many-positional-arguments,too-many-locals,too-many-branches,too-many-statements
92107
def inject_credential(
93108
cred_type: ManagedCredentialType,
94109
credential: Credential,
@@ -97,6 +112,7 @@ def inject_credential(
97112
args: list[GenericOptionalPrimitiveType],
98113
private_data_dir: str,
99114
) -> None:
115+
# pylint: disable=unidiomatic-typecheck
100116
"""Inject credential data.
101117
102118
Inject credential data into the environment variables and
@@ -133,21 +149,19 @@ def inject_credential(
133149
safe_env.update(build_safe_env(injected_env))
134150
return
135151

136-
class TowerNamespace:
137-
"""Dummy class."""
138-
139152
tower_namespace = TowerNamespace()
140153

141154
# maintain a normal namespace for building the ansible-playbook
142155
# arguments (env and args)
143-
namespace: dict[str, TowerNamespace | GenericOptionalPrimitiveType] = {
156+
namespace: dict[str, TowerNamespaceValueType] = {
144157
'tower': tower_namespace,
145158
}
146159

147160
# maintain a sanitized namespace for building the DB-stored arguments
148161
# (safe_env)
149-
safe_namespace: dict[str, TowerNamespace | GenericOptionalPrimitiveType] = {
150-
'tower': tower_namespace, }
162+
safe_namespace: dict[str, TowerNamespaceValueType] = {
163+
'tower': tower_namespace,
164+
}
151165

152166
# build a normal namespace with secret values decrypted (for
153167
# ansible-playbook) and a safe namespace with secret values hidden (for
@@ -170,8 +184,9 @@ class TowerNamespace:
170184

171185
for field in cred_type.inputs.get('fields', []):
172186
field_id = str(field['id'])
187+
field_type_is_bool = field['type'] == 'boolean'
173188
# default missing boolean fields to False
174-
if field['type'] == 'boolean' and field_id not in credential.get_input_keys():
189+
if field_type_is_bool and field_id not in credential.get_input_keys():
175190
namespace[field_id] = False
176191
safe_namespace[field_id] = False
177192
# make sure private keys end with a \n
@@ -193,20 +208,24 @@ class TowerNamespace:
193208
**namespace,
194209
) # type: ignore[misc]
195210
env_dir = os.path.join(private_data_dir, 'env')
196-
_, path = tempfile.mkstemp(dir=env_dir)
197-
with open(path, 'w') as f:
211+
path = tempfile.mkstemp(dir=env_dir)[1]
212+
with open(path, 'w') as f: # pylint: disable=unspecified-encoding
198213
f.write(data)
199214
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
200215
container_path = get_incontainer_path(path, private_data_dir)
201216

202217
# determine if filename indicates single file or many
203218
if file_label.find('.') == -1:
204-
tower_namespace.filename = container_path
219+
tower_namespace.filename = container_path # pylint: disable=attribute-defined-outside-init
205220
else:
206221
if not hasattr(tower_namespace, 'filename'):
207-
tower_namespace.filename = TowerNamespace()
222+
tower_namespace.filename = TowerNamespace(
223+
) # pylint: disable=attribute-defined-outside-init
208224
file_label = file_label.split('.')[1]
209-
setattr(tower_namespace.filename, file_label, container_path)
225+
setattr(
226+
tower_namespace.filename,
227+
file_label,
228+
container_path) # pylint: disable=attribute-defined-outside-init
210229

211230
for env_var, tmpl in cred_type.injectors.get('env', {}).items():
212231
if env_var in ENV_BLOCKLIST:
@@ -220,23 +239,25 @@ class TowerNamespace:
220239
# awx-manage inventory_update does not support extra_vars via -e
221240
def build_extra_vars(
222241
node: dict[str, str | list[str]] | list[str] | str,
223-
) -> dict[str, str] | list[str] | str:
242+
) -> ExtraVarsType:
224243
if isinstance(node, dict):
225244
return {
226-
build_extra_vars(k): build_extra_vars(v) for k,
245+
build_extra_vars(entry): build_extra_vars(v) for entry,
227246
v in node.items()
228247
}
229-
elif isinstance(node, list):
230-
return [build_extra_vars(x) for x in node]
231-
else:
232-
return sandbox_env.from_string(node).render(**namespace)
233-
234-
def build_extra_vars_file(vars, private_dir: str) -> str:
248+
if isinstance(node, list):
249+
return [build_extra_vars(entry) for entry in node]
250+
return sandbox_env.from_string(node).render(**namespace)
251+
252+
def build_extra_vars_file(
253+
extra_vars: ExtraVarsType,
254+
private_dir: str,
255+
) -> str:
235256
handle, path = tempfile.mkstemp(
236257
dir=os.path.join(private_dir, 'env'),
237258
)
238259
f = os.fdopen(handle, 'w')
239-
f.write(yaml_safe_dump(vars))
260+
f.write(yaml_safe_dump(extra_vars))
240261
f.close()
241262
os.chmod(path, stat.S_IRUSR)
242263
return path
@@ -249,4 +270,5 @@ def build_extra_vars_file(vars, private_dir: str) -> str:
249270
if extra_vars:
250271
path = build_extra_vars_file(extra_vars, private_data_dir)
251272
container_path = get_incontainer_path(path, private_data_dir)
252-
args.extend(['-e', '@%s' % container_path])
273+
args.extend(['-e', '@%s' % container_path]
274+
) # pylint: disable=consider-using-f-string

tests/_temporary_private_api_test.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
"""Tests for the temporarily hosted private helpers."""
22

3-
from awx_plugins.interfaces._temporary_private_api import (
4-
ManagedCredentialType,
5-
)
3+
from awx_plugins.interfaces._temporary_private_api import ManagedCredentialType
64

75

86
def test_managed_credential_type_instantiation() -> None:
97
"""Check that managed credential type can be instantiated."""
10-
118
assert ManagedCredentialType('', '', '', {})

0 commit comments

Comments
 (0)