feat(packages/py): set up Ruff linting for Python bindings - #342
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📜 Recent review details⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
🔇 Additional comments (1)
Release Notes
Changes by Author
WalkthroughAdds Ruff linting configuration to ChangesRuff Linting Setup
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related issues
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 7 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (7 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@img2num`:
- Around line 192-193: Update the help text for the "lint-py" command to mention
that it also starts a container and therefore supports the image flags --img,
--dh-img, and --ghcr-img; modify the help string associated with the lint-py
command (lookup the declaration or usage of "lint-py" in the CLI help generation
code) to append or replace the current description "Lint Python bindings and
examples with Ruff." with a version that clarifies container startup and lists
the supported flags (e.g., "Lint Python bindings and examples with Ruff; starts
a container — supports --img, --dh-img, --ghcr-img").
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0ff3d752-042c-4537-bde5-08b8178e411b
📒 Files selected for processing (2)
img2numpyproject.toml
📜 Review details
🔇 Additional comments (2)
pyproject.toml (1)
25-46: Ruff setup looks consistent.The target version, rule set, per-file ignore, and
devextra all line up with the new Python linting flow.img2num (1)
120-135:lint-pywiring looks correct.The new mode is routed through the container helper and invokes Ruff in the dev environment as intended.
Ryan-Millard
left a comment
There was a problem hiding this comment.
Hi, thanks for the great PR - this is a really nice implementation, and the improvements to the img2num dev script are a thoughtful touch.
I just have two requests:
-
Add a reusable linting script
Please define a reusable lint command in
pyproject.toml(similar touv run devinconsole-py) so it can be run like:uv run lint
This makes it easy to run inside the container, e.g.:
./img2num sh uv run lint
Please avoid using Bash-specific scripts so it remains cross-shell compatible.
Why?
Because I, and other devs, like to do this:
ryan@Ryans-PC:~/projects/Img2Num$ ./img2num sh [+] up 2/2 ✔ Image ryanmillard/img2num-dev:latest Pulled 2.5s ✔ Container img2num-dev-1 Running 0.0s root@e6f62aadf4dd:/usr/src/app# uv run --extra dev ruff check packages/py example-apps F401 [*] `numpy` imported but unused --> example-apps/console-py/main.py:8:17 ...
Note that we enter the interactive shell and then run whatever follow-up command we needed.
-
Remove changes to
img2numThese changes are useful, but they’re out of scope for this PR.
Since this PR is focused on linting setup, it would be better to move theimg2numchanges into a separate PR to keep things focused.If you're interested, I’d definitely like to revisit this in a follow-up PR - especially extending the proxy pattern (like
pnpm <args>so we'd haveuv <args>) to support more commands.
|
Hi @Ryan-Millard, I've hit a constraint I'd like your input on. After investigating two approaches:
ruff itself is available in Would you prefer I bump the uv version in the Dockerfile to one that supports |
Hi @Geff115. Thank you for asking me about this - I had no idea that uv didn't support workspace scripts. It looks like we have a few options:
I think I need @Krasner's opinion on this, though. We need a unified monorepo management system, but it's a big decision and isn't overly necessary right now. In the meantime, please will you share the uv version you intend to use. I think we'll update uv in any case, so please will you try updating it and implementing the script. To save you from losing time by building the Docker container, just update uv directly from its interactive shell like this: Open ./img2num shUpdate uv: uv self updateJust remember to revert back to the |
|
Hi @Ryan-Millard, I tested with uv 0.11.9 (the latest, updated via Given the options you outlined, it sounds like option 3 (pnpm proxy) might be the most practical path forward while uv catches up. That said, since you mentioned wanting @Krasner 's input on the monorepo management decision, I'm happy to wait for that discussion before proceeding. I don't want to implement something that gets refactored shortly after. In the meantime, should I update this PR to simply document the |
Yes, please. That would be great. It's very strange that uv doesn't support that - it's such an important thing for monorepos. |
|
will review as soon as possible... |
|
@Ryan-Millard @Geff115
"scripts": {
"help": "node scripts/help.js",
"format": "node scripts/format.js",
"format:check": "node scripts/format.js --check",
"format:cpp": "node scripts/format-cpp.js",
"format:cpp:check": "node scripts/format-cpp.js",
"format:js": "pnpm prettier --write . --ignore-path .prettierignore --config .prettierrc",
"format:js:check": "pnpm prettier --check . --ignore-path .prettierignore --config .prettierrc",
"validate-scripts": "node scripts/validate-scripts.js",
"eslint": "eslint packages/js example-apps/react-js scripts/img2num-dev-scripts docs",
"eslint:fix": "eslint packages/js example-apps/react-js scripts/img2num-dev-scripts docs --fix",
"editorconfig:check": "editorconfig-checker",
"lint-py": "uv run --extra dev ruff check packages/py example-apps"
},
|
|
@Krasner, after having some time to think about it, I think another monorepo management tool would be better because we already have a lot of workspace-level pnpm scripts for the entire project that are dedicated to JavaScript. By adding more scripts, we'd make the I'll open a discussion about this so we can avoid the off-topic conversation on this PR. @Geff115 we don't actually need the long The ruff command can be simplified
root@648a77abe1dc:/usr/src/app# uv sync --extra dev
warning: Missing version constraint (e.g., a lower bound) for `numpy`
warning: Missing version constraint (e.g., a lower bound) for `opencv-python`
Resolved 7 packages in 487ms
Prepared 2 packages in 4m 10s
Uninstalled 3 packages in 66ms
░░░░░░░░░░░░░░░░░░░░ [0/2] Installing wheels... warning: Failed to hardlink files; falling back to full copy. This may lead to degraded performance.
If the cache and target directories are on different filesystems, hardlinking may not be supported.
If this is intentional, set `export UV_LINK_MODE=copy` or use `--link-mode=copy` to suppress this warning.
Installed 2 packages in 196ms
- console-py==0.0.0 (from file:///usr/src/app/example-apps/console-py)
- numpy==2.2.6
+ numpy==2.4.4
- opencv-python==4.13.0.92
+ ruff==0.15.12
root@648a77abe1dc:/usr/src/app# uv run ruff check .
E401 [*] Multiple imports on one line
--> core/tools/embed_shaders.py:1:1
|
1 | import sys, pathlib
| ^^^^^^^^^^^^^^^^^^^
2 |
3 | SHADER_DIR = pathlib.Path(sys.argv[1])
|
help: Split imports
E501 Line too long (90 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/fourier_coefficient_triangle.py:18:89
|
17 | # Draw vector X_k
18 | ax.arrow(0, 0, a, b, head_width=0.08, head_length=0.12, fc='blue', ec='blue', linewidth=2)
| ^^
19 |
20 | # Draw dashed triangle sides
|
E501 Line too long (95 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/fourier_coefficient_triangle.py:25:89
|
24 | # Annotations - outside the triangle
25 | ax.text(a/2, -0.05, r'$a$', fontsize=12, ha='center', va='top') # Real side
| ^^^^^^^
26 | ax.text(a + 0.2, b/2, r'$b$', fontsize=12, ha='left', va='center') # Imag side
|
E501 Line too long (96 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/fourier_coefficient_triangle.py:26:89
|
24 | # Annotations - outside the triangle
25 | ax.text(a/2, -0.05, r'$a$', fontsize=12, ha='center', va='top') # Real side
26 | ax.text(a + 0.2, b/2, r'$b$', fontsize=12, ha='left', va='center') # Imag side
| ^^^^^^^^
27 |
28 | # Phase angle arc
|
E501 Line too long (112 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/fourier_coefficient_triangle.py:37:89
|
35 | ax.plot(a, b, 'o', color='blue')
36 | ax.text(a + 0.15, b + 0.15, r'$X_k$', fontsize=12)
37 | ax.text(a + 0.15, b + -0.15, r'$(\text{Pythag: } |X_k| = \sqrt{a^2 + b^2})$', fontsize=10, color='blue') # Note
| ^^^^^^^^^^^^^^^^^^^^^^^^
38 |
39 | # Axes labels - moved to avoid overlap
|
E501 Line too long (93 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:35:89
|
33 | axs[0].plot(t_cont, sum_cont, 'k--', label="Sum (continuous)")
34 | axs[0].plot(t_disc_jittered, sum_disc_jittered, 'ko', label="Sum (samples, jittered)")
35 | axs[0].set_title("Time Domain – Harmonics (continuous) and Sampled Sum (discrete, jittered)")
| ^^^^^
36 | axs[0].set_xlabel("Time [seconds]")
37 | axs[0].set_ylabel("Amplitude")
|
B905 `zip()` without an explicit `strict=` parameter
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:44:33
|
42 | lines = []
43 | labels = []
44 | for i, (freq, amp) in enumerate(zip(freqs, amplitudes)):
| ^^^^^^^^^^^^^^^^^^^^^^
45 | markerline, stemlines, baseline = axs[1].stem([freq], [amp], linefmt=colors[i], markerfmt=f'{colors[i]}o', basefmt=" ")
46 | lines.append(markerline)
|
help: Add explicit value for parameter `strict=`
E501 Line too long (123 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:45:89
|
43 | labels = []
44 | for i, (freq, amp) in enumerate(zip(freqs, amplitudes)):
45 | markerline, stemlines, baseline = axs[1].stem([freq], [amp], linefmt=colors[i], markerfmt=f'{colors[i]}o', basefmt=" ")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 | lines.append(markerline)
47 | labels.append(f"Harmonic {i+1}")
|
E501 Line too long (97 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:49:89
|
47 | labels.append(f"Harmonic {i+1}")
48 |
49 | axs[1].set_title("Frequency Domain – Peaks at Harmonic Frequencies (colored to match harmonics)")
| ^^^^^^^^^
50 | axs[1].set_xlabel("Frequency [Hz]")
51 | axs[1].set_ylabel("Magnitude")
|
E501 Line too long (99 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:53:89
|
51 | axs[1].set_ylabel("Magnitude")
52 | axs[1].grid(True)
53 | axs[1].legend(lines, labels, loc='center left', bbox_to_anchor=(1, 0.5)) # legend outside the plot
| ^^^^^^^^^^^
54 |
55 | plt.tight_layout()
|
E501 Line too long (93 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/introduction/python_scripts/continuous-sinusoid.py:10:89
|
9 | # === Time vector and signal ===
10 | # Create an array 't' of evenly spaced time points from 0 up to (but not including) 1 second.
| ^^^^^
11 | # The total number of points = fs * duration = 100 samples.
12 | t = np.linspace(0, duration, int(fs * duration), endpoint=False)
|
E501 Line too long (89 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/introduction/python_scripts/continuous-sinusoid.py:22:89
|
21 | # === Fourier Transform ===
22 | # Compute the Fast Fourier Transform (FFT) of the signal to get its frequency components.
| ^
23 | X = np.fft.fft(x)
|
E501 Line too long (92 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/introduction/python_scripts/discrete-sinusoid.py:29:89
|
27 | num_points = min(max(1, num_points), N)
28 |
29 | # Randomly pick indices WITHOUT replacement, then sort them so points progress left-to-right
| ^^^^
30 | chosen_indices = np.sort(np.random.choice(n, size=num_points, replace=False))
31 | n_down = chosen_indices
|
E501 Line too long (103 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/introduction/python_scripts/discrete-sinusoid.py:35:89
|
34 | # Add small random jitter:
35 | # x_jitter_frac: fraction of the sample interval (1/fs). 0.15 => ┬▒15% of sample interval horizontally.
| ^^^^^^^^^^^^^^^
36 | # y_jitter: absolute amplitude jitter (in signal units). Keep small so the waveform is still visible.
37 | x_jitter_frac = 0.15
|
E501 Line too long (101 > 88)
--> docs/docs/internal/core/internal-code/fft_iterative/prerequisite-theory/introduction/python_scripts/discrete-sinusoid.py:36:89
|
34 | # Add small random jitter:
35 | # x_jitter_frac: fraction of the sample interval (1/fs). 0.15 => ┬▒15% of sample interval horizontally.
36 | # y_jitter: absolute amplitude jitter (in signal units). Keep small so the waveform is still visible.
| ^^^^^^^^^^^^^
37 | x_jitter_frac = 0.15
38 | y_jitter = 0.03
|
E501 Line too long (90 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/fourier_coefficient_triangle.py:18:89
|
17 | # Draw vector X_k
18 | ax.arrow(0, 0, a, b, head_width=0.08, head_length=0.12, fc='blue', ec='blue', linewidth=2)
| ^^
19 |
20 | # Draw dashed triangle sides
|
E501 Line too long (95 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/fourier_coefficient_triangle.py:25:89
|
24 | # Annotations - outside the triangle
25 | ax.text(a/2, -0.05, r'$a$', fontsize=12, ha='center', va='top') # Real side
| ^^^^^^^
26 | ax.text(a + 0.2, b/2, r'$b$', fontsize=12, ha='left', va='center') # Imag side
|
E501 Line too long (96 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/fourier_coefficient_triangle.py:26:89
|
24 | # Annotations - outside the triangle
25 | ax.text(a/2, -0.05, r'$a$', fontsize=12, ha='center', va='top') # Real side
26 | ax.text(a + 0.2, b/2, r'$b$', fontsize=12, ha='left', va='center') # Imag side
| ^^^^^^^^
27 |
28 | # Phase angle arc
|
E501 Line too long (112 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/fourier_coefficient_triangle.py:37:89
|
35 | ax.plot(a, b, 'o', color='blue')
36 | ax.text(a + 0.15, b + 0.15, r'$X_k$', fontsize=12)
37 | ax.text(a + 0.15, b + -0.15, r'$(\text{Pythag: } |X_k| = \sqrt{a^2 + b^2})$', fontsize=10, color='blue') # Note
| ^^^^^^^^^^^^^^^^^^^^^^^^
38 |
39 | # Axes labels - moved to avoid overlap
|
E501 Line too long (93 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:35:89
|
33 | axs[0].plot(t_cont, sum_cont, 'k--', label="Sum (continuous)")
34 | axs[0].plot(t_disc_jittered, sum_disc_jittered, 'ko', label="Sum (samples, jittered)")
35 | axs[0].set_title("Time Domain – Harmonics (continuous) and Sampled Sum (discrete, jittered)")
| ^^^^^
36 | axs[0].set_xlabel("Time [seconds]")
37 | axs[0].set_ylabel("Amplitude")
|
B905 `zip()` without an explicit `strict=` parameter
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:44:33
|
42 | lines = []
43 | labels = []
44 | for i, (freq, amp) in enumerate(zip(freqs, amplitudes)):
| ^^^^^^^^^^^^^^^^^^^^^^
45 | markerline, stemlines, baseline = axs[1].stem([freq], [amp], linefmt=colors[i], markerfmt=f'{colors[i]}o', basefmt=" ")
46 | lines.append(markerline)
|
help: Add explicit value for parameter `strict=`
E501 Line too long (123 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:45:89
|
43 | labels = []
44 | for i, (freq, amp) in enumerate(zip(freqs, amplitudes)):
45 | markerline, stemlines, baseline = axs[1].stem([freq], [amp], linefmt=colors[i], markerfmt=f'{colors[i]}o', basefmt=" ")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 | lines.append(markerline)
47 | labels.append(f"Harmonic {i+1}")
|
E501 Line too long (97 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:49:89
|
47 | labels.append(f"Harmonic {i+1}")
48 |
49 | axs[1].set_title("Frequency Domain – Peaks at Harmonic Frequencies (colored to match harmonics)")
| ^^^^^^^^^
50 | axs[1].set_xlabel("Frequency [Hz]")
51 | axs[1].set_ylabel("Magnitude")
|
E501 Line too long (99 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/fourier-series--the-bridge/python_scripts/time_freq_domain.py:53:89
|
51 | axs[1].set_ylabel("Magnitude")
52 | axs[1].grid(True)
53 | axs[1].legend(lines, labels, loc='center left', bbox_to_anchor=(1, 0.5)) # legend outside the plot
| ^^^^^^^^^^^
54 |
55 | plt.tight_layout()
|
E501 Line too long (93 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/introduction/python_scripts/continuous-sinusoid.py:10:89
|
9 | # === Time vector and signal ===
10 | # Create an array 't' of evenly spaced time points from 0 up to (but not including) 1 second.
| ^^^^^
11 | # The total number of points = fs * duration = 100 samples.
12 | t = np.linspace(0, duration, int(fs * duration), endpoint=False)
|
E501 Line too long (89 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/introduction/python_scripts/continuous-sinusoid.py:22:89
|
21 | # === Fourier Transform ===
22 | # Compute the Fast Fourier Transform (FFT) of the signal to get its frequency components.
| ^
23 | X = np.fft.fft(x)
|
E501 Line too long (92 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/introduction/python_scripts/discrete-sinusoid.py:29:89
|
27 | num_points = min(max(1, num_points), N)
28 |
29 | # Randomly pick indices WITHOUT replacement, then sort them so points progress left-to-right
| ^^^^
30 | chosen_indices = np.sort(np.random.choice(n, size=num_points, replace=False))
31 | n_down = chosen_indices
|
E501 Line too long (103 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/introduction/python_scripts/discrete-sinusoid.py:35:89
|
34 | # Add small random jitter:
35 | # x_jitter_frac: fraction of the sample interval (1/fs). 0.15 => ┬▒15% of sample interval horizontally.
| ^^^^^^^^^^^^^^^
36 | # y_jitter: absolute amplitude jitter (in signal units). Keep small so the waveform is still visible.
37 | x_jitter_frac = 0.15
|
E501 Line too long (101 > 88)
--> docs/versioned_docs/version-old/reference/wasm/modules/image/fft_iterative/prerequisite-theory/introduction/python_scripts/discrete-sinusoid.py:36:89
|
34 | # Add small random jitter:
35 | # x_jitter_frac: fraction of the sample interval (1/fs). 0.15 => ┬▒15% of sample interval horizontally.
36 | # y_jitter: absolute amplitude jitter (in signal units). Keep small so the waveform is still visible.
| ^^^^^^^^^^^^^
37 | x_jitter_frac = 0.15
38 | y_jitter = 0.03
|
F401 [*] `numpy` imported but unused
--> example-apps/console-py/main.py:8:17
|
6 | # if not preset install these with
7 | # python3 -m pip install -r requirements.txt --break-system-packages
8 | import numpy as np
| ^^
9 | import cv2
|
help: Remove unused import: `numpy`
E501 Line too long (100 > 88)
--> example-apps/console-py/main.py:23:89
|
21 | # bilateral filter in-place
22 | img_bf = img2num.bilateral_filter(img, 3, 50, 0)
23 | cv2.imwrite(os.path.join(OUTDIR, "bilateral_image.png"), cv2.cvtColor(img_bf, cv2.COLOR_RGBA2BGR))
| ^^^^^^^^^^^^
24 |
25 | # kmeans
|
E501 Line too long (101 > 88)
--> example-apps/console-py/main.py:27:89
|
25 | # kmeans
26 | img_kmeans, labels = img2num.kmeans(img_bf, 16, 100, 0)
27 | cv2.imwrite(os.path.join(OUTDIR, "kmeans_image.png"), cv2.cvtColor(img_kmeans, cv2.COLOR_RGBA2BGR))
| ^^^^^^^^^^^^^
28 | # svg file
29 | res_svg = img2num.labels_to_svg(img, labels, 100)
|
F403 `from .api import *` used; unable to detect undefined names
--> packages/py/img2num/__init__.py:1:1
|
1 | from .api import *
| ^^^^^^^^^^^^^^^^^^
|
F401 [*] `numpy` imported but unused
--> packages/py/img2num/api.py:1:17
|
1 | import numpy as np
| ^^
2 | import inspect
3 | import functools
|
help: Remove unused import: `numpy`
SIM108 Use ternary operator `image = kwargs[image_arg] if image_arg in kwargs else args[idx]` instead of `if`-`else`-block
--> packages/py/img2num/api.py:21:13
|
19 | @functools.wraps(fn)
20 | def wrapper(*args, **kwargs):
21 | / if image_arg in kwargs:
22 | | image = kwargs[image_arg]
23 | | else:
24 | | image = args[idx]
| |_________________________________^
25 |
26 | if image.ndim < 2:
|
help: Replace `if`-`else`-block with `image = kwargs[image_arg] if image_arg in kwargs else args[idx]`
E501 Line too long (91 > 88)
--> packages/py/img2num/api.py:53:89
|
51 | @_inject_dims("image")
52 | def bilateral_filter(image, sigma_spatial, sigma_range, color_space, *, width, height):
53 | return _bilateral_filter(image, width, height, sigma_spatial, sigma_range, color_space)
| ^^^
54 |
55 | @_inject_dims("data")
|
E501 Line too long (103 > 88)
--> third_party/dawn/PRESUBMIT.py:132:89
|
130 | if match := reg.search(line):
131 | matches.append(
132 | f"{f.LocalPath()} ({line_num}): found non-inclusive language: {match.group(0)}"
| ^^^^^^^^^^^^^^^
133 | )
|
E501 Line too long (93 > 88)
--> third_party/dawn/PRESUBMIT.py:145:89
|
144 | def _CalculateEnumeratedEntriesAndTypes(lines):
145 | """Returns a dictionary of enumerated entries, and a list of all the 'types' encountered.
| ^^^^^
146 |
147 | The implemented parsing is unsophisticated, and assumes a readable/well-formed .proto file.
|
E501 Line too long (95 > 88)
--> third_party/dawn/PRESUBMIT.py:147:89
|
145 | """Returns a dictionary of enumerated entries, and a list of all the 'types' encountered.
146 |
147 | The implemented parsing is unsophisticated, and assumes a readable/well-formed .proto file.
| ^^^^^^^
148 | Things like unmatched '{}'s will cause a crash. Missing ';'s or writing something like `} message Foo {` will also
149 | cause misbehaviour.
|
E501 Line too long (118 > 88)
--> third_party/dawn/PRESUBMIT.py:148:89
|
147 | The implemented parsing is unsophisticated, and assumes a readable/well-formed .proto file.
148 | Things like unmatched '{}'s will cause a crash. Missing ';'s or writing something like `} message Foo {` will also
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
149 | cause misbehaviour.
150 | Constructs like this are normally bad style, so if really needed, adding support for them is left as an exercise for
|
E501 Line too long (120 > 88)
--> third_party/dawn/PRESUBMIT.py:150:89
|
148 | Things like unmatched '{}'s will cause a crash. Missing ';'s or writing something like `} message Foo {` will also
149 | cause misbehaviour.
150 | Constructs like this are normally bad style, so if really needed, adding support for them is left as an exercise for
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
151 | the reader.
152 | """
|
E741 Ambiguous variable name: `l`
--> third_party/dawn/PRESUBMIT.py:164:9
|
162 | oneof_scopes = set()
163 | types = []
164 | for l in lines:
| ^
165 | l = l.strip().rstrip()
166 | l = l.split("//", 1)[0]
|
E741 Ambiguous variable name: `l`
--> third_party/dawn/PRESUBMIT.py:165:9
|
163 | types = []
164 | for l in lines:
165 | l = l.strip().rstrip()
| ^
166 | l = l.split("//", 1)[0]
167 | while l:
|
E741 Ambiguous variable name: `l`
--> third_party/dawn/PRESUBMIT.py:166:9
|
164 | for l in lines:
165 | l = l.strip().rstrip()
166 | l = l.split("//", 1)[0]
| ^
167 | while l:
168 | if match := re.search(push_re, l):
|
E741 Ambiguous variable name: `l`
--> third_party/dawn/PRESUBMIT.py:174:17
|
172 | prefix_str = '.'.join(prefix_stack)
173 | types.append(prefix_str)
174 | l = match.group(2)
| ^
175 | continue
176 | if match := re.search(reserved_re, l):
|
E741 Ambiguous variable name: `l`
--> third_party/dawn/PRESUBMIT.py:182:17
|
180 | reserved_numbers.extend(new_numbers)
181 | enumerated_entries[f"{prefix_str}.reserved"] = reserved_numbers
182 | l = match.group(1)
| ^
183 | continue
184 | if match := re.search(value_re, l):
|
E741 Ambiguous variable name: `l`
--> third_party/dawn/PRESUBMIT.py:187:17
|
185 | enumerated_entries[
186 | f"{prefix_str}.{match.group(1)}"] = match.group(2)
187 | l = match.group(2)
| ^
188 | continue
189 | if match := re.search(pop_re, l):
|
E741 Ambiguous variable name: `l`
--> third_party/dawn/PRESUBMIT.py:192:17
|
190 | prefix_stack.pop()
191 | prefix_str = '.'.join(prefix_stack)
192 | l = match.group(1)
| ^
193 | continue
194 | l = ""
|
E741 Ambiguous variable name: `l`
--> third_party/dawn/PRESUBMIT.py:194:13
|
192 | l = match.group(1)
193 | continue
194 | l = ""
| ^
195 |
196 | return enumerated_entries, types, oneof_scopes
|
E501 Line too long (118 > 88)
--> third_party/dawn/PRESUBMIT.py:211:89
|
209 | return [
210 | output_api.PresubmitError(
211 | f"Unexpectedly found more than one ir.proto in change, [{file.AbsoluteLocalPath()}, {proto_file}]"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
212 | )
213 | ]
|
UP031 Use format specifiers instead of percent format
--> third_party/dawn/PRESUBMIT.py:274:54
|
272 | except input_api.subprocess.CalledProcessError as e:
273 | if input_api.is_committing:
274 | results.append(output_api.PresubmitError('%s' % (e, )))
| ^^^^^^^^^^^^
275 | else:
276 | results.append(output_api.PresubmitPromptWarning('%s' % (e, )))
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/PRESUBMIT.py:276:62
|
274 | results.append(output_api.PresubmitError('%s' % (e, )))
275 | else:
276 | results.append(output_api.PresubmitPromptWarning('%s' % (e, )))
| ^^^^^^^^^^^^
277 | return results
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/PRESUBMIT.py:308:54
|
306 | except input_api.subprocess.CalledProcessError as e:
307 | if input_api.is_committing:
308 | results.append(output_api.PresubmitError('%s' % (e, )))
| ^^^^^^^^^^^^
309 | else:
310 | results.append(output_api.PresubmitPromptWarning('%s' % (e, )))
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/PRESUBMIT.py:310:62
|
308 | results.append(output_api.PresubmitError('%s' % (e, )))
309 | else:
310 | results.append(output_api.PresubmitPromptWarning('%s' % (e, )))
| ^^^^^^^^^^^^
311 | return results
|
help: Replace with format specifiers
E501 Line too long (109 > 88)
--> third_party/dawn/PRESUBMIT.py:323:89
|
322 | def _CheckCopyrightHeaders(input_api, output_api):
323 | """Checks that newly added files have a correct copyright year and prompts when it finds a discrepancy"""
| ^^^^^^^^^^^^^^^^^^^^^
324 | current_year = int(input_api.time.strftime('%Y'))
325 | copyright_regex = re.compile(r'Copyright (\d{4})')
|
E501 Line too long (121 > 88)
--> third_party/dawn/PRESUBMIT.py:368:89
|
366 | errors.append(
367 | output_api.PresubmitPromptWarning(
368 | f'{f.LocalPath()}: Copyright year is {year}, should be {current_year} as this is a new file.'
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
369 | ))
370 | break
|
E401 [*] Multiple imports on one line
--> third_party/dawn/generator/dawn_gpu_info_generator.py:29:1
|
27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 | import json, os, sys
| ^^^^^^^^^^^^^^^^^^^^
30 | from collections import namedtuple
|
help: Split imports
F401 [*] `collections.namedtuple` imported but unused
--> third_party/dawn/generator/dawn_gpu_info_generator.py:30:25
|
29 | import json, os, sys
30 | from collections import namedtuple
| ^^^^^^^^^^
31 |
32 | from generator_lib import Generator, run_generator, FileRender, GeneratorOutput
|
help: Remove unused import: `collections.namedtuple`
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_gpu_info_generator.py:93:48
|
92 | … # Don't allow duplicate entries
93 | … assert device not in self.devices, 'Architecture "{}" contained duplicate deviceID "{}"'.format(
| __________________________________________^
94 | | … self.name.get(), device)
| |__________________________________^
95 | … # Ensure that all device IDs don't contain bits outside the mask
96 | … assert device_num & mask_num == device_num, 'Architecture "{}" contained deviceID "{}" which doesn\'t match the given mask of "{…
|
help: Convert to f-string
E501 Line too long (108 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:93:89
|
92 | # Don't allow duplicate entries
93 | assert device not in self.devices, 'Architecture "{}" contained duplicate deviceID "{}"'.format(
| ^^^^^^^^^^^^^^^^^^^^
94 | self.name.get(), device)
95 | # Ensure that all device IDs don't contain bits outside the mask
|
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_gpu_info_generator.py:96:57
|
94 | self.name.get(), device)
95 | # Ensure that all device IDs don't contain bits outside the mask
96 | assert device_num & mask_num == device_num, 'Architecture "{}" contained deviceID "{}" which doesn\'t match the given mas…
| _________________________________________________________^
97 | | self.name.get(), device, mask)
| |______________________________________________^
98 |
99 | self.devices.append(device)
|
help: Convert to f-string
E501 Line too long (151 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:96:89
|
94 | …
95 | …n bits outside the mask
96 | …m, 'Architecture "{}" contained deviceID "{}" which doesn\'t match the given mask of "{}"'.format(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
97 | …
|
E501 Line too long (94 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:123:89
|
121 | architecture = Architecture(arch_name, arch_data, self.mask)
122 |
123 | # Validate that deviceIDs are only allowed to be in one Architecture at a time
| ^^^^^^
124 | for other_architecture in self.architectures:
125 | for device in architecture.devices:
|
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_gpu_info_generator.py:126:74
|
124 | for other_architecture in self.architectures:
125 | for device in architecture.devices:
126 | assert device not in other_architecture.devices, 'Architectures "{}" and "{}" both contain deviceID "{}"'.for…
| __________________________________________________________________________^
127 | | architecture.name.get(),
128 | | other_architecture.name.get(), device)
| |__________________________________________________________________^
129 |
130 | self.architectures.append(architecture)
|
help: Convert to f-string
E501 Line too long (137 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:126:89
|
124 | … for other_architecture in self.architectures:
125 | … for device in architecture.devices:
126 | … assert device not in other_architecture.devices, 'Architectures "{}" and "{}" both contain deviceID "{}"'.format(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
127 | … architecture.name.get(),
128 | … other_architecture.name.get(), device)
|
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_gpu_info_generator.py:140:60
|
138 | for device in architecture.devices:
139 | device_num = int(device, 0) & combined_mask
140 | assert device_num != other_device_num, 'DeviceID "{}" & mask "{}" conflicts with deviceId "{}" & mask "{}" in arc…
| ____________________________________________________________^
141 | | other_device, other_mask, device, self.mask,
142 | | architecture.name.get())
| |________________________________________________^
143 |
144 | def maskDeviceId(self):
|
help: Convert to f-string
E501 Line too long (156 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:140:89
|
138 | …
139 | …ed_mask
140 | …m, 'DeviceID "{}" & mask "{}" conflicts with deviceId "{}" & mask "{}" in architecture "{}"'.format(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
141 | …, self.mask,
142 | …
|
E501 Line too long (91 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:172:89
|
170 | … # Validate that deviceIDs are unique across device sets
171 | … for other_device_set in self.device_sets:
172 | … # Only validate device IDs between internal and public device sets.
| ^^^
173 | … if other_device_set.internal == device_set.internal:
174 | … assert device_set.mask != other_device_set.mask, 'Vendor "{}" contained duplicate device masks "{}"'.format(
|
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_gpu_info_generator.py:174:78
|
172 | … # Only validate device IDs between internal and public device sets.
173 | … if other_device_set.internal == device_set.internal:
174 | … assert device_set.mask != other_device_set.mask, 'Vendor "{}" contained duplicate device masks "{}"'.format(
| ____________________________________________________________^
175 | | … self.name.get(), device_set.mask)
| |_______________________________________________^
176 | … other_device_set.validate_devices(
177 | … architecture.devices, device_set.mask)
|
help: Convert to f-string
E501 Line too long (136 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:174:89
|
172 | … # Only validate device IDs between internal and public device sets.
173 | … if other_device_set.internal == device_set.internal:
174 | … assert device_set.mask != other_device_set.mask, 'Vendor "{}" contained duplicate device masks "{}"'.format(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
175 | … self.name.get(), device_set.mask)
176 | … other_device_set.validate_devices(
|
E501 Line too long (110 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:179:89
|
177 | architecture.devices, device_set.mask)
178 |
179 | # Validate that architecture names are unique between internal and public device sets.
| ^^^^^^^^^^^^^^^^^^^^^^
180 | else:
181 | for other_architecture in other_device_set.architectures:
|
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_gpu_info_generator.py:184:36
|
182 | assert architecture.name.canonical_case(
183 | ) != other_architecture.name.canonical_case(
184 | ), '"{}" is defined as both an internal and public architecture'.format(
| ____________________________________^
185 | | architecture.name.get())
| |____________________________________________________________^
186 |
187 | if device_set.internal:
|
help: Convert to f-string
E501 Line too long (104 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:184:89
|
182 | … assert architecture.name.canonical_case(
183 | … ) != other_architecture.name.canonical_case(
184 | … ), '"{}" is defined as both an internal and public architecture'.format(
| ^^^^^^^^^^^^^^^^
185 | … architecture.name.get())
|
E501 Line too long (91 > 88)
--> third_party/dawn/generator/dawn_gpu_info_generator.py:207:89
|
206 | for (vendor_name, vendor_data) in json['vendors'].items():
207 | # Skip vendors that have a leading underscore. Those are intended to be "comments".
| ^^^
208 | if vendor_name[0] == '_':
209 | continue
|
E401 [*] Multiple imports on one line
--> third_party/dawn/generator/dawn_json_generator.py:29:1
|
27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 | import json, os, sys
| ^^^^^^^^^^^^^^^^^^^^
30 | from collections import namedtuple, defaultdict
31 | from copy import deepcopy
|
help: Split imports
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/dawn_json_generator.py:121:16
|
120 | tags = json_data.get('tags')
121 | if tags != None:
| ^^^^
122 | for tag in tags:
123 | assert tag in allowed_tags, f'unrecognized tag "{tag}"'
|
help: Replace with `cond is not None`
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/generator/dawn_json_generator.py:161:24
|
159 | value_name = m['name']
160 | tags = validate_and_get_tags(m)
161 | if tags == None:
| ^^^^
162 | tags = []
|
help: Replace with `cond is None`
E501 Line too long (91 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:182:89
|
181 | if 'deprecated' not in tags:
182 | # Emscripten implements some Dawn extensions, and some upstream things that
| ^^^
183 | # aren't in Dawn yet.
184 | if 'emscripten' in tags and 'dawn' not in tags:
|
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/generator/dawn_json_generator.py:193:29
|
191 | if value_name == "undefined":
192 | self.hasUndefined = True
193 | if lastValue == None:
| ^^^^
194 | self.startValue = value
195 | elif value != lastValue + 1:
|
help: Replace with `cond is None`
E501 Line too long (98 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:201:89
|
199 | EnumValue(Name(value_name), value, m.get('valid', True), m))
200 |
201 | # Assert that all values except those with "enum_value_conflict": true are unique in enums
| ^^^^^^^^^^
202 | all_values = set()
203 | for value in self.values:
|
SIM102 Use a single `if` statement instead of nested `if` statements
--> third_party/dawn/generator/dawn_json_generator.py:204:13
|
202 | all_values = set()
203 | for value in self.values:
204 | / if value.value in all_values:
205 | | #TODO(42241174) remove this condition once wgpu refactoring is complete.
206 | | if not value.json_data.get('enum_value_conflict', False):
| |_________________________________________________________________________^
207 | raise Exception(
208 | "Duplicate value {} for '{}' in enum '{}'".format(
|
help: Combine `if` statements using `and`
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_json_generator.py:208:25
|
206 | if not value.json_data.get('enum_value_conflict', False):
207 | raise Exception(
208 | / "Duplicate value {} for '{}' in enum '{}'".format(
209 | | hex(value.value), value.name.get(), name))
| |_____________________________________________________________________^
210 | all_values.add(value.value)
211 | self.is_wire_transparent = True
|
help: Convert to f-string
E501 Line too long (99 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:291:89
|
289 | self.array_element_optional = array_element_optional
290 | if array_element_optional:
291 | assert annotation == 'const*', 'array_element_optional can only be used on array types'
| ^^^^^^^^^^^
292 | self.is_return_value = is_return_value
293 | self.handle_type = None
|
UP039 [*] Unnecessary parentheses after class definition
--> third_party/dawn/generator/dawn_json_generator.py:320:13
|
320 | class Method():
| ^^
321 |
322 | def __init__(self, name, returns, arguments, autolock, json_data):
|
help: Remove parentheses
UP039 [*] Unnecessary parentheses after class definition
--> third_party/dawn/generator/dawn_json_generator.py:445:25
|
445 | class ConstantDefinition():
| ^^
446 |
447 | def __init__(self, is_enabled, name, json_data):
|
help: Remove parentheses
UP039 [*] Unnecessary parentheses after class definition
--> third_party/dawn/generator/dawn_json_generator.py:455:26
|
455 | class FunctionDeclaration():
| ^^
456 |
457 | def __init__(self, is_enabled, name, json_data, no_cpp=False):
|
help: Remove parentheses
B905 `zip()` without an explicit `strict=` parameter
--> third_party/dawn/generator/dawn_json_generator.py:497:24
|
495 | members_by_name[member.name.canonical_case()] = member
496 |
497 | for (member, m) in zip(members, json_data):
| ^^^^^^^^^^^^^^^^^^^^^^^
498 | if member.annotation != 'value':
499 | if not 'length' in m:
|
help: Add explicit value for parameter `strict=`
E713 [*] Test for membership should be `not in`
--> third_party/dawn/generator/dawn_json_generator.py:499:20
|
497 | for (member, m) in zip(members, json_data):
498 | if member.annotation != 'value':
499 | if not 'length' in m:
| ^^^^^^^^^^^^^
500 | if member.type.category != 'object':
501 | member.length = "constant"
|
help: Convert to `not in`
B011 Do not `assert False` (`python -O` removes these calls), raise `AssertionError()`
--> third_party/dawn/generator/dawn_json_generator.py:504:28
|
502 | member.constant_length = 1
503 | else:
504 | assert False
| ^^^^^
505 | elif isinstance(m['length'], int):
506 | assert m['length'] > 0
|
help: Replace `assert False`
UP034 [*] Avoid extraneous parentheses
--> third_party/dawn/generator/dawn_json_generator.py:545:16
|
543 | types[root] for root in struct.json_data.get('chain roots', [])
544 | ]
545 | assert all((root.category == 'structure' for root in struct.chain_roots))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Remove extraneous parentheses
E721 Use `is` and `is not` for type comparisons, or `isinstance()` for isinstance checks
--> third_party/dawn/generator/dawn_json_generator.py:566:12
|
564 | assert returns != 'void', '"returns": "void" should be omitted instead'
565 | if returns:
566 | if type(returns) == str:
| ^^^^^^^^^^^^^^^^^^^^
567 | returns = {'type': returns}
568 | function.returns = AnnotatedTypedMember(
|
SIM102 Use a single `if` statement instead of nested `if` statements
--> third_party/dawn/generator/dawn_json_generator.py:645:17
|
643 | for method in object.methods:
644 | for arg in method.arguments:
645 | / if arg.type.category == 'object':
646 | | if arg.optional:
| |____________________________________^
647 | max_dependent_depth = max(max_dependent_depth,
648 | compute_depth(arg.type) + 1)
|
help: Combine `if` statements using `and`
E731 Do not assign a `lambda` expression, use a `def`
--> third_party/dawn/generator/dawn_json_generator.py:667:5
|
666 | def parse_json(json, enabled_tags, disabled_tags=None):
667 | / is_enabled = lambda json_data: item_is_enabled(
668 | | enabled_tags, json_data) and not item_is_disabled(
669 | | disabled_tags, json_data)
| |_____________________________________^
670 | category_to_parser = {
671 | 'bitmask': BitmaskType,
|
help: Rewrite `is_enabled` as a `def`
SIM118 [*] Use `key in dict` instead of `key in dict.keys()`
--> third_party/dawn/generator/dawn_json_generator.py:687:9
|
686 | by_category = {}
687 | for name in category_to_parser.keys():
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
688 | by_category[name] = []
|
help: Remove `.keys()`
SIM118 [*] Use `key in dict` instead of `key in dict.keys()`
--> third_party/dawn/generator/dawn_json_generator.py:723:9
|
722 | # Sort everything by name
723 | for category in by_category.keys():
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
724 | by_category[category] = sorted(by_category[category],
725 | key=lambda typ: typ.name)
|
help: Remove `.keys()`
E501 Line too long (96 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:774:89
|
772 | # Generate commands from object methods
773 | for api_object in wire_params['by_category']['object']:
774 | # Reference counting functions are generated separately, so label them as "handwritten".
| ^^^^^^^^
775 | wire_json['special items']['client_handwritten_commands'] += [
776 | api_object.name.CamelCase() + 'AddRef',
|
E501 Line too long (89 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:786:89
|
784 | # Only object return values, status or void are supported:
785 | #
786 | #- "void" is not a return value so commands can just be pushed to the server.
| ^
787 | # - objects use the wire's "promise pipelining" and will be sent associated with the
788 | # WireHandle provided by the client.
|
E501 Line too long (96 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:787:89
|
785 | #
786 | #- "void" is not a return value so commands can just be pushed to the server.
787 | # - objects use the wire's "promise pipelining" and will be sent associated with the
| ^^^^^^^^
788 | # WireHandle provided by the client.
789 | # - "status" is used to synchronously return validation errors so the server checks that
|
E501 Line too long (100 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:789:89
|
787 | # - objects use the wire's "promise pipelining" and will be sent associated with the
788 | # WireHandle provided by the client.
789 | # - "status" is used to synchronously return validation errors so the server checks that
| ^^^^^^^^^^^^
790 | # they are always a success.
791 | #
|
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/generator/dawn_json_generator.py:796:41
|
794 | is_status = method.returns and method.returns.type.name.canonical_case(
795 | ) == 'status'
796 | is_void = method.returns == None
| ^^^^
797 | if not (is_object or is_status or is_void):
798 | assert command_suffix in (
|
help: Replace with `cond is None`
E501 Line too long (94 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:829:89
|
827 | commands.append(command)
828 |
829 | # Generate commands from structure methods. Notes that currently this is only FreeMembers.
| ^^^^^^
830 | for api_struct in wire_params['by_category']['structure']:
831 | wire_json['special items']['client_handwritten_commands'] += [
|
E501 Line too long (98 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:880:89
|
879 | def mark_n2k(typ):
880 | # Only proceed if it's a structure and hasn't been marked yet to avoid infinite recursion.
| ^^^^^^^^^^
881 | if isinstance(typ, StructureType) and not typ.needs_n2k:
882 | typ.needs_n2k = True
|
E501 Line too long (98 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:888:89
|
887 | def mark_k2n(typ):
888 | # Only proceed if it's a structure and hasn't been marked yet to avoid infinite recursion.
| ^^^^^^^^^^
889 | if isinstance(typ, StructureType) and not typ.needs_k2n:
890 | typ.needs_k2n = True
|
E501 Line too long (94 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:960:89
|
958 | for callback_info_member in member.type.members:
959 | if callback_info_member.type.category == 'callback function':
960 | # We give the callback function a new name based on the callback info.
| ^^^^^^
961 | name = member.name.get().removesuffix(' info')
962 | function_member = deepcopy(callback_info_member)
|
E501 Line too long (99 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:973:89
|
971 | continue
972 |
973 | # userdata parameter omitted because Kotlin clients can achieve the same with closures.
| ^^^^^^^^^^^
974 | if member.name.get() == 'userdata':
975 | continue
|
E501 Line too long (95 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:977:89
|
975 | continue
976 |
977 | # Dawn sometimes uses 'annotation = *' for output parameters, for example to return
| ^^^^^^^
978 | # arrays. We convert the return type and strip out the parameters.
979 | if member.annotation == '*' and member.length == 'constant':
|
E501 Line too long (91 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:993:89
|
991 | yield member
992 |
993 | # Calculate if we should, and can, provide a Kotlin default value for a given argument.
| ^^^
994 | # This will affect its order in the method parameter and structure field lists.
995 | def kotlin_default(arg):
|
E501 Line too long (99 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:996:89
|
994 | # This will affect its order in the method parameter and structure field lists.
995 | def kotlin_default(arg):
996 | # Optional and non-optional container parameters are defaulted to empty containers to match
| ^^^^^^^^^^^
997 | # the behavior of the JavaScript API.
998 | if arg.length and arg.length != 'constant' and arg.type.name.get(
|
E501 Line too long (97 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1011:89
|
1009 | return 'null'
1010 |
1011 | # Non-optional structures are defaulted to a defaulted structure if we can construct one.
| ^^^^^^^^^
1012 | # This is to match the behavior of the JavaScript API which lets clients pass undefined
1013 | # structure values even for non-optional fields.
|
E501 Line too long (95 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1012:89
|
1011 | # Non-optional structures are defaulted to a defaulted structure if we can construct one.
1012 | # This is to match the behavior of the JavaScript API which lets clients pass undefined
| ^^^^^^^
1013 | # structure values even for non-optional fields.
1014 | if arg.type.category in [
|
E501 Line too long (95 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1020:89
|
1018 | for member in arg.type.members):
1019 | constructor_args = []
1020 | # default_value = zero is a special defaulting variation from C we have to emulate.
| ^^^^^^^
1021 | if arg.default_value == 'zero':
1022 | constructor_args = [
|
E501 Line too long (117 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1023:89
|
1021 | if arg.default_value == 'zero':
1022 | constructor_args = [
1023 | f"{member.name.camelCase()} = {member.type.name.CamelCase()}.{as_ktName(value.name.CamelCase())}"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1024 | for member in kotlin_record_members(arg.type.members)
1025 | if member.type.category in ['bitmask', 'enum']
|
E501 Line too long (98 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1030:89
|
1028 | return f"{kotlin_name(arg.type)}({', '.join(constructor_args)})"
1029 |
1030 | # For bitmasks/enums we insert the full type of the default. No default value doesn't mean
| ^^^^^^^^^^
1031 | # no default in the bindings, because it should match the bitmask/enum labeled 'undefined'.
1032 | if arg.type.category in ['bitmask', 'enum']:
|
E501 Line too long (99 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1031:89
|
1030 | # For bitmasks/enums we insert the full type of the default. No default value doesn't mean
1031 | # no default in the bindings, because it should match the bitmask/enum labeled 'undefined'.
| ^^^^^^^^^^^
1032 | if arg.type.category in ['bitmask', 'enum']:
1033 | for value in arg.type.values:
|
E501 Line too long (93 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1035:89
|
1033 | for value in arg.type.values:
1034 | if value.name.name == (arg.default_value or 'undefined'):
1035 | return f"{arg.type.name.CamelCase()}.{as_ktName(value.name.CamelCase())}"
| ^^^^^
1036 | return arg.default_value
|
E501 Line too long (91 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1043:89
|
1042 | if arg.type.category == 'native':
1043 | # Is this a Dawn named constant that can be matched with the global definition?
| ^^^
1044 | constant = find_by_name(by_category["constant"], arg.default_value)
1045 | if constant:
|
UP031 Use format specifiers instead of percent format
--> third_party/dawn/generator/dawn_json_generator.py:1050:24
|
1048 | # Convert double/floats to the Kotlin format.
1049 | if arg.type.name.get() in ['double', 'float']:
1050 | return "%.1ff" % float(arg.default_value.rstrip('fF'))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1051 |
1052 | # Java doesn't have unsigned 32 bit / 64 bit variables so the cleanest workaround is
|
help: Replace with format specifiers
E501 Line too long (96 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1052:89
|
1050 | return "%.1ff" % float(arg.default_value.rstrip('fF'))
1051 |
1052 | # Java doesn't have unsigned 32 bit / 64 bit variables so the cleanest workaround is
| ^^^^^^^^
1053 | # to insert the bitwise equivalent of a signed number.
1054 | if arg.type.name.get() in ['int', 'int32_t', 'uint32_t'
|
E501 Line too long (96 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1062:89
|
1060 | return '-1'
1061 |
1062 | # In all remaining cases the default as specified in dawn.json will work verbatim in
| ^^^^^^^^
1063 | # Kotlin.
1064 | return arg.default_value
|
E501 Line too long (92 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1067:89
|
1066 | unreachable_code(
1067 | f"no logic to default '{arg.type.name.get()}' in category '{arg.type.category}'"
| ^^^^
1068 | )
1069 | return None
|
E501 Line too long (100 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1072:89
|
1071 | def kotlin_name(type):
1072 | return f"{'GPU' if type.category in ('object', 'structure') else ''}{type.name.CamelCase()}"
| ^^^^^^^^^^^^
1073 |
1074 | def kotlin_return(method):
|
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/generator/dawn_json_generator.py:1080:40
|
1078 | ) == 'size_t':
1079 | unreachable_code("Returning containers is not supported")
1080 | if ((method.returns == None
| ^^^^
1081 | or method.returns.type.name.get() == 'status')
1082 | and argument.type.category == 'structure'):
|
help: Replace with `cond is None`
E501 Line too long (92 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1088:89
|
1086 | if (method.returns
1087 | and method.returns.type.name.canonical_case() == 'status'):
1088 | # This is a function like GPUBuffer.readMappedRange(). Its C return is a status,
| ^^^^
1089 | # but it has no "out" parameters. The idiomatic Kotlin function
1090 | # should return Unit and throw an exception on failure.
|
E501 Line too long (100 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1094:89
|
1093 | # If the function should return an omitted structure, we return nothing instead.
1094 | if method.returns and method.returns.type.category == 'structure' and not include_structure(
| ^^^^^^^^^^^^
1095 | method.returns.type):
1096 | return None
|
E501 Line too long (96 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1099:89
|
1098 | # Return values are not treated as optional to keep the Kotlin API simple.
1099 | # Methods are expected to return an object if declared. If they can't, dawn may raise an
| ^^^^^^^^
1100 | # error (converted to a Kotlin exception); otherwise JNI will throw NullPointerException.
1101 | # In either case the optional type is redundant.
|
E501 Line too long (97 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1100:89
|
1098 | # Return values are not treated as optional to keep the Kotlin API simple.
1099 | # Methods are expected to return an object if declared. If they can't, dawn may raise an
1100 | # error (converted to a Kotlin exception); otherwise JNI will throw NullPointerException.
| ^^^^^^^^^
1101 | # In either case the optional type is redundant.
1102 | return AnnotatedTypedMember(
|
E501 Line too long (89 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1158:89
|
1156 | return f"{kt_file_path}/{kotlin_name(type)}"
1157 |
1158 | # A structure may need to know which other structures listed it as a chain root, e.g.
| ^
1159 | # to know whether to mark the generated class 'open'.
1160 | chain_children = defaultdict(list)
|
E701 Multiple statements on one line (colon)
--> third_party/dawn/generator/dawn_json_generator.py:1246:35
|
1245 | def as_jsEnumValue(value):
1246 | if 'jsrepr' in value.json_data: return value.json_data['jsrepr']
| ^
1247 | return "'" + value.name.js_enum_case() + "'"
|
E501 Line too long (89 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1254:89
|
1254 | # Returns a single character wasm type (v/p/i/j/f/d) if valid, a "(longer string)" if not
| ^
1255 | def as_wasmType(x):
1256 | if x is None:
|
B011 Do not `assert False` (`python -O` removes these calls), raise `AssertionError()`
--> third_party/dawn/generator/dawn_json_generator.py:1279:20
|
1277 | return f'({x.name.name})' # Invalid
1278 | else:
1279 | assert False, 'Type -> ' + x.category
| ^^^^^
|
help: Replace `assert False`
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_json_generator.py:1287:20
|
1285 | if annotation == 'value':
1286 | if typ.category == 'object':
1287 | return '{}::Acquire({})'.format(as_cppType(typ.name), arg)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1288 | elif typ.category == 'structure':
1289 | converted_members = [
|
help: Convert to f-string
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_json_generator.py:1292:21
|
1290 | convert_cType_to_cppType(
1291 | member.type, member.annotation,
1292 | '{}.{}'.format(arg, as_varName(member.name)), indent + 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1293 | for member in typ.members
1294 | ]
|
help: Convert to f-string
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_json_generator.py:1301:20
|
1299 | return as_cppType(typ.name) + ' {\n' + converted_members + '\n}'
1300 | elif typ.category == 'function pointer':
1301 | return 'reinterpret_cast<{}>({})'.format(as_cppType(typ.name), arg)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1302 | else:
1303 | return 'static_cast<{}>({})'.format(as_cppType(typ.name), arg)
|
help: Convert to f-string
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_json_generator.py:1303:20
|
1301 | return 'reinterpret_cast<{}>({})'.format(as_cppType(typ.name), arg)
1302 | else:
1303 | return 'static_cast<{}>({})'.format(as_cppType(typ.name), arg)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1304 | else:
1305 | return 'reinterpret_cast<{} {}>({})'.format(as_cppType(typ.name),
|
help: Convert to f-string
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/dawn_json_generator.py:1305:16
|
1303 | return 'static_cast<{}>({})'.format(as_cppType(typ.name), arg)
1304 | else:
1305 | return 'reinterpret_cast<{} {}>({})'.format(as_cppType(typ.name),
| ________________^
1306 | | annotation, arg)
| |____________________________________________________________________^
|
help: Convert to f-string
E701 Multiple statements on one line (colon)
--> third_party/dawn/generator/dawn_json_generator.py:1335:20
|
1333 | def item_is_enabled(enabled_tags, json_data):
1334 | tags = validate_and_get_tags(json_data)
1335 | if tags is None: return True
| ^
1336 | return any(tag in enabled_tags for tag in tags)
|
E701 Multiple statements on one line (colon)
--> third_party/dawn/generator/dawn_json_generator.py:1340:29
|
1339 | def item_is_disabled(disabled_tags, json_data):
1340 | if disabled_tags is None: return False
| ^
1341 | tags = validate_and_get_tags(json_data)
1342 | if tags is None: return False
|
E701 Multiple statements on one line (colon)
--> third_party/dawn/generator/dawn_json_generator.py:1342:20
|
1340 | if disabled_tags is None: return False
1341 | tags = validate_and_get_tags(json_data)
1342 | if tags is None: return False
| ^
1343 |
1344 | return any(tag in disabled_tags for tag in tags)
|
B011 Do not `assert False` (`python -O` removes these calls), raise `AssertionError()`
--> third_party/dawn/generator/dawn_json_generator.py:1398:16
|
1396 | return []
1397 | else:
1398 | assert False, "c_methods only valid on objects and structure"
| ^^^^^
|
help: Replace `assert False`
B011 Do not `assert False` (`python -O` removes these calls), raise `AssertionError()`
--> third_party/dawn/generator/dawn_json_generator.py:1454:12
|
1453 | def unreachable_code(msg="unreachable_code"):
1454 | assert False, msg
| ^^^^^
|
help: Replace `assert False`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/dawn_json_generator.py:1483:25
|
1481 | def as_cProc(type_name, method_name):
1482 | c_proc = c_prefix + 'Proc'
1483 | if type_name != None:
| ^^^^
1484 | assert not type_name.native
1485 | c_proc += type_name.CamelCase()
|
help: Replace with `cond is not None`
E501 Line too long (127 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1493:89
|
1491 | 'Name': lambda name: Name(name),
1492 | 'as_nullability_annotated_cType': \
1493 | lambda arg: 'void' if arg is None else annotate(as_cTypeEnumSpecialCase(arg.type), arg, with_nullability=True),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1494 | 'as_annotated_cType': \
1495 | lambda arg: 'void' if arg is None else annotate(as_cTypeEnumSpecialCase(arg.type), arg),
|
E501 Line too long (104 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1495:89
|
1493 | … lambda arg: 'void' if arg is None else annotate(as_cTypeEnumSpecialCase(arg.type), arg, with_nullability=True),
1494 | … 'as_annotated_cType': \
1495 | … lambda arg: 'void' if arg is None else annotate(as_cTypeEnumSpecialCase(arg.type), arg),
| ^^^^^^^^^^^^^^^^
1496 | … 'as_annotated_cppType': \
1497 | … lambda arg, make_const_member=False: 'void' if arg is None else annotate(as_cppType(arg.type.name), arg, make_const_member…
|
E501 Line too long (158 > 88)
--> third_party/dawn/generator/dawn_json_generator.py:1497:89
|
1495 | …otate(as_cTypeEnumSpecialCase(arg.type), arg),
1496 | …
1497 | …' if arg is None else annotate(as_cppType(arg.type.name), arg, make_const_member=make_const_member),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1498 | …
1499 | …
|
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/dawn_json_generator.py:2042:30
|
2040 | def get_dependencies(self, args):
2041 | deps = [os.path.abspath(args.dawn_json)]
2042 | if args.wire_json != None:
| ^^^^
2043 | deps += [os.path.abspath(args.wire_json)]
2044 | if args.kotlin_json != None:
|
help: Replace with `cond is not None`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/dawn_json_generator.py:2044:32
|
2042 | if args.wire_json != None:
2043 | deps += [os.path.abspath(args.wire_json)]
2044 | if args.kotlin_json != None:
| ^^^^
2045 | deps += [os.path.abspath(args.kotlin_json)]
2046 | return deps
|
help: Replace with `cond is not None`
E401 [*] Multiple imports on one line
--> third_party/dawn/generator/dawn_version_generator.py:29:1
|
27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 | import os, subprocess, sys, shutil
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30 |
31 | from generator_lib import Generator, run_generator, FileRender, GeneratorOutput
|
help: Split imports
E501 Line too long (96 > 88)
--> third_party/dawn/generator/dawn_version_generator.py:52:89
|
50 | except Exception:
51 | return ""
52 | # No hash was available (possibly) because the directory was not a git checkout. Dawn should
| ^^^^^^^^
53 | # explicitly handle its absenece and disable features relying on the hash, i.e. caching.
54 | return ""
|
E501 Line too long (92 > 88)
--> third_party/dawn/generator/dawn_version_generator.py:53:89
|
51 | return ""
52 | # No hash was available (possibly) because the directory was not a git checkout. Dawn should
53 | # explicitly handle its absenece and disable features relying on the hash, i.e. caching.
| ^^^^
54 | return ""
|
E501 Line too long (100 > 88)
--> third_party/dawn/generator/dawn_version_generator.py:93:89
|
91 | result.stdout.decode("utf-8").strip())
92 |
93 | # Check a packed-refs file exists. If so, we need to potentially unpack and include it as a dep.
| ^^^^^^^^^^^^
94 | packed = os.path.join(dawn_dir, ".git", "packed-refs")
95 | if os.path.exists(packed) and unpack_git_ref(packed, resolved):
|
E501 Line too long (100 > 88)
--> third_party/dawn/generator/dawn_version_generator.py:136:89
|
134 | def get_description(self):
135 | return (
136 | "Generates version dependent Dawn code. Currently regenerated dependent on the version "
| ^^^^^^^^^^^^
137 | "header (if available), otherwise tries to use git hash.")
|
E401 [*] Multiple imports on one line
--> third_party/dawn/generator/extract_json.py:28:1
|
26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | import os, sys, json
| ^^^^^^^^^^^^^^^^^^^^
29 |
30 | if __name__ == "__main__":
|
help: Split imports
UP015 [*] Unnecessary mode argument
--> third_party/dawn/generator/extract_json.py:50:36
|
48 | # Skip writing to the file if it already has the correct content.
49 | try:
50 | with open(output_file, 'r') as outfile:
| ^^^
51 | if outfile.read() == content:
52 | continue
|
help: Remove mode argument
UP024 [*] Replace aliased errors with `OSError`
--> third_party/dawn/generator/extract_json.py:53:16
|
51 | if outfile.read() == content:
52 | continue
53 | except (OSError, EnvironmentError):
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
54 | pass
|
help: Replace with builtin `OSError`
E401 [*] Multiple imports on one line
--> third_party/dawn/generator/generator_lib.py:51:1
|
49 | """
50 |
51 | import argparse, json, os, re, sys
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52 | from collections import namedtuple
|
help: Split imports
E402 Module level import not at top of file
--> third_party/dawn/generator/generator_lib.py:129:1
|
127 | pass
128 |
129 | import jinja2
| ^^^^^^^^^^^^^
|
E713 [*] Test for membership should be `not in`
--> third_party/dawn/generator/generator_lib.py:146:16
|
145 | def get_source(self, environment, template):
146 | if not template in self.allow_list:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
147 | raise jinja2.TemplateNotFound(template)
|
help: Convert to `not in`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/generator_lib.py:345:24
|
344 | # Output a list of all dependencies for CMake or the tarball for GN/Ninja.
345 | if args.depfile != None or args.print_cmake_dependencies:
| ^^^^
346 | dependencies = generator.get_dependencies(args)
347 | dependencies += [
|
help: Replace with `cond is not None`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/generator_lib.py:357:28
|
355 | dependencies += _compute_python_dependencies(args.root_dir)
356 |
357 | if args.depfile != None:
| ^^^^
358 | with open(args.depfile, 'w') as f:
359 | f.write(args.output_json_tarball + ": " +
|
help: Replace with `cond is not None`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/generator_lib.py:368:38
|
366 | # The caller wants to assert that the outputs are what it expects.
367 | # Load the file and compare with our renders.
368 | if args.expected_outputs_file != None:
| ^^^^
369 | with open(args.expected_outputs_file) as f:
370 | expected = set([line.strip() for line in f.readlines()])
|
help: Replace with `cond is not None`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/generator_lib.py:392:36
|
391 | # Output the JSON tarball
392 | if args.output_json_tarball != None:
| ^^^^
393 | json_root = {}
394 | for output in render_outputs:
|
help: Replace with `cond is not None`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/generator_lib.py:401:27
|
400 | # Output the files directly.
401 | if args.output_dir != None:
| ^^^^
402 | for output in render_outputs:
403 | output_path = os.path.join(args.output_dir, output.name)
|
help: Replace with `cond is not None`
E401 [*] Multiple imports on one line
--> third_party/dawn/generator/opengl_loader_generator.py:29:1
|
27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 | import os, json, sys
| ^^^^^^^^^^^^^^^^^^^^
30 | from collections import namedtuple
31 | import xml.etree.ElementTree as etree
|
help: Split imports
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/generator/opengl_loader_generator.py:40:25
|
38 | def __init__(self, gl_name, proc_name=None):
39 | assert gl_name.startswith('gl')
40 | if proc_name == None:
| ^^^^
41 | proc_name = gl_name[2:]
|
help: Replace with `cond is None`
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/opengl_loader_generator.py:56:16
|
55 | def __repr__(self):
56 | return 'Proc("{}", "{}")'.format(self.gl_name, self.proc_name)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Convert to f-string
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/opengl_loader_generator.py:79:32
|
77 | def parse_type_declaration(element):
78 | result = ''
79 | if element.text != None:
| ^^^^
80 | result += element.text
81 | ptype = element.find('ptype')
|
help: Replace with `cond is not None`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/opengl_loader_generator.py:82:25
|
80 | result += element.text
81 | ptype = element.find('ptype')
82 | if ptype != None:
| ^^^^
83 | result += ptype.text
84 | if ptype.tail != None:
|
help: Replace with `cond is not None`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/opengl_loader_generator.py:84:34
|
82 | if ptype != None:
83 | result += ptype.text
84 | if ptype.tail != None:
| ^^^^
85 | result += ptype.tail
86 | return result.strip()
|
help: Replace with `cond is not None`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/generator/opengl_loader_generator.py:100:37
|
98 | self.gl_name = proto.find('name').text
99 | self.alias = None
100 | if element.find('alias') != None:
| ^^^^
101 | self.alias = element.find('alias').attrib['name']
|
help: Replace with `cond is not None`
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/opengl_loader_generator.py:114:16
|
113 | def __repr__(self):
114 | return 'Proc("{}")'.format(self.gl_name)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Convert to f-string
B006 Do not use mutable data structures for argument defaults
--> third_party/dawn/generator/opengl_loader_generator.py:153:49
|
152 | # Get list of enums and procs per OpenGL ES/Desktop OpenGL version
153 | def parse_version_blocks(api, removed_procs=set()):
| ^^^^^
154 | blocks = []
155 | for section in root.findall('''feature[@api='{}']'''.format(api)):
|
help: Replace with `None`; initialize within function
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/opengl_loader_generator.py:155:37
|
153 | def parse_version_blocks(api, removed_procs=set()):
154 | blocks = []
155 | for section in root.findall('''feature[@api='{}']'''.format(api)):
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
156 | section_procs = []
157 | for command in section.findall('./require/command'):
|
help: Convert to f-string
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/generator/opengl_loader_generator.py:159:54
|
157 | for command in section.findall('./require/command'):
158 | proc_name = command.attrib['name']
159 | assert all_procs[proc_name].alias == None
| ^^^^
160 | if proc_name not in removed_procs:
161 | section_procs.append(all_procs[proc_name])
|
help: Replace with `cond is None`
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/opengl_loader_generator.py:178:13
|
176 | def parse_extension_block(extension):
177 | section = root.find(
178 | '''extensions/extension[@name='{}']'''.format(extension))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
179 | supported_specs = section.attrib['supported'].split('|')
180 | section_procs = []
|
help: Convert to f-string
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/generator/opengl_loader_generator.py:183:50
|
181 | for command in section.findall('./require/command'):
182 | proc_name = command.attrib['name']
183 | assert all_procs[proc_name].alias == None
| ^^^^
184 | section_procs.append(all_procs[proc_name])
|
help: Replace with `cond is None`
E713 [*] Test for membership should be `not in`
--> third_party/dawn/generator/opengl_loader_generator.py:210:20
|
208 | block_procs = []
209 | for proc in block.procs:
210 | if not proc.glProcName() in already_added_header_procs:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
211 | already_added_header_procs.add(proc.glProcName())
212 | block_procs.append(proc)
|
help: Convert to `not in`
E713 [*] Test for membership should be `not in`
--> third_party/dawn/generator/opengl_loader_generator.py:216:20
|
214 | block_enums = []
215 | for enum in block.enums:
216 | if not enum.name in already_added_header_enums:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
217 | already_added_header_enums.add(enum.name)
218 | block_enums.append(enum)
|
help: Convert to `not in`
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/opengl_loader_generator.py:226:13
|
224 | for block in gles_blocks:
225 | add_header_block(
226 | 'OpenGL ES {}.{}'.format(block.version.major, block.version.minor),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
227 | block)
|
help: Convert to f-string
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/generator/opengl_loader_generator.py:231:13
|
229 | for block in desktop_gl_blocks:
230 | add_header_block(
231 | / 'Desktop OpenGL {}.{}'.format(block.version.major,
232 | | block.version.minor), block)
| |______________________________________________________________^
233 |
234 | for block in extension_desktop_gl_blocks:
|
help: Convert to f-string
E501 Line too long (90 > 88)
--> third_party/dawn/generator/webgpu_docs_utility.py:119:89
|
117 | log_warning(
118 | log_file,
119 | f"Missing documentation for all {part_type} of {item_type} '{item_name}'."
| ^^
120 | )
121 | else:
|
E501 Line too long (115 > 88)
--> third_party/dawn/generator/webgpu_docs_utility.py:124:89
|
122 | log_warning(
123 | log_file,
124 | f"Missing documentation for {part_type} of {item_type} '{item_name}': {', '.join(missing_parts)}. "
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
125 | f"(Found for: {', '.join(found_parts)})")
126 | return False
|
E501 Line too long (91 > 88)
--> third_party/dawn/generator/webgpu_docs_utility.py:138:89
|
136 | """Cleans a docstring by validating and formatting references for Kotlin KDoc."""
137 | # These are special-cased references that are not part of the API but are
138 | # used in the documentation. They are manually mapped in the `dawn_kotlin` JSON config.
| ^^^
139 | KOTLIN_HARDCODED_LINK_REFS = [
140 | "CallbackStatuses",
|
E501 Line too long (90 > 88)
--> third_party/dawn/generator/webgpu_docs_utility.py:217:89
|
216 | def replacer(match):
217 | """Converts a matched object-method name to a qualified KDoc @see link."""
| ^^
218 | object_name = match.group(
219 | 1) # The object name, e.g., "Instance"
|
B023 Function definition does not bind loop variable `methods`
--> third_party/dawn/generator/webgpu_docs_utility.py:222:31
|
220 | arg_name = match.group(2) # The arg name, e.g., "WaitAny"
221 | y_camel = arg_name[0].lower() + arg_name[1:] # e.g., "waitAny"
222 | if y_camel in methods:
| ^^^^^^^
223 | kotlin_str = f'{object_name}.{y_camel}'
224 | return kotlin_str if "@see" in doc else f'@see {kotlin_str}'
|
B023 Function definition does not bind loop variable `doc`
--> third_party/dawn/generator/webgpu_docs_utility.py:224:52
|
222 | if y_camel in methods:
223 | kotlin_str = f'{object_name}.{y_camel}'
224 | return kotlin_str if "@see" in doc else f'@see {kotlin_str}'
| ^^^
225 | return match.group(0) # Return original if not a valid method
|
SIM118 Use `key in dict` instead of `key in dict.keys()`
--> third_party/dawn/generator/webgpu_docs_utility.py:259:13
|
257 | # Prefixes object names with 'GPU' for Kotlin references.
258 | if object_methods:
259 | for obj_name in object_methods.keys():
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
260 | doc = re.sub(r'\b' + re.escape(obj_name) + r'\b', 'GPU' + obj_name,
261 | doc)
|
help: Remove `.keys()`
E501 Line too long (89 > 88)
--> third_party/dawn/generator/webgpu_docs_utility.py:431:89
|
429 | by_category_lookups[data_category] = name_to_item_map
430 |
431 | # Iterate through categorized API data and extract docs from corresponding JSON data.
| ^
432 | for category, items in by_category.items():
433 | data_category = category_map.get(category)
|
SIM102 Use a single `if` statement instead of nested `if` statements
--> third_party/dawn/generator/webgpu_docs_utility.py:472:13
|
470 | if not doc_node or not doc_node.strip():
471 | is_main_doc_missing = True
472 | / elif isinstance(doc_node, dict):
473 | | if not doc_node.get('doc') or not doc_node.get('doc').strip():
| |______________________________________________________________________________^
474 | is_main_doc_missing = True
|
help: Combine `if` statements using `and`
E501 Line too long (89 > 88)
--> third_party/dawn/generator/webgpu_docs_utility.py:502:89
|
500 | log_warning(
501 | log_file,
502 | f"Missing documentation for all methods of object '{item_name}'."
| ^
503 | )
504 | continue
|
E501 Line too long (90 > 88)
--> third_party/dawn/generator/webgpu_docs_utility.py:517:89
|
515 | log_warning(
516 | log_file,
517 | f"Missing main documentation for method '{method_full_name}'."
| ^^
518 | )
|
E501 Line too long (112 > 88)
--> third_party/dawn/generator/webgpu_docs_utility.py:531:89
|
530 | def cleanup_doc_map(doc_map, by_category, params):
531 | """Post-processes the documentation map to fix and validate cross-references for a specific target language.
| ^^^^^^^^^^^^^^^^^^^^^^^^
532 |
533 | Args:
|
E501 Line too long (90 > 88)
--> third_party/dawn/generator/webgpu_docs_utility.py:570:89
|
569 | def recursive_clean(d):
570 | """Recursively traverses the doc map and applies the language-specific cleaner."""
| ^^
571 | if isinstance(d, dict):
572 | for k, v in d.items():
|
UP031 Use format specifiers instead of percent format
--> third_party/dawn/go_presubmit_support.py:61:50
|
59 | cwd=input_api.PresubmitLocalPath())
60 | except input_api.subprocess.CalledProcessError as e:
61 | results.append(output_api.PresubmitError('%s' % (e, )))
| ^^^^^^^^^^^^
62 | return results
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/go_presubmit_support.py:80:21
|
78 | errors.append(
79 | output_api.PresubmitError(
80 | / 'Go code in %s is not formatted, please run "gofmt -w %s"'
81 | | % (path, full_path)))
| |_______________________________________^
82 | except input_api.subprocess.CalledProcessError as e:
83 | errors.append(output_api.PresubmitError('EnforceGoFormatting: %s' % e))
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/go_presubmit_support.py:83:49
|
81 | % (path, full_path)))
82 | except input_api.subprocess.CalledProcessError as e:
83 | errors.append(output_api.PresubmitError('EnforceGoFormatting: %s' % e))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84 | return errors
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/infra/config/scripts/milestones.py:109:28
|
107 | def add_milestone(milestones, milestone_num, branch):
108 | if str(milestone_num) in milestones:
109 | raise RuntimeError('Milestone %d already exists' % milestone_num)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
110 |
111 | milestones[str(milestone_num)] = {
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/infra/config/scripts/milestones.py:127:28
|
125 | def remove_milestone(milestones, milestone_num):
126 | if str(milestone_num) not in milestones:
127 | raise RuntimeError('Milestone %d does not exist' % milestone_num)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
128 | del milestones[str(milestone_num)]
129 | # Not strictly necessary, but returning a value keeps this consistent with
|
help: Replace with format specifiers
F401 [*] `logging` imported but unused
--> third_party/dawn/infra/specs/generate_test_spec_json.py:30:8
|
29 | import argparse
30 | import logging
| ^^^^^^^
31 | import os
32 | import pprint
|
help: Remove unused import: `logging`
UP035 `typing.Dict` is deprecated, use `dict` instead
--> third_party/dawn/infra/specs/generate_test_spec_json.py:35:1
|
33 | import sys
34 | import tempfile
35 | from typing import Dict, List, Optional, Tuple
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36 |
37 | # //testing/buildbot is only retrieved via DEPS for standalone checkouts.
|
UP035 `typing.List` is deprecated, use `list` instead
--> third_party/dawn/infra/specs/generate_test_spec_json.py:35:1
|
33 | import sys
34 | import tempfile
35 | from typing import Dict, List, Optional, Tuple
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36 |
37 | # //testing/buildbot is only retrieved via DEPS for standalone checkouts.
|
UP035 `typing.Tuple` is deprecated, use `tuple` instead
--> third_party/dawn/infra/specs/generate_test_spec_json.py:35:1
|
33 | import sys
34 | import tempfile
35 | from typing import Dict, List, Optional, Tuple
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36 |
37 | # //testing/buildbot is only retrieved via DEPS for standalone checkouts.
|
E402 Module level import not at top of file
--> third_party/dawn/infra/specs/generate_test_spec_json.py:50:1
|
49 | sys.path.insert(0, TESTING_BUILDBOT_DIR)
50 | import generate_buildbot_json
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51 |
52 | # Add custom mixins here.
|
UP006 [*] Use `dict` instead of `Dict` for type annotation
--> third_party/dawn/infra/specs/generate_test_spec_json.py:217:63
|
216 | def _get_trimmed_mixins(
217 | generator: generate_buildbot_json.BBJSONGenerator) -> Dict[str, dict]:
| ^^^^
218 | """Helper function to get a trimmed set of mixins.
|
help: Replace with `dict`
UP006 [*] Use `list` instead of `List` for type annotation
--> third_party/dawn/infra/specs/generate_test_spec_json.py:278:36
|
278 | def _run_generator(generator_args: List[str],
| ^^^^
279 | output_dir: Optional[str] = None) -> None:
280 | """Runs the generate_buildbot_json script for Dawn.
|
help: Replace with `list`
UP045 [*] Use `X | None` for type annotations
--> third_party/dawn/infra/specs/generate_test_spec_json.py:279:32
|
278 | def _run_generator(generator_args: List[str],
279 | output_dir: Optional[str] = None) -> None:
| ^^^^^^^^^^^^^
280 | """Runs the generate_buildbot_json script for Dawn.
|
help: Convert to `X | None`
E711 Comparison to `None` should be `cond is not None`
--> third_party/dawn/infra/specs/generate_test_spec_json.py:290:33
|
288 | files to disk.
289 | """
290 | verify_only = output_dir != None
| ^^^^
291 |
292 | assert '--pyl-files-dir' not in generator_args
|
help: Replace with `cond is not None`
UP006 [*] Use `tuple` instead of `Tuple` for type annotation
--> third_party/dawn/infra/specs/generate_test_spec_json.py:321:22
|
321 | def _parse_args() -> Tuple[argparse.Namespace, List[str]]:
| ^^^^^
322 | """Parses known and unknown args."""
323 | parser = argparse.ArgumentParser(
|
help: Replace with `tuple`
UP006 [*] Use `list` instead of `List` for type annotation
--> third_party/dawn/infra/specs/generate_test_spec_json.py:321:48
|
321 | def _parse_args() -> Tuple[argparse.Namespace, List[str]]:
| ^^^^
322 | """Parses known and unknown args."""
323 | parser = argparse.ArgumentParser(
|
help: Replace with `list`
F401 [*] `platform` imported but unused
--> third_party/dawn/scripts/dawn_node_cts/node_helpers.py:31:8
|
29 | import functools
30 | import os
31 | import platform
| ^^^^^^^^
32 | import sys
|
help: Remove unused import: `platform`
E402 Module level import not at top of file
--> third_party/dawn/scripts/dawn_node_cts/node_helpers.py:39:1
|
37 | sys.path.insert(0, DAWN_ROOT)
38 |
39 | from tools.python import cipd_deps
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
F401 [*] `functools` imported but unused
--> third_party/dawn/scripts/dawn_node_cts/run_dawn_node_cts.py:32:8
|
30 | import argparse
31 | import contextlib
32 | import functools
| ^^^^^^^^^
33 | import glob
34 | import json
|
help: Remove unused import: `functools`
F401 [*] `glob` imported but unused
--> third_party/dawn/scripts/dawn_node_cts/run_dawn_node_cts.py:33:8
|
31 | import contextlib
32 | import functools
33 | import glob
| ^^^^
34 | import json
35 | import logging
|
help: Remove unused import: `glob`
UP004 [*] Class `FileEntry` inherits from `object`
--> third_party/dawn/scripts/extract.py:37:17
|
37 | class FileEntry(object):
| ^^^^^^
38 |
39 | def __init__(self, path, mode, fileobj):
|
help: Remove `object` inheritance
UP004 [*] Class `SymlinkEntry` inherits from `object`
--> third_party/dawn/scripts/extract.py:45:20
|
45 | class SymlinkEntry(object):
| ^^^^^^
46 |
47 | def __init__(self, path, mode, target):
|
help: Remove `object` inheritance
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/extract.py:80:34
|
78 | tar_file.extractfile(info))
79 | else:
80 | raise ValueError('Unknown entry type "%s"' % (info.name, ))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/extract.py:130:19
|
128 | try:
129 | if os.path.exists(output):
130 | print("Removing %s" % (output, ))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
131 | shutil.rmtree(output)
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/extract.py:133:15
|
131 | shutil.rmtree(output)
132 |
133 | print("Extracting %s to %s" % (archive, output))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
134 | prefix = None
135 | num_extracted = 0
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/extract.py:173:23
|
171 | num_extracted += 1
172 | if num_extracted % 100 == 0:
173 | print("Extracted %d files..." % (num_extracted, ))
| ^^^^^^^^^^^^^^^^^^^^^^^
174 | finally:
175 | entries.close()
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/extract.py:180:11
|
178 | f.write(digest)
179 |
180 | print("Done. Extracted %d files." % (num_extracted, ))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
181 | return 0
|
help: Replace with format specifiers
F841 Local variable `p` is assigned to but never used
--> third_party/dawn/scripts/merge_scripts/fuzz_corpora_common.py:74:5
|
72 | f'gs://{BUCKET}/{BUCKET_DIRECTORY}/{fuzzer_name}',
73 | ])
74 | p = subprocess.run(cmd, check=True)
| ^
|
help: Remove assignment to unused variable `p`
E402 Module level import not at top of file
--> third_party/dawn/scripts/merge_scripts/generate_tint_fuzz_corpora.py:45:1
|
43 | sys.path.insert(0, DAWN_ROOT)
44 |
45 | from scripts.merge_scripts import fuzz_corpora_common
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 |
47 | try:
|
E402 Module level import not at top of file
--> third_party/dawn/scripts/merge_scripts/generate_wire_trace_fuzz_corpora.py:44:1
|
42 | sys.path.insert(0, DAWN_ROOT)
43 |
44 | from scripts.merge_scripts import fuzz_corpora_common
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
45 |
46 | try:
|
E501 Line too long (111 > 88)
--> third_party/dawn/scripts/perf_test_runner.py:41:89
|
39 | # Dawn locates at /path/to/Chromium/src/third_party/dawn/
40 | # Chromium build usually locates at /path/to/Chromium/src/out/Release/
41 | # You might want to change the base_path if you want to run dawn_perf_tests build from a Dawn standalone build.
| ^^^^^^^^^^^^^^^^^^^^^^^
42 | base_path = os.path.abspath(
43 | os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../../'))
|
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/scripts/perf_test_runner.py:114:22
|
112 | perftests_path = newest_binary
113 |
114 | if perftests_path == None or not os.path.exists(perftests_path):
| ^^^^
115 | print('Cannot find Release %s!' % binary_name)
116 | sys.exit(1)
|
help: Replace with `cond is None`
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/perf_test_runner.py:115:11
|
114 | if perftests_path == None or not os.path.exists(perftests_path):
115 | print('Cannot find Release %s!' % binary_name)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
116 | sys.exit(1)
|
help: Replace with format specifiers
B006 Do not use mutable data structures for argument defaults
--> third_party/dawn/scripts/perf_test_runner.py:125:36
|
125 | def get_results(metric, extra_args=[]):
| ^^
126 | process = subprocess.Popen(
127 | [perftests_path, '--gtest_filter=' + test_name] + extra_args,
|
help: Replace with `None`; initialize within function
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/perf_test_runner.py:143:15
|
141 | m = re.findall(pattern, output_string)
142 | if not m:
143 | print("Did not find the metric '%s' in the test output:" % metric)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
144 | print(output_string)
145 | sys.exit(1)
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/perf_test_runner.py:152:7
|
150 | # Calibrate the number of steps
151 | steps = get_results("steps", ["--calibration"])[0]
152 | print("running with %d steps." % steps)
| ^^^^^^^^^^^^^^^^^^^^^^^^
153 |
154 | # Loop 'max_experiments' times, running the tests.
|
help: Replace with format specifiers
B007 Loop control variable `experiment` not used within loop body
--> third_party/dawn/scripts/perf_test_runner.py:155:5
|
154 | # Loop 'max_experiments' times, running the tests.
155 | for experiment in range(max_experiments):
| ^^^^^^^^^^
156 | experiment_scores = get_results(metric, ["--override-steps", str(steps)])
|
help: Rename unused `experiment` to `_experiment`
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/perf_test_runner.py:159:26
|
158 | for score in experiment_scores:
159 | sys.stdout.write("%s: %.2f" % (metric, score))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
160 | scores.append(score)
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/perf_test_runner.py:163:30
|
162 | if (len(scores) > 1):
163 | sys.stdout.write(", mean: %.2f" % mean(scores))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
164 | sys.stdout.write(", variation: %.2f%%" %
165 | (coefficient_of_variation(scores) * 100.0))
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/scripts/perf_test_runner.py:169:30
|
167 | if (len(scores) > 7):
168 | truncation_n = len(scores) >> 3
169 | sys.stdout.write(", truncated mean: %.2f" %
| ______________________________^
170 | | truncated_mean(scores, truncation_n))
| |_________________________________________________________________^
171 | sys.stdout.write(", variation: %.2f%%" %
172 | (truncated_cov(scores, truncation_n) * 100.0))
|
help: Replace with format specifiers
UP035 `typing.Type` is deprecated, use `type` instead
--> third_party/dawn/scripts/roll_chromium_deps.py:47:1
|
45 | import subprocess
46 | import sys
47 | from typing import Any, Self, Type
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
48 |
49 | import requests
|
F541 [*] f-string without any placeholders
--> third_party/dawn/scripts/roll_chromium_deps.py:821:9
|
819 | chromium_lines.extend([
820 | f'Roll chromium_revision {chromium_revision_range.revision_range()}',
821 | f'',
| ^^^
822 | f'Change log: {chromium_revision_range.log_link()}',
823 | f'Full diff: {chromium_revision_range.commit_link()}',
|
help: Remove extraneous `f` prefix
UP006 [*] Use `type` instead of `Type` for type annotation
--> third_party/dawn/scripts/roll_chromium_deps.py:848:50
|
848 | def _generate_section_for_entry_type(entry_type: Type[ChangedDepsEntry],
| ^^^^
849 | changed_entries: list[ChangedDepsEntry],
850 | empty_message: str,
|
help: Replace with `type`
E501 Line too long (91 > 88)
--> third_party/dawn/scripts/run_tint_benchmark_test.py:30:89
|
28 | """Runs the Tint benchmark to check that it works.
29 |
30 | This script is necessary in order to support running the Tint benchmark on Swarming, but it
| ^^^
31 | is effectively a thin wrapper around the underlying tint_benchmark binary.
32 | """
|
UP015 [*] Unnecessary mode argument
--> third_party/dawn/src/dawn/node/gen_napi_symbols.py:38:28
|
36 | output_file = Path(sys.argv[2])
37 |
38 | with open(symbols_js_file, "r") as f:
| ^^^
39 | matches = re.findall(r"napi_[a-z0-9_]*", f.read())
|
help: Remove mode argument
UP035 `typing.Dict` is deprecated, use `dict` instead
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:36:1
|
34 | import sys
35 | import zlib
36 | from typing import Dict, Optional
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37 |
38 | # Imports from Emscripten
|
E501 Line too long (166 > 88)
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:45:89
|
43 | …
44 | …
45 | …cripten's license (available under both MIT License and University of Illinois/NCSA Open Source License)"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 | …
47 | …
|
E501 Line too long (92 > 88)
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:50:89
|
48 | OPTIONS = {
49 | 'cpp_bindings':
50 | "Add the include path for Dawn-like <webgpu/webgpu_cpp.h> C++ bindings. Default: true.",
| ^^^^
51 |
52 | # The following options are generally not needed, as they are automatically
|
E501 Line too long (99 > 88)
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:59:89
|
57 | # embuilder build path/to/port/file.py:opt_level=2:shared_memory=true
58 | 'opt_level':
59 | "Optimization (-O) level for the bindings' Wasm layer. Default: choose based on -sASSERTIONS.",
| ^^^^^^^^^^^
60 | 'shared_memory':
61 | "Enable -sSHARED_MEMORY. Default: choose based on whether linker has -sSHARED_MEMORY enabled.",
|
E501 Line too long (99 > 88)
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:61:89
|
59 | "Optimization (-O) level for the bindings' Wasm layer. Default: choose based on -sASSERTIONS.",
60 | 'shared_memory':
61 | "Enable -sSHARED_MEMORY. Default: choose based on whether linker has -sSHARED_MEMORY enabled.",
| ^^^^^^^^^^^
62 | }
63 | _VALID_OPTION_VALUES = {
|
UP006 [*] Use `dict` instead of `Dict` for type annotation
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:68:8
|
66 | 'shared_memory': ['auto', 'true', 'false'],
67 | }
68 | _opts: Dict[str, Optional[str]] = {
| ^^^^
69 | 'cpp_bindings': 'true',
70 | 'opt_level': 'auto',
|
help: Replace with `dict`
UP045 [*] Use `X | None` for type annotations
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:68:18
|
66 | 'shared_memory': ['auto', 'true', 'false'],
67 | }
68 | _opts: Dict[str, Optional[str]] = {
| ^^^^^^^^^^^^^
69 | 'cpp_bindings': 'true',
70 | 'opt_level': 'auto',
|
help: Convert to `X | None`
B007 Loop control variable `dirnames` not used within loop body
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:76:19
|
75 | def _walk(path):
76 | for (dirpath, dirnames, filenames) in os.walk(path):
| ^^^^^^^^
77 | for filename in filenames:
78 | yield os.path.join(dirpath, filename)
|
help: Rename unused `dirnames` to `_dirnames`
E501 Line too long (95 > 88)
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:92:89
|
90 | if not os.path.isfile(os.path.join(_c_include_dir, 'webgpu', 'webgpu.h')):
91 | diagnostics.error(
92 | "emdawnwebgpu.port.py must sit in a built emdawnwebgpu_pkg, not be used standalone or "
| ^^^^^^^
93 | "from Dawn's source tree. Download a pre-built package from "
94 | "https://github.com/google/dawn/releases or build it locally.")
|
SIM115 Use a context manager for opening files
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:178:13
|
177 | for filename in _files_affecting_port_build:
178 | add(open(filename, 'rb').read())
| ^^^^
179 |
180 | (lib_name_suffix, _) = _compute_library_compile_flags(settings)
|
E501 Line too long (101 > 88)
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:190:89
|
188 | if not settings.LINK_AS_CXX:
189 | diagnostics.error(
190 | 'emdawnwebgpu requires C++. Link using em++ (or emcc -sDEFAULT_TO_CXX), instead of emcc.'
| ^^^^^^^^^^^^^
191 | )
|
SIM118 Use `key in dict` instead of `key in dict.keys()`
--> third_party/dawn/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py:202:8
|
200 | ]
201 |
202 | if 'CLOSURE_ARGS' in settings.keys():
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
203 | # This works in Emscripten >4.0.7. In <=4.0.7, the user has to pass it.
204 | settings.CLOSURE_ARGS += [
|
help: Remove `.keys()`
E501 Line too long (98 > 88)
--> third_party/dawn/src/tint/cmd/bench/generate_benchmark_inputs.py:30:89
|
28 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | """
30 | Generates a header file that declares all of the Tint benchmark programs as embedded WGSL shaders,
| ^^^^^^^^^^
31 | and declares macros that will be used to register them all with Google Benchmark.
|
UP015 [*] Unnecessary mode argument
--> third_party/dawn/src/tint/cmd/bench/generate_benchmark_inputs.py:107:34
|
106 | # Rewrite the file without CRLF line endings.
107 | with open(wgsl_path, 'r') as file:
| ^^^
108 | wgsl = file.read()
109 | with open(wgsl_path, 'w', newline='\n') as file:
|
help: Remove mode argument
SIM102 Use a single `if` statement instead of nested `if` statements
--> third_party/dawn/src/tint/cmd/bench/generate_benchmark_inputs.py:113:13
|
112 | # Check if the generated content is different to the current file.
113 | / if args.check_stale:
114 | | if not filecmp.cmp(
115 | | tmp_wgsl_path, final_wgsl_path, shallow=False):
| |_______________________________________________________________________^
116 | print(f'{final_wgsl_path} is stale')
117 | print()
|
help: Combine `if` statements using `and`
E501 Line too long (90 > 88)
--> third_party/dawn/src/tint/cmd/bench/generate_benchmark_inputs.py:178:89
|
176 | for char in input.read():
177 | if char == ord('\r'):
178 | # Skip carriage return to make output consistent across platforms.
| ^^
179 | continue
180 | if (i % 16) == 0:
|
F541 [*] f-string without any placeholders
--> third_party/dawn/src/tint/cmd/bench/generate_benchmark_inputs.py:184:23
|
182 | print(' ' + str(char), file=output, end=',')
183 | i += 1
184 | print(f'}}}},', file=output)
| ^^^^^^^^
185 |
186 | print('};', file=output)
|
help: Remove extraneous `f` prefix
E501 Line too long (97 > 88)
--> third_party/dawn/src/tint/tint_gdb.py:37:89
|
35 | from itertools import chain
36 |
37 | # When debugging this module, set _DEBUGGING = True so that re-sourcing this file in gdb replaces
| ^^^^^^^^^
38 | # the existing printers.
39 | _DEBUGGING = True
|
E501 Line too long (103 > 88)
--> third_party/dawn/src/tint/tint_gdb.py:41:89
|
39 | _DEBUGGING = True
40 |
41 | # Enable to display other data members along with child elements of compound data types (arrays, etc.).
| ^^^^^^^^^^^^^^^
42 | # This is useful in debuggers like VS Code that doesn't display the `to_string()` result in the watch window.
43 | # OTOH, it's less useful when using gdb/lldb's print command.
|
E501 Line too long (109 > 88)
--> third_party/dawn/src/tint/tint_gdb.py:42:89
|
41 | # Enable to display other data members along with child elements of compound data types (arrays, etc.).
42 | # This is useful in debuggers like VS Code that doesn't display the `to_string()` result in the watch window.
| ^^^^^^^^^^^^^^^^^^^^^
43 | # OTOH, it's less useful when using gdb/lldb's print command.
44 | _DISPLAY_MEMBERS_AS_CHILDREN = False
|
E501 Line too long (94 > 88)
--> third_party/dawn/src/tint/tint_gdb.py:47:89
|
46 | # Tips for debugging using VS Code:
47 | # - Set a breakpoint where you can view the types you want to debug/write pretty printers for.
| ^^^^^^
48 | # - Debug Console: source /path/to/dawn/src/tint/tint_gdb.py
49 | # - To execute Python code, in the Debug Console:
|
E501 Line too long (89 > 88)
--> third_party/dawn/src/tint/tint_gdb.py:51:89
|
49 | # - To execute Python code, in the Debug Console:
50 | # -exec python foo = gdb.parse_and_eval('map.set_')
51 | # -exec python v = (foo['slots_']['impl_']['slice']['data'] + 8).dereference()['value']
| ^
52 | #
53 | # - Useful docs:
|
UP004 [*] Class `Printer` inherits from `object`
--> third_party/dawn/src/tint/tint_gdb.py:62:15
|
62 | class Printer(object):
| ^^^^^^
63 | '''Base class for Printers'''
|
help: Remove `object` inheritance
UP008 [*] Use `super()` instead of `super(__class__, self)`
--> third_party/dawn/src/tint/tint_gdb.py:77:14
|
76 | def __init__(self, val):
77 | super(UtilsSlicePrinter, self).__init__(val)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
78 | self.len = self.val['len']
79 | self.cap = self.val['cap']
|
help: Remove `super()` parameters
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/src/tint/tint_gdb.py:91:16
|
90 | def to_string(self):
91 | return 'length={} capacity={}'.format(self.len, self.cap)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
92 |
93 | def members(self):
|
help: Convert to f-string
UP028 Replace `yield` over `for` loop with `yield from`
--> third_party/dawn/src/tint/tint_gdb.py:103:9
|
102 | def children(self):
103 | / for m in self.members():
104 | | yield m
| |___________________^
105 | for i in range(self.len):
106 | yield str(i), self.value_at(i)
|
help: Replace with `yield from`
UP008 [*] Use `super()` instead of `super(__class__, self)`
--> third_party/dawn/src/tint/tint_gdb.py:119:14
|
118 | def __init__(self, val):
119 | super(UtilsVectorPrinter, self).__init__(val)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
120 | self.slice = self.val['impl_']['slice']
121 | self.using_heap = self.slice['cap'] > self.template_type(1)
|
help: Remove `super()` parameters
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/src/tint/tint_gdb.py:127:16
|
126 | def to_string(self):
127 | return 'heap={} {}'.format(self.using_heap, self.slice)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
128 |
129 | def members(self):
|
help: Convert to f-string
UP008 [*] Use `super()` instead of `super(__class__, self)`
--> third_party/dawn/src/tint/tint_gdb.py:151:14
|
150 | def __init__(self, val):
151 | super(UtilsVectorRefPrinter, self).__init__(val)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
152 | self.slice = self.val['slice_']
153 | self.can_move = self.val['can_move_']
|
help: Remove `super()` parameters
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/src/tint/tint_gdb.py:156:16
|
155 | def to_string(self):
156 | return 'can_move={} {}'.format(self.can_move, self.slice)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
157 |
158 | def members(self):
|
help: Convert to f-string
UP008 [*] Use `super()` instead of `super(__class__, self)`
--> third_party/dawn/src/tint/tint_gdb.py:181:14
|
180 | def __init__(self, val):
181 | super(UtilsHashmapBasePrinter, self).__init__(val)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
182 | self.slice = UtilsVectorPrinter(self.val['slots_']).slice_printer()
183 | self.try_read_std_optional_func = self.try_read_std_optional
|
help: Remove `super()` parameters
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/src/tint/tint_gdb.py:191:16
|
189 | if v['hash'] != 0:
190 | length += 1
191 | return 'length={}'.format(length)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
192 |
193 | def children(self):
|
help: Convert to f-string
E722 Do not use bare `except`
--> third_party/dawn/src/tint/tint_gdb.py:223:9
|
221 | v = entry['_M_payload']['_M_payload']['_M_value']
222 | return slot, v
223 | except:
| ^^^^^^
224 | return None
|
E722 Do not use bare `except`
--> third_party/dawn/src/tint/tint_gdb.py:238:9
|
236 | kvp = entry['_M_payload']['_M_payload']['_M_value']
237 | return str(kvp['key']), kvp['value']
238 | except:
| ^^^^^^
239 | return None
|
E501 Line too long (89 > 88)
--> third_party/dawn/src/tint/tint_lldb.py:30:89
|
28 | # Pretty printers for the Tint project.
29 | #
30 | # If using lldb from command line, add a line to your ~/.lldbinit to import the printers:
| ^
31 | #
32 | # command script import /path/to/dawn/src/tint/tint_lldb.py
|
E501 Line too long (94 > 88)
--> third_party/dawn/src/tint/tint_lldb.py:68:89
|
66 | # Tips for debugging using VS Code:
67 | #
68 | # - Set a breakpoint where you can view the types you want to debug/write pretty printers for.
| ^^^^^^
69 | # - Debug Console: -exec command script import /path/to/dawn/src/tint/tint_lldb.py
70 | # - You can re-run the above command to reload the printers after modifying the python script.
|
E501 Line too long (94 > 88)
--> third_party/dawn/src/tint/tint_lldb.py:70:89
|
68 | # - Set a breakpoint where you can view the types you want to debug/write pretty printers for.
69 | # - Debug Console: -exec command script import /path/to/dawn/src/tint/tint_lldb.py
70 | # - You can re-run the above command to reload the printers after modifying the python script.
| ^^^^^^
71 |
72 | # - Useful docs:
|
UP010 [*] Unnecessary `__future__` imports `division`, `print_function` for target Python version
--> third_party/dawn/src/tint/tint_lldb.py:79:1
|
77 | # SBValue: https://lldb.llvm.org/python_api/lldb.SBValue.html
78 |
79 | from __future__ import print_function, division
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
80 | import sys
81 | import logging
|
help: Remove unnecessary `__future__` import
F401 [*] `re` imported but unused
--> third_party/dawn/src/tint/tint_lldb.py:82:8
|
80 | import sys
81 | import logging
82 | import re
| ^^
83 | import lldb
84 | import types
|
help: Remove unused import: `re`
F401 [*] `types` imported but unused
--> third_party/dawn/src/tint/tint_lldb.py:84:8
|
82 | import re
83 | import lldb
84 | import types
| ^^^^^
85 |
86 | if sys.version_info[0] == 2:
|
help: Remove unused import: `types`
UP036 Version block is outdated for minimum Python version
--> third_party/dawn/src/tint/tint_lldb.py:86:4
|
84 | import types
85 |
86 | if sys.version_info[0] == 2:
| ^^^^^^^^^^^^^^^^^^^^^^^^
87 | # python2-based LLDB accepts utf8-encoded ascii strings only.
88 | def to_lldb_str(s):
|
help: Remove outdated version block
F821 Undefined name `unicode`
--> third_party/dawn/src/tint/tint_lldb.py:90:16
|
88 | def to_lldb_str(s):
89 | return s.encode('utf8', 'backslashreplace') if isinstance(
90 | s, unicode) else s
| ^^^^^^^
91 |
92 | range = xrange
|
F821 Undefined name `xrange`
--> third_party/dawn/src/tint/tint_lldb.py:92:13
|
90 | s, unicode) else s
91 |
92 | range = xrange
| ^^^^^^
93 | else:
94 | to_lldb_str = str
|
E501 Line too long (116 > 88)
--> third_party/dawn/src/tint/tint_lldb.py:155:89
|
153 | ''''
154 | get_summary' is annoyingly not a part of the standard LLDB synth provider API.
155 | This trick allows us to share data extraction logic between synth providers and their sibling summary providers.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
156 | '''
157 | synth = synth_class(valobj.GetNonSyntheticValue(), dict)
|
UP004 [*] Class `Printer` inherits from `object`
--> third_party/dawn/src/tint/tint_lldb.py:170:15
|
170 | class Printer(object):
| ^^^^^^
171 | '''Base class for Printers'''
|
help: Remove `object` inheritance
B006 Do not use mutable data structures for argument defaults
--> third_party/dawn/src/tint/tint_lldb.py:173:37
|
171 | '''Base class for Printers'''
172 |
173 | def __init__(self, valobj, dict={}):
| ^^
174 | self.valobj = valobj
175 | self.initialize()
|
help: Replace with `None`; initialize within function
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/src/tint/tint_lldb.py:238:16
|
237 | def get_summary(self):
238 | return 'length={} capacity={}'.format(self.len.GetValueAsUnsigned(),
| ________________^
239 | | self.cap.GetValueAsUnsigned())
| |____________________________________________________________________________^
240 |
241 | def num_children(self):
|
help: Convert to f-string
E501 Line too long (106 > 88)
--> third_party/dawn/src/tint/tint_lldb.py:242:89
|
241 | def num_children(self):
242 | # NOTE: VS Code on MacOS hangs if we try to expand something too large, so put an artificial limit
| ^^^^^^^^^^^^^^^^^^
243 | # until we can figure out how to know if this is a valid instance.
244 | return min(self.len.GetValueAsUnsigned(), 256)
|
UP031 Use format specifiers instead of percent format
--> third_party/dawn/src/tint/tint_lldb.py:255:50
|
253 | # TODO: return self.value_at(index)
254 | offset = index * self.elem_size
255 | return self.data.CreateChildAtOffset('[%s]' % index, offset,
| ^^^^^^^^^^^^^^
256 | self.elem_type)
257 | except Exception as e:
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/src/tint/tint_lldb.py:264:46
|
262 | '''Returns array value at index'''
263 | offset = index * self.elem_size
264 | return self.data.CreateChildAtOffset('[%s]' % index, offset,
| ^^^^^^^^^^^^^^
265 | self.elem_type)
|
help: Replace with format specifiers
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/src/tint/tint_lldb.py:279:16
|
277 | def get_summary(self):
278 | using_heap = self.cap.GetValueAsUnsigned() > self.fixed_size
279 | return 'heap={} {}'.format(using_heap,
| ________________^
280 | | self.slice_printer.get_summary())
| |____________________________________________________________________^
281 |
282 | def num_children(self):
|
help: Convert to f-string
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/src/tint/tint_lldb.py:304:16
|
303 | def get_summary(self):
304 | return 'can_move={} {}'.format(self.can_move.GetValue(),
| ________________^
305 | | self.slice_printer.get_summary())
| |________________________________________________________________________^
306 |
307 | def num_children(self):
|
help: Convert to f-string
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/src/tint/tint_lldb.py:335:16
|
334 | def get_summary(self):
335 | return 'length={}'.format(self.num_children())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
336 |
337 | def num_children(self):
|
help: Convert to f-string
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/src/tint/tint_lldb.py:355:43
|
353 | kvp = slot, entry
354 |
355 | return kvp[1].CreateChildAtOffset('[{}]'.format(kvp[0]), 0,
| ^^^^^^^^^^^^^^^^^^^^^
356 | kvp[1].GetType())
|
help: Convert to f-string
E722 Do not use bare `except`
--> third_party/dawn/src/tint/tint_lldb.py:377:9
|
375 | return slot, v
376 | return None
377 | except:
| ^^^^^^
378 | return None
|
E722 Do not use bare `except`
--> third_party/dawn/src/tint/tint_lldb.py:400:9
|
398 | return k.GetValue(), v
399 | return None
400 | except:
| ^^^^^^
401 | return None
|
W605 [*] Invalid escape sequence: `\[`
--> third_party/dawn/test/tint/extract-spvasm.py:47:31
|
45 | parts = []
46 | for line in sys.stdin:
47 | run_match = re.match('\[ RUN\s+\]\s+(\S+)', line)
| ^^
48 | if run_match:
49 | test_name = run_match.group(1)
|
help: Use a raw string literal
W605 [*] Invalid escape sequence: `\s`
--> third_party/dawn/test/tint/extract-spvasm.py:47:37
|
45 | parts = []
46 | for line in sys.stdin:
47 | run_match = re.match('\[ RUN\s+\]\s+(\S+)', line)
| ^^
48 | if run_match:
49 | test_name = run_match.group(1)
|
help: Use a raw string literal
W605 [*] Invalid escape sequence: `\]`
--> third_party/dawn/test/tint/extract-spvasm.py:47:40
|
45 | parts = []
46 | for line in sys.stdin:
47 | run_match = re.match('\[ RUN\s+\]\s+(\S+)', line)
| ^^
48 | if run_match:
49 | test_name = run_match.group(1)
|
help: Use a raw string literal
W605 [*] Invalid escape sequence: `\s`
--> third_party/dawn/test/tint/extract-spvasm.py:47:42
|
45 | parts = []
46 | for line in sys.stdin:
47 | run_match = re.match('\[ RUN\s+\]\s+(\S+)', line)
| ^^
48 | if run_match:
49 | test_name = run_match.group(1)
|
help: Use a raw string literal
W605 [*] Invalid escape sequence: `\S`
--> third_party/dawn/test/tint/extract-spvasm.py:47:46
|
45 | parts = []
46 | for line in sys.stdin:
47 | run_match = re.match('\[ RUN\s+\]\s+(\S+)', line)
| ^^
48 | if run_match:
49 | test_name = run_match.group(1)
|
help: Use a raw string literal
E741 Ambiguous variable name: `l`
--> third_party/dawn/test/tint/extract-spvasm.py:57:21
|
55 | with open(test_name, 'w') as f:
56 | f.write('; Test: ' + test_name + '\n')
57 | for l in parts:
| ^
58 | f.write(l)
59 | f.close()
|
E713 [*] Test for membership should be `not in`
--> third_party/dawn/test/tint/parse_hlsl_errors.py:50:12
|
48 | def add_error(error_to_files, error, file):
49 | error = error.strip()
50 | if not error in error_to_files:
| ^^^^^^^^^^^^^^^^^^^^^^^
51 | error_to_files[error] = [file]
52 | else:
|
help: Convert to `not in`
W605 [*] Invalid escape sequence: `\.`
--> third_party/dawn/test/tint/parse_hlsl_errors.py:82:30
|
80 | return True
81 |
82 | m = re.search('.*\.hlsl:[0-9]+:.*?(error.*)', line) # DXC???
| ^^
83 | if m:
84 | add_error(error_to_files, m.groups()[0], f)
|
help: Use a raw string literal
UP015 [*] Unnecessary mode argument
--> third_party/dawn/test/tint/parse_hlsl_errors.py:104:22
|
102 | for f in files:
103 | found_error = False
104 | with open(f, "r") as fs:
| ^^^
105 | all_lines = fs.readlines()
106 | first_line = all_lines[0]
|
help: Remove mode argument
E501 Line too long (104 > 88)
--> third_party/dawn/test/tint/parse_hlsl_errors.py:114:89
|
113 | if not found_error:
114 | # If no error message was found, add the SKIP line as it may contain the reason for skipping
| ^^^^^^^^^^^^^^^^
115 | add_error(error_to_files, first_line, f)
|
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/test/tint/parse_hlsl_errors.py:122:23
|
120 | if args.list_files:
121 | for f in files:
122 | print('\t{}'.format(f))
| ^^^^^^^^^^^^^^^^
|
help: Convert to f-string
SIM115 Use a context manager for opening files
--> third_party/dawn/third_party/gn/dxc/build/cmake_configure_file.py:74:11
|
72 | return r
73 |
74 | fin = open(input_file, 'r')
| ^^^^
75 |
76 | output_lines = []
|
UP015 [*] Unnecessary mode argument
--> third_party/dawn/third_party/gn/dxc/build/cmake_configure_file.py:74:28
|
72 | return r
73 |
74 | fin = open(input_file, 'r')
| ^^^
75 |
76 | output_lines = []
|
help: Remove mode argument
UP015 [*] Unnecessary mode argument
--> third_party/dawn/third_party/gn/dxc/build/cmake_configure_file.py:133:32
|
131 | # Avoid needless incremental rebuilds if the output file exists and hasn't changed
132 | if os.path.exists(output_file):
133 | with open(output_file, 'r') as fout:
| ^^^
134 | if fout.read() == output_text:
135 | return 0
|
help: Remove mode argument
SIM115 Use a context manager for opening files
--> third_party/dawn/third_party/gn/dxc/build/cmake_configure_file.py:137:12
|
135 | return 0
136 |
137 | fout = open(output_file, 'w')
| ^^^^
138 | fout.write(output_text)
139 | return 0
|
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:53:34
|
51 | for i, arg in enumerate(rest):
52 | if arg == '-h' and len(rest) > i + 1:
53 | assert header_dir == None
| ^^^^
54 | header_dir = rest[i + 1]
55 | elif arg == '-r' and len(rest) > i + 1:
|
help: Replace with `cond is None`
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:56:36
|
54 | header_dir = rest[i + 1]
55 | elif arg == '-r' and len(rest) > i + 1:
56 | assert resource_dir == None
| ^^^^
57 | resource_dir = rest[i + 1]
58 | elif arg.endswith('.mc') or arg.endswith('.man'):
|
help: Replace with `cond is None`
E711 Comparison to `None` should be `cond is None`
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:59:34
|
57 | resource_dir = rest[i + 1]
58 | elif arg.endswith('.mc') or arg.endswith('.man'):
59 | assert input_file == None
| ^^^^
60 | input_file = arg
|
help: Replace with `cond is None`
E501 Line too long (90 > 88)
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:68:89
|
66 | source = os.path.join(THIS_DIR, "..", "win_build_output",
67 | re.sub(r'.*gn/dxc/', 'mc/', header_dir))
68 | # If these are new files, create the source directory. The diff will fail later to let
| ^^
69 | # the user know what files to copy.
70 | os.makedirs(source, exist_ok=True)
|
SIM115 Use a context manager for opening files
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:87:17
|
85 | # by CreateProcess. Drop last 2 NULs, one for list terminator, one for
86 | # trailing vs. separator.
87 | env_pairs = open(env_file).read()[:-2].split('\0')
| ^^^^
88 | env_dict = dict([item.split('=', 1) for item in env_pairs])
|
F841 Local variable `extension` is assigned to but never used
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:90:5
|
88 | env_dict = dict([item.split('=', 1) for item in env_pairs])
89 |
90 | extension = os.path.splitext(input_file)[1]
| ^^^^^^^^^
91 |
92 | # mc writes to stderr, so this explicitly redirects to stdout and eats it.
|
help: Remove assignment to unused variable `extension`
UP015 [*] Unnecessary mode argument
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:124:36
|
122 | os.path.splitext(os.path.basename(input_file))[0] + '.h')
123 | header_contents = []
124 | with open(header_file, 'r') as f:
| ^^^
125 | define_block = [] # The current contiguous block of #defines.
126 | for line in f.readlines():
|
help: Remove mode argument
UP031 Use format specifiers instead of percent format
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:148:19
|
146 | diff = filecmp.dircmp(tmp_dir, source)
147 | if diff.diff_files or set(diff.left_list) != set(diff.right_list):
148 | print('mc.exe output different from files in %s, see %s' %
| ___________________^
149 | | (source, tmp_dir))
| |___________________________________^
150 | diff.report()
151 | for f in diff.diff_files:
|
help: Replace with format specifiers
E701 Multiple statements on one line (colon)
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:152:38
|
150 | diff.report()
151 | for f in diff.diff_files:
152 | if f.endswith('.bin'): continue
| ^
153 | fromfile = os.path.join(source, f)
154 | tofile = os.path.join(tmp_dir, f)
|
SIM115 Use a context manager for opening files
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:157:25
|
155 | print(''.join(
156 | difflib.unified_diff(
157 | open(fromfile).readlines(),
| ^^^^
158 | open(tofile).readlines(), fromfile, tofile)))
159 | delete_tmp_dir = False
|
SIM115 Use a context manager for opening files
--> third_party/dawn/third_party/gn/dxc/build/message_compiler.py:158:25
|
156 | difflib.unified_diff(
157 | open(fromfile).readlines(),
158 | open(tofile).readlines(), fromfile, tofile)))
| ^^^^
159 | delete_tmp_dir = False
160 | sys.exit(1)
|
E501 Line too long (99 > 88)
--> third_party/dawn/third_party/gn/emsdk/can-use-closure.py:40:89
|
38 | os.chdir(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
39 |
40 | compiler_path = './third_party/emsdk/upstream/emscripten/node_modules/.bin/google-closure-compiler'
| ^^^^^^^^^^^
41 | try:
42 | subprocess.check_call([compiler_path, '--version'],
|
F401 [*] `os` imported but unused
--> third_party/dawn/tools/fetch_dawn_dependencies.py:39:8
|
37 | """
38 |
39 | import os
| ^^
40 | import sys
41 | import subprocess
|
help: Remove unused import: `os`
F401 [*] `sys` imported but unused
--> third_party/dawn/tools/fetch_dawn_dependencies.py:40:8
|
39 | import os
40 | import sys
| ^^^
41 | import subprocess
42 | import argparse
|
help: Remove unused import: `sys`
SIM115 Use a context manager for opening files
--> third_party/dawn/tools/fetch_dawn_dependencies.py:137:12
|
136 | log(f"Listing dependencies from {dir_path}")
137 | DEPS = open(deps_path).read()
| ^^^^
138 |
139 | ldict = {}
|
E731 Do not assign a `lambda` expression, use a `def`
--> third_party/dawn/tools/fetch_dawn_dependencies.py:158:9
|
157 | # Run git from within the submodule's path (don't use for clone)
158 | / git = lambda *x: subprocess.run([args.git, '-C', submodule_path, *x],
159 | | capture_output=True)
| |____________________________________________________________^
160 |
161 | log(f"Fetching dependency '{submodule}'")
|
help: Rewrite `git` as a `def`
B023 Function definition does not bind loop variable `submodule_path`
--> third_party/dawn/tools/fetch_dawn_dependencies.py:158:58
|
157 | # Run git from within the submodule's path (don't use for clone)
158 | git = lambda *x: subprocess.run([args.git, '-C', submodule_path, *x],
| ^^^^^^^^^^^^^^
159 | capture_output=True)
|
E501 Line too long (89 > 88)
--> third_party/dawn/tools/fetch_dawn_dependencies.py:184:89
|
182 | else:
183 | if args.shallow:
184 | log(f"Shallow cloning '{git_url}' at '{git_tag}' into '{submodule_path}'"
| ^
185 | )
186 | shallow_clone(git, git_url, git_tag)
|
E402 Module level import not at top of file
--> third_party/dawn/tools/run.py:40:1
|
38 | sys.path.insert(0, DAWN_ROOT)
39 |
40 | from tools.python import cipd_deps
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
UP031 Use format specifiers instead of percent format
--> third_party/dawn/webgpu-cts/PRESUBMIT.py:63:50
|
61 | cwd=input_api.change.RepositoryRoot())
62 | except input_api.subprocess.CalledProcessError as e:
63 | results.append(output_api.PresubmitError('%s' % (e, )))
| ^^^^^^^^^^^^
64 | return results
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/webgpu-cts/scripts/add_query_to_expectation_file.py:63:12
|
62 | def generate_expectations(queries, tags, results, bug):
63 | tags = '[ %s ] ' % ' '.join(tags) if tags else ''
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
64 | results = ' [ %s ]' % ' '.join(results)
65 | bug = bug + ' ' if bug else ''
|
help: Replace with format specifiers
UP031 Use format specifiers instead of percent format
--> third_party/dawn/webgpu-cts/scripts/add_query_to_expectation_file.py:64:15
|
62 | def generate_expectations(queries, tags, results, bug):
63 | tags = '[ %s ] ' % ' '.join(tags) if tags else ''
64 | results = ' [ %s ]' % ' '.join(results)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
65 | bug = bug + ' ' if bug else ''
66 | content = ''
|
help: Replace with format specifiers
UP032 [*] Use f-string instead of `format` call
--> third_party/dawn/webgpu-cts/scripts/add_query_to_expectation_file.py:72:24
|
70 | logging.warning('Did not get any test names for query %s', q)
71 | for tn in test_names:
72 | content += '{bug}{tags}{test}{results}\n'.format(bug=bug,
| ________________________^
73 | | tags=tags,
74 | | test=tn,
75 | | results=results)
| |_____________________________________________________________________________^
76 | with open(EXPECTATION_FILE_PATH, 'a') as outfile:
77 | outfile.write(content)
|
help: Convert to f-string
UP015 [*] Unnecessary mode argument
--> third_party/dawn/webgpu-cts/scripts/copy_files.py:49:31
|
47 | args = parser.parse_args()
48 |
49 | with open(args.file_list, 'r') as f:
| ^^^
50 | for file in f.read().splitlines():
51 | src = os.path.join(args.src_dir, file)
|
help: Remove mode argument
SIM105 Use `contextlib.suppress(shutil.SameFileError)` instead of `try`-`except`-`pass`
--> third_party/dawn/webgpu-cts/scripts/copy_files.py:53:13
|
51 | src = os.path.join(args.src_dir, file)
52 | dst = os.path.join(args.dst_dir, file)
53 | / try:
54 | | shutil.copy(src, dst)
55 | | except shutil.SameFileError:
56 | | pass
| |____________________^
57 |
58 | if args.stamp:
|
help: Replace `try`-`except`-`pass` with `with contextlib.suppress(shutil.SameFileError): ...`
F401 [*] `sys` imported but unused
--> third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py:33:8
|
31 | import glob
32 | import os
33 | import sys
| ^^^
34 |
35 | from dir_paths import gn_webgpu_cts_dir, webgpu_cts_root_dir
|
help: Remove unused import: `sys`
E501 Line too long (91 > 88)
--> third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py:45:89
|
43 | # "/absolute/path/to/file.ts"
44 | # The path is always Unix-style.
45 | # It will also output many Typescript errors since the build doesn't download the .d.ts
| ^^^
46 | # dependencies.
47 | stdout = run_tsc_ignore_errors([
|
E741 Ambiguous variable name: `l`
--> third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py:53:29
|
51 | ])
52 |
53 | lines = [l.decode() for l in stdout.splitlines()]
| ^
54 | return [
55 | line[len(src_prefix):] for line in lines
|
UP015 [*] Unnecessary mode argument
--> third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py:86:35
|
85 | if args.check:
86 | with open(ts_sources_txt, 'r') as f:
| ^^^
87 | txt = f.readlines()
88 | if (txt != ts_sources):
|
help: Remove mode argument
UP031 Use format specifiers instead of percent format
--> third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py:90:21
|
88 | if (txt != ts_sources):
89 | raise RuntimeError(
90 | / '%s is out of date. Please re-run //third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py\n'
91 | | % ts_sources_txt)
| |____________________________________^
92 | with open(resource_files_txt, 'r') as f:
93 | if (f.readlines() != resource_files):
|
help: Replace with format specifiers
E501 Line too long (114 > 88)
--> third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py:90:89
|
88 | if (txt != ts_sources):
89 | raise RuntimeError(
90 | '%s is out of date. Please re-run //third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py\n'
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
91 | % ts_sources_txt)
92 | with open(resource_files_txt, 'r') as f:
|
UP015 [*] Unnecessary mode argument
--> third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py:92:39
|
90 | '%s is out of date. Please re-run //third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py\n'
91 | % ts_sources_txt)
92 | with open(resource_files_txt, 'r') as f:
| ^^^
93 | if (f.readlines() != resource_files):
94 | raise RuntimeError(
|
help: Remove mode argument
UP031 Use format specifiers instead of percent format
--> third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py:95:21
|
93 | if (f.readlines() != resource_files):
94 | raise RuntimeError(
95 | / '%s is out of date. Please re-run //third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py\n'
96 | | % resource_files_txt)
| |________________________________________^
97 | else:
98 | with open(ts_sources_txt, 'w') as f:
|
help: Replace with format specifiers
E501 Line too long (114 > 88)
--> third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py:95:89
|
93 | if (f.readlines() != resource_files):
94 | raise RuntimeError(
95 | '%s is out of date. Please re-run //third_party/dawn/webgpu-cts/scripts/gen_ts_dep_lists.py\n'
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
96 | % resource_files_txt)
97 | else:
|
E501 Line too long (95 > 88)
--> third_party/dawn/webgpu-cts/scripts/tsc_ignore_errors.py:56:89
|
54 | stdout, stderr = process.communicate()
55 |
56 | # Typecheck errors go in stdout, not stderr. If we see something in stderr, raise an error.
| ^^^^^^^
57 | if len(stderr):
58 | raise RuntimeError('tsc \'%s\' failed\n%s' % (' '.join(cmd), stderr))
|
UP031 Use format specifiers instead of percent format
--> third_party/dawn/webgpu-cts/scripts/tsc_ignore_errors.py:58:28
|
56 | # Typecheck errors go in stdout, not stderr. If we see something in stderr, raise an error.
57 | if len(stderr):
58 | raise RuntimeError('tsc \'%s\' failed\n%s' % (' '.join(cmd), stderr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
59 |
60 | return stdout
|
help: Replace with format specifiers
Found 344 errors.
[*] 95 fixable with the `--fix` option (74 hidden fixes can be enabled with the `--unsafe-fixes` option).
root@648a77abe1dc:/usr/src/app# |
There was a problem hiding this comment.
Thank you for the PR @Geff115!
These are just some simple changes that I'd like you to implement:
- Reverting the changes to the
img2numBash script (you can usegit checkout main -- img2numif you'd like). - Add a quick comment to the root
pyproject.tomlfor my future sanity.😁
There's also a linting problem related to a .editorconfig violation, but it's minor and I can just fix it before merging.
Other than that, this is wonderful and you actually do not need to add anything further. Thanks again!
@Ryan-Millard using |
That's a great catch! Shouldn't we rather add that piece to the ignore = [ "third_party" ]If you agree, please leave a review and ask for that change to be added. |
|
For the monorepo management system, please see discussion #376 |
… on the suggested changes from Ryan and Krasner
|
I have resolved the img2num script and the pyproject.toml file based on the suggested changes aforementioned. Let me know if you'd like me to pick up anything else. |
Hi @Geff115. Sorry for the late reply - I've had a lot of work recently and only had time to spare now. This is great stuff - thank you! I'll just wait for the workflows to complete and merge it. |
Summary
Sets up Ruff as the Python linter for the Python bindings and example apps,
as requested in issue #332.
Changes
pyproject.toml[tool.ruff]and[tool.ruff.lint]configuration targeting Python 3.10+with rule sets covering pycodestyle (E/W), Pyflakes (F), flake8-bugbear (B),
pyupgrade (UP), and flake8-simplify (SIM).
ruff>=0.4.0under[project.optional-dependencies]dev extras souv sync --extra dev --no-build-isolationinstalls it inside the container.img2num(shell wrapper)lint-pycommand that runsuv run --extra dev ruff check packages/py example-appsinside the Docker dev container.
./img2num lint-pyTesting
Ran
./img2num lint-pyinside the dev container — Ruff resolves, scans allPython files, and reports correctly with no tooling warnings.
Note: 7 pre-existing violations were found in
packages/pyandexample-apps/console-py.These are not introduced by this PR and are left for a follow-up.
Related
Closes #332