@neralabs/rerail-pack-python 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/README.md +707 -3
  2. package/licenses/bandit/UPSTREAM.md +10 -0
  3. package/licenses/ruff/UPSTREAM.md +56 -0
  4. package/pack.json +7 -20
  5. package/package.json +1 -1
  6. package/rules/bandit-b101-assert-used.json +2 -2
  7. package/rules/bandit-b102-exec-used.json +2 -2
  8. package/rules/bandit-b110-try-except-pass.json +1 -1
  9. package/rules/bandit-b112-try-except-continue.json +1 -1
  10. package/rules/bandit-b113-request-without-timeout.json +2 -2
  11. package/rules/bandit-b301-pickle.json +2 -2
  12. package/rules/bandit-b302-marshal.json +2 -2
  13. package/rules/bandit-b303-md5.json +1 -1
  14. package/rules/bandit-b305-cipher-modes.json +2 -2
  15. package/rules/bandit-b306-mktemp-q.json +2 -2
  16. package/rules/bandit-b307-eval.json +1 -1
  17. package/rules/bandit-b308-mark-safe.json +2 -2
  18. package/rules/bandit-b310-urllib-urlopen.json +1 -1
  19. package/rules/bandit-b311-random.json +1 -1
  20. package/rules/bandit-b312-telnetlib.json +1 -1
  21. package/rules/bandit-b313-xml-bad-celementtree.json +1 -1
  22. package/rules/bandit-b314-xml-bad-elementtree.json +1 -1
  23. package/rules/bandit-b315-xml-bad-expatreader.json +1 -1
  24. package/rules/bandit-b316-xml-bad-expatbuilder.json +1 -1
  25. package/rules/bandit-b317-xml-bad-sax.json +1 -1
  26. package/rules/bandit-b318-xml-bad-minidom.json +1 -1
  27. package/rules/bandit-b319-xml-bad-pulldom.json +1 -1
  28. package/rules/bandit-b321-ftplib.json +2 -2
  29. package/rules/bandit-b323-unverified-context.json +2 -2
  30. package/rules/bandit-b401-import-telnetlib.json +2 -2
  31. package/rules/bandit-b402-import-ftplib.json +2 -2
  32. package/rules/bandit-b405-import-xml-etree.json +1 -1
  33. package/rules/bandit-b407-import-xml-expat.json +1 -1
  34. package/rules/bandit-b408-import-xml-minidom.json +1 -1
  35. package/rules/bandit-b409-import-xml-pulldom.json +1 -1
  36. package/rules/bandit-b411-import-xmlrpclib.json +1 -1
  37. package/rules/bandit-b413-import-pycrypto.json +1 -1
  38. package/rules/bandit-b415-import-pyghmi.json +2 -2
  39. package/rules/bandit-b502-ssl-with-bad-version.json +2 -2
  40. package/rules/bandit-b505-weak-cryptographic-key.json +2 -2
  41. package/rules/bandit-b507-ssh-no-host-key-verification.json +2 -2
  42. package/rules/bandit-b606-start-process-with-no-shell.json +2 -2
  43. package/rules/bandit-b615-huggingface-unsafe-download.json +2 -2
  44. package/rules/ruff-async100-cancel-scope-no-checkpoint.json +2 -2
  45. package/rules/ruff-async105-trio-sync-call.json +1 -1
  46. package/rules/ruff-async115-async-zero-sleep.json +1 -1
  47. package/rules/ruff-async116-long-sleep-not-forever.json +1 -1
  48. package/rules/ruff-async210-blocking-http-call-in-async-function.json +2 -2
  49. package/rules/ruff-async221-run-process-in-async-function.json +1 -1
  50. package/rules/ruff-async222-wait-for-process-in-async-function.json +2 -2
  51. package/rules/ruff-async230-blocking-open-call-in-async-function.json +2 -2
  52. package/rules/ruff-async250-blocking-input-in-async-function.json +2 -2
  53. package/rules/ruff-async251-blocking-sleep-in-async-function.json +1 -1
  54. package/rules/ruff-b002-unary-prefix-increment-decrement.json +3 -3
  55. package/rules/ruff-b003-assignment-to-os-environ.json +2 -2
  56. package/rules/ruff-b004-unreliable-callable-check.json +1 -1
  57. package/rules/ruff-b005-strip-with-multi-characters.json +2 -2
  58. package/rules/ruff-b007-unused-loop-control-variable.json +1 -1
  59. package/rules/ruff-b009-get-attr-with-constant.json +1 -1
  60. package/rules/ruff-b010-set-attr-with-constant.json +2 -2
  61. package/rules/ruff-b011-assert-false.json +1 -1
  62. package/rules/ruff-b013-redundant-tuple-in-exception-handler.json +1 -1
  63. package/rules/ruff-b014-duplicate-handler-exception.json +1 -1
  64. package/rules/ruff-b016-raise-literal.json +1 -1
  65. package/rules/ruff-b020-loop-variable-overrides-iterator.json +1 -1
  66. package/rules/ruff-b021-f-string-docstring.json +1 -1
  67. package/rules/ruff-b022-useless-contextlib-suppress.json +1 -1
  68. package/rules/ruff-b023-function-uses-loop-variable.json +2 -2
  69. package/rules/ruff-b025-duplicate-try-block-exception.json +1 -1
  70. package/rules/ruff-b026-star-arg-unpacking-after-keyword-arg.json +1 -1
  71. package/rules/ruff-b028-no-explicit-stacklevel.json +2 -2
  72. package/rules/ruff-b029-except-with-empty-tuple.json +1 -1
  73. package/rules/ruff-b030-except-with-non-exception-classes.json +406 -0
  74. package/rules/ruff-b032-unintentional-type-annotation.json +1 -1
  75. package/rules/ruff-b033-duplicate-value.json +1 -1
  76. package/rules/ruff-b034-re-sub-positional-args.json +1 -1
  77. package/rules/ruff-b039-mutable-contextvar-default.json +2 -2
  78. package/rules/ruff-b904-raise-without-from-inside-except.json +2 -2
  79. package/rules/ruff-b905-zip-without-explicit-strict.json +1 -1
  80. package/rules/ruff-e711-none-comparison.json +1 -1
  81. package/rules/ruff-e721-type-comparison.json +1 -1
  82. package/rules/ruff-e722-bare-except.json +2 -2
  83. package/rules/ruff-e742-ambiguous-class-name.json +2 -2
  84. package/rules/ruff-e743-ambiguous-function-name.json +2 -2
  85. package/rules/ruff-f403-undefined-local-with-import-star.json +1 -1
  86. package/rules/ruff-f405-undefined-local-with-import-star-usage.json +2 -2
  87. package/rules/ruff-f406-undefined-local-with-nested-import-star-usage.json +2 -2
  88. package/rules/ruff-f407-future-feature-not-defined.json +1 -1
  89. package/rules/ruff-f501-percent-format-invalid-format.json +2 -2
  90. package/rules/ruff-f502-percent-format-expected-mapping.json +1 -1
  91. package/rules/ruff-f503-percent-format-expected-sequence.json +1 -1
  92. package/rules/ruff-f504-percent-format-extra-named-arguments.json +1 -1
  93. package/rules/ruff-f505-percent-format-missing-argument.json +1 -1
  94. package/rules/ruff-f506-percent-format-mixed-positional-and-named.json +2 -2
  95. package/rules/ruff-f507-percent-format-positional-count-mismatch.json +2 -2
  96. package/rules/ruff-f508-percent-format-star-requires-sequence.json +2 -2
  97. package/rules/ruff-f509-percent-format-unsupported-format-character.json +2 -2
  98. package/rules/ruff-f521-string-dot-format-invalid-format.json +1 -1
  99. package/rules/ruff-f522-string-dot-format-extra-named-arguments.json +2 -2
  100. package/rules/ruff-f523-string-dot-format-extra-positional-arguments.json +1 -1
  101. package/rules/ruff-f524-string-dot-format-missing-arguments.json +1 -1
  102. package/rules/ruff-f525-string-dot-format-mixing-automatic.json +1 -1
  103. package/rules/ruff-f541-f-string-missing-placeholders.json +2 -2
  104. package/rules/ruff-f601-multi-value-repeated-key-literal.json +1 -1
  105. package/rules/ruff-f602-multi-value-repeated-key-variable.json +2 -2
  106. package/rules/ruff-f622-multiple-starred-expressions.json +1 -1
  107. package/rules/ruff-f632-is-literal.json +1 -1
  108. package/rules/ruff-f633-invalid-print-syntax.json +2 -2
  109. package/rules/ruff-f701-break-outside-loop.json +1 -1
  110. package/rules/ruff-f702-continue-outside-loop.json +1 -1
  111. package/rules/ruff-f706-return-outside-function.json +1 -1
  112. package/rules/ruff-f707-default-except-not-last.json +1 -1
  113. package/rules/ruff-f822-undefined-export.json +1 -1
  114. package/rules/ruff-f823-undefined-local.json +2 -2
  115. package/rules/ruff-f842-unused-annotation.json +1 -1
  116. package/rules/ruff-f901-raise-not-implemented.json +1 -1
  117. package/rules/ruff-pie794-duplicate-class-field-definition.json +1 -1
  118. package/rules/ruff-pie796-non-unique-enums.json +1 -1
  119. package/rules/ruff-pie800-unnecessary-spread.json +1 -1
  120. package/rules/ruff-pie804-unnecessary-dict-kwargs.json +1 -1
  121. package/rules/ruff-pie807-reimplemented-container-builtin.json +1 -1
  122. package/rules/ruff-pie810-multiple-starts-ends-with.json +2 -2
  123. package/rules/ruff-ret501-unnecessary-return-none.json +1 -1
  124. package/rules/ruff-ret502-implicit-return-value.json +2 -2
  125. package/rules/ruff-ret505-superfluous-else-return.json +1 -1
  126. package/rules/ruff-ret506-superfluous-else-raise.json +1 -1
  127. package/rules/ruff-ret507-superfluous-else-continue.json +1 -1
  128. package/rules/ruff-ret508-superfluous-else-break.json +1 -1
  129. package/rules/ruff-sim101-duplicate-isinstance-call.json +1 -1
  130. package/rules/ruff-sim107-return-in-try-except-finally.json +2 -2
  131. package/rules/ruff-sim109-compare-with-tuple.json +1 -1
  132. package/rules/ruff-sim112-uncapitalized-environment-variables.json +2 -2
  133. package/rules/ruff-sim113-enumerate-for-loop.json +1 -1
  134. package/rules/ruff-sim208-double-negation.json +1 -1
  135. package/rules/ruff-sim210-if-expr-with-true-false.json +1 -1
  136. package/rules/ruff-sim211-if-expr-with-false-true.json +1 -1
  137. package/rules/ruff-sim212-if-expr-with-twisted-arms.json +2 -2
  138. package/rules/ruff-sim300-yoda-conditions.json +2 -2
  139. package/rules/ruff-sim905-split-static-string.json +1 -1
  140. package/rules/ruff-sim910-dict-get-with-none-default.json +1 -1
  141. package/rules/ruff-t100-debugger.json +3 -3
  142. package/rules/bandit-b406-import-xml-sax.json +0 -73
  143. package/rules/bandit-b610-django-extra-used.json +0 -268
  144. package/rules/ruff-f722-forward-annotation-syntax-error.json +0 -654
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b318-xml-bad-minidom",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect unsafe xml.dom.minidom parsing calls",
6
+ "description": "Use defusedxml instead of xml.dom.minidom to parse XML; the standard parser is open to entity-expansion and other XML attacks on untrusted input.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b319-xml-bad-pulldom",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect unsafe xml.dom.pulldom parsing calls",
6
+ "description": "Use defusedxml instead of xml.dom.pulldom to parse XML; the standard parser is open to entity-expansion and other XML attacks on untrusted input.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b321-ftplib",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect insecure ftplib.FTP construction",
6
+ "description": "Avoid opening ftplib.FTP connections; FTP sends credentials and data unencrypted, so use SFTP, SCP, or another encrypted protocol.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -33,7 +33,7 @@
33
33
  "violation": {
34
34
  "code": "B321",
35
35
  "anchor": "witness.span",
36
- "message": "FTP is unencrypted and insecure; use SSH, SFTP, SCP, or another encrypted protocol.",
36
+ "message": "Replace this FTP connection with SFTP, SCP, or another encrypted protocol; FTP sends credentials in clear text.",
37
37
  "suppress": {
38
38
  "nosec": {
39
39
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b323-unverified-context",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect creation of unverified SSL contexts",
6
+ "description": "Don't create SSL contexts with ssl._create_unverified_context(); it turns off certificate and hostname verification and allows man-in-the-middle attacks.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -33,7 +33,7 @@
33
33
  "violation": {
34
34
  "code": "B323",
35
35
  "anchor": "witness.span",
36
- "message": "Creating an unverified SSL context disables certificate validation and hostname checks.",
36
+ "message": "Use ssl.create_default_context() instead, which verifies certificates and hostnames.",
37
37
  "suppress": {
38
38
  "nosec": {
39
39
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b401-import-telnetlib",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect direct imports of the insecure telnetlib module.",
6
+ "description": "Remove imports of telnetlib; Telnet sends credentials and data unencrypted, so use SSH or another encrypted protocol.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -34,7 +34,7 @@
34
34
  "violation": {
35
35
  "code": "B401",
36
36
  "anchor": "witness.span",
37
- "message": "A telnet-related module is being imported. Telnet is insecure; use SSH or another encrypted protocol.",
37
+ "message": "Remove this telnetlib import and use SSH or another encrypted protocol instead.",
38
38
  "suppress": {
39
39
  "nosec": {
40
40
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b402-import-ftplib",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect direct imports of the insecure ftplib module.",
6
+ "description": "Remove imports of ftplib; FTP sends credentials and data unencrypted, so use SFTP, SCP, or another encrypted protocol.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -34,7 +34,7 @@
34
34
  "violation": {
35
35
  "code": "B402",
36
36
  "anchor": "witness.span",
37
- "message": "An FTP-related module is being imported. FTP is insecure; use SSH, SFTP, SCP, or another encrypted protocol.",
37
+ "message": "Remove this ftplib import and use SFTP, SCP, or another encrypted protocol instead.",
38
38
  "suppress": {
39
39
  "nosec": {
40
40
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b405-import-xml-etree",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect direct imports of xml.etree.cElementTree and xml.etree.ElementTree.",
6
+ "description": "Avoid importing xml.etree.ElementTree or cElementTree; use defusedxml instead, since the standard parsers are open to XML attacks on untrusted input.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b407-import-xml-expat",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect direct imports of xml.dom.expatbuilder.",
6
+ "description": "Avoid importing xml.dom.expatbuilder to parse XML; it is open to XML attacks, so use defusedxml.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b408-import-xml-minidom",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect direct imports of xml.dom.minidom.",
6
+ "description": "Avoid importing xml.dom.minidom to parse XML; it is open to XML attacks, so use defusedxml.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b409-import-xml-pulldom",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect direct imports of xml.dom.pulldom.",
6
+ "description": "Avoid importing xml.dom.pulldom to parse XML; it is open to XML attacks, so use defusedxml.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b411-import-xmlrpclib",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect direct imports of xmlrpc.",
6
+ "description": "Avoid importing xmlrpc unprotected; its XML parsing is open to XML attacks unless patched with defusedxml.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b413-import-pycrypto",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect direct imports of deprecated pyCrypto namespaces.",
6
+ "description": "Avoid importing the pyCrypto package; it is unmaintained and has known vulnerabilities, so use the cryptography package instead.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b415-import-pyghmi",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect direct imports of the insecure pyghmi package.",
6
+ "description": "Avoid importing pyghmi; IPMI is an insecure protocol, so prefer an encrypted management protocol.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -34,7 +34,7 @@
34
34
  "violation": {
35
35
  "code": "B415",
36
36
  "anchor": "witness.span",
37
- "message": "An IPMI-related module is being imported. IPMI is insecure; use an encrypted protocol.",
37
+ "message": "Replace this pyghmi import with a client for an encrypted management protocol such as Redfish over HTTPS; IPMI is insecure.",
38
38
  "suppress": {
39
39
  "nosec": {
40
40
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b502-ssl-with-bad-version",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect calls whose method or ssl_version argument selects an insecure SSL/TLS protocol.",
6
+ "description": "Don't select SSLv2, SSLv3, TLS 1.0 or TLS 1.1 when configuring ssl or pyOpenSSL connections; these protocol versions are broken.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -76,7 +76,7 @@
76
76
  "violation": {
77
77
  "code": "B502",
78
78
  "anchor": "witness.span",
79
- "message": "An SSL context is configured with an insecure protocol version.",
79
+ "message": "Select TLS 1.2 or newer here (e.g. ssl.PROTOCOL_TLS_CLIENT) instead of this SSLv2, SSLv3, TLS 1.0 or TLS 1.1 protocol.",
80
80
  "suppress": {
81
81
  "nosec": {
82
82
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b505-weak-cryptographic-key",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Bandit 1.9.4's B505 weak_cryptographic_key: a DSA or RSA key below 2048 bits or an EC curve below 224 bits, by keyword or position (Bandit's medium thresholds). Port of the kernel test b505_weak_key_sizes_by_keyword_or_position. Bandit's `# nosec` is honoured (`suppress.nosec`), as its recordings honour it.",
6
+ "description": "Use RSA and DSA keys of at least 2048 bits and elliptic curves of at least 224 bits; smaller keys can be broken.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -152,7 +152,7 @@
152
152
  "violation": {
153
153
  "anchor": "witness.span",
154
154
  "code": "B505",
155
- "message": "Bandit B505 (weak-cryptographic-key)",
155
+ "message": "Generate this key with at least 2048 bits for RSA or DSA, or a curve of at least 224 bits for EC; smaller keys can be broken.",
156
156
  "suppress": {
157
157
  "nosec": {
158
158
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b507-ssh-no-host-key-verification",
4
4
  "revision": 4,
5
5
  "mode": "steer",
6
- "description": "Once an import whose name contains paramiko has been walked (Bandit's substring test, in Bandit's source-order walk), flag a call whose function name is set_missing_host_key_policy (the attribute name, a bare name, or a name aliased by an earlier import to one ending in set_missing_host_key_policy) and whose first positional argument is a name, attribute, or call naming AutoAddPolicy or WarningPolicy.",
6
+ "description": "Don't let Paramiko auto-accept unknown SSH host keys with AutoAddPolicy or WarningPolicy; it opens the door to man-in-the-middle attacks.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -196,7 +196,7 @@
196
196
  "violation": {
197
197
  "code": "B507",
198
198
  "anchor": "witness.span",
199
- "message": "Paramiko call with policy set to automatically trust the unknown host key.",
199
+ "message": "Set paramiko.RejectPolicy and load known host keys instead of auto-accepting unknown ones; that invites man-in-the-middle attacks.",
200
200
  "suppress": {
201
201
  "nosec": {
202
202
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b606-start-process-with-no-shell",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Detect configured process APIs that execute without a command shell",
6
+ "description": "Validate input passed to the os exec, spawn and startfile functions; they start whatever program and arguments they receive.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -49,7 +49,7 @@
49
49
  "violation": {
50
50
  "code": "B606",
51
51
  "anchor": "witness.span",
52
- "message": "Review input passed to a no-shell process API",
52
+ "message": "Validate any untrusted input passed to this os exec, spawn or startfile call; it starts whatever program and arguments it receives.",
53
53
  "suppress": {
54
54
  "nosec": {
55
55
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "bandit-b615-huggingface-unsafe-download",
4
4
  "revision": 5,
5
5
  "mode": "steer",
6
- "description": "Require a transformers, datasets, or huggingface_hub-like import; resolve the supported download/load APIs; allow nonliteral revisions, hexadecimal revisions of at least seven characters, or local-path first arguments, and flag all other unpinned downloads.",
6
+ "description": "Pin Hugging Face model and dataset downloads to a specific commit revision; an unpinned download can silently pull changed or tampered files.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*.py"
@@ -1138,7 +1138,7 @@
1138
1138
  "violation": {
1139
1139
  "code": "B615",
1140
1140
  "anchor": "witness.span",
1141
- "message": "Unsafe Hugging Face Hub download without revision pinning in ${API}()",
1141
+ "message": "Pin ${API}() to a specific commit hash with revision=; an unpinned download can silently pull changed or tampered files.",
1142
1142
  "suppress": {
1143
1143
  "nosec": {
1144
1144
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async100-cancel-scope-no-checkpoint",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC100 (cancel-scope-no-checkpoint): a `with` statement whose last timeout-context item (`asyncio.timeout[_at]`, `anyio.move_on_after`/`fail_after`/`CancelScope`, `trio.move_on_after`/`move_on_at`/`fail_after`/`fail_at`/`CancelScope` calls) is the last item when the statement is `async with`, and whose body has no `yield` (nested scopes included) and no `await`, `async with`, `async for` or async comprehension outside nested functions and classes. Reported on the whole statement. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Add an await inside asyncio, anyio or trio timeout and cancel-scope blocks; without a checkpoint the timeout can never fire.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -343,7 +343,7 @@
343
343
  "violation": {
344
344
  "anchor": "witness.span",
345
345
  "code": "ASYNC100",
346
- "message": "A `with $CALLEE(...):` context does not contain any `await` statements. This makes it pointless, as the timeout can only be triggered by a checkpoint.",
346
+ "message": "Add an await inside this `with $CALLEE(...):` block; without a checkpoint the timeout can never fire.",
347
347
  "suppress": {
348
348
  "noqa": {
349
349
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async105-trio-sync-call",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC105 (trio-sync-call): a call to one of trio's async functions (Ruff's MethodName::is_async list) that is not the operand of an `await` (parentheses ignored), in any context. Reported on the call. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Await calls to trio's async functions such as trio.sleep; without await the call only creates a coroutine that never runs.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async115-async-zero-sleep",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC115 (async-zero-sleep): a call to `trio.sleep` or `anyio.sleep` with exactly one argument, an int literal whose value is zero (any radix; parentheses allowed) as `seconds=` (trio), `delay=` (anyio) or the first positional argument, in any context, reported on the call. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Use lowlevel.checkpoint() instead of sleep(0) in trio and anyio code; it states the intent of yielding to the scheduler.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async116-long-sleep-not-forever",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC116 (long-sleep-not-forever): a call to `trio.sleep` or `anyio.sleep` with exactly one argument, an int or float literal (any spelling; not complex, not signed; parentheses allowed) whose value is greater than 86400 as `seconds=` (trio), `delay=` (anyio) or the first positional argument, in any context, reported on the call. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Use sleep_forever() instead of trio or anyio sleep calls longer than 24 hours; a sleep that long is almost always meant to never end.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async210-blocking-http-call-in-async-function",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC210 (blocking-http-call-in-async-function): a call to `urllib.request.urlopen`, `urllib3.request` or an `httpx`/`requests` module-level HTTP method inside an `async def` body whose function is the nearest enclosing function, lambda body or class, reported on the callee. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Don't make blocking HTTP calls with requests, httpx, urllib or urllib3 inside async functions; they stall the event loop.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -147,7 +147,7 @@
147
147
  "violation": {
148
148
  "anchor": "witness.span",
149
149
  "code": "ASYNC210",
150
- "message": "Async functions should not call blocking HTTP methods",
150
+ "message": "Replace this blocking HTTP call with an awaited async client call, such as `httpx.AsyncClient` or `aiohttp`.",
151
151
  "suppress": {
152
152
  "noqa": {
153
153
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async221-run-process-in-async-function",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC221 (run-process-in-async-function): a call to `os.system`, `os.posix_spawn[p]`, `subprocess.run`/`call`/`check_call`/`check_output`/`getoutput`/`getstatusoutput`, or an `os.spawn*` function whose mode (Ruff's find_argument_value(\"mode\", 0): `arguments` in syntactic mode) is absent or `os.P_WAIT` (directly, or through a name whose value, read as find_assigned_value's lookup_symbol does (`resolves.binding` with `stopAtGlobal`), is `os.P_WAIT`) inside an `async def` body whose function is the nearest enclosing function, lambda body or class, reported on the callee. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Don't run processes with subprocess.run, os.system or other blocking process calls inside async functions; they block the event loop until the process exits.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async222-wait-for-process-in-async-function",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC222 (wait-for-process-in-async-function): a call to `os.wait`, `os.wait3`, `os.wait4`, `os.waitid` or `os.waitpid` inside an `async def` body whose function is the nearest enclosing function, lambda body or class, reported on the callee. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Don't call os.wait, os.waitpid or the other blocking os.wait functions inside async functions; they block the event loop.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -130,7 +130,7 @@
130
130
  "violation": {
131
131
  "anchor": "witness.span",
132
132
  "code": "ASYNC222",
133
- "message": "Async functions should not wait on processes with blocking methods",
133
+ "message": "Replace this blocking `os.wait` call by awaiting the async process object, such as `await proc.wait()`.",
134
134
  "suppress": {
135
135
  "noqa": {
136
136
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async230-blocking-open-call-in-async-function",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC230 (blocking-open-call-in-async-function): a call to the builtin `open` (`builtins.open`, `io.open`, `io.open_code`), or `.open()` on a `pathlib.Path(...)` call or on a name whose binding holds one (Ruff's find_binding_value through `resolves.binding`: a plain name assignment, annotated assignment or walrus value, an unpacked name's element of a tuple or list display, or a `with` item's context expression; and, as Ruff's match_value, an unpacked name paired with a display element by index where the engine gives no value: a set display, unequal arities, a position after a starred value), inside an `async def` body whose function is the nearest enclosing function, lambda body or class, reported on the callee. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Don't open files with open(), io.open or Path.open() inside async functions; use an async file API so file I/O doesn't block the event loop.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -325,7 +325,7 @@
325
325
  "violation": {
326
326
  "anchor": "witness.span",
327
327
  "code": "ASYNC230",
328
- "message": "Async functions should not open files with blocking methods like `open`",
328
+ "message": "Open this file with an async file API, such as `anyio.open_file()`, `trio.open_file()` or `aiofiles.open()`.",
329
329
  "suppress": {
330
330
  "noqa": {
331
331
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async250-blocking-input-in-async-function",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC250 (blocking-input-in-async-function): a call to the builtin `input` (the unshadowed name, or `builtins.input`) inside an `async def` body whose function is the nearest enclosing function, lambda body or class, reported on the callee. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Don't call input() inside async functions; it blocks the event loop while waiting for the user.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -129,7 +129,7 @@
129
129
  "violation": {
130
130
  "anchor": "witness.span",
131
131
  "code": "ASYNC250",
132
- "message": "Blocking call to `input()` in async context",
132
+ "message": "Read input in a worker thread, such as `await asyncio.to_thread(input)`, instead of calling `input()` directly.",
133
133
  "suppress": {
134
134
  "noqa": {
135
135
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-async251-blocking-sleep-in-async-function",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's ASYNC251 (blocking-sleep-in-async-function): a call to `time.sleep` inside an `async def` body whose function is the nearest enclosing function, lambda body or class, reported on the callee. Names resolve as in Ruff's resolve_qualified_name, through the engine's `resolves` (M7).",
6
+ "description": "Don't call time.sleep() inside async functions; await the async library's sleep so other tasks keep running.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b002-unary-prefix-increment-decrement",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B002 (unary-prefix-increment-decrement): a unary `+` whose operand is a unary `+`, or a unary `-` whose operand is a unary `-` (parentheses around the operand are transparent, as in Ruff's AST). Reported on the outer unary expression.",
6
+ "description": "Don't write a doubled plus or minus prefix to increment or decrement a value; Python has no such operators, so the value is left unchanged.",
7
7
  "scope": { "include": ["**/*"], "exclude": [] },
8
8
  "clauses": [
9
9
  {
@@ -26,7 +26,7 @@
26
26
  }
27
27
  }
28
28
  },
29
- "violation": { "anchor": "witness.span", "code": "B002", "message": "Python does not support the unary prefix increment operator (`++`)", "suppress": { "noqa": { "codes": ["B002"] } } }
29
+ "violation": { "anchor": "witness.span", "code": "B002", "message": "Replace this `++` prefix with `+= 1`; Python reads `++x` as `x`, so nothing is incremented.", "suppress": { "noqa": { "codes": ["B002"] } } }
30
30
  },
31
31
  {
32
32
  "id": "unary-prefix-decrement",
@@ -48,7 +48,7 @@
48
48
  }
49
49
  }
50
50
  },
51
- "violation": { "anchor": "witness.span", "code": "B002", "message": "Python does not support the unary prefix decrement operator (`--`)", "suppress": { "noqa": { "codes": ["B002"] } } }
51
+ "violation": { "anchor": "witness.span", "code": "B002", "message": "Replace this `--` prefix with `-= 1`; Python reads `--x` as `x`, so nothing is decremented.", "suppress": { "noqa": { "codes": ["B002"] } } }
52
52
  }
53
53
  ]
54
54
  }
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b003-assignment-to-os-environ",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B003 (assignment-to-os-environ): a plain assignment statement with exactly one target, that target being the attribute `os.environ` (the name `os`, not resolved; parentheses around the target are transparent). Chained assignments (several targets), annotated and augmented assignments are not checked, as in Ruff. Reported on the attribute.",
6
+ "description": "Don't assign a new value to os.environ; it doesn't change the real process environment, so update or clear the existing mapping instead.",
7
7
  "scope": { "include": ["**/*"], "exclude": [] },
8
8
  "clauses": [
9
9
  {
@@ -48,7 +48,7 @@
48
48
  }
49
49
  }
50
50
  },
51
- "violation": { "anchor": "witness.span", "code": "B003", "message": "Assigning to `os.environ` doesn't clear the environment", "suppress": { "noqa": { "codes": ["B003"] } } }
51
+ "violation": { "anchor": "witness.span", "code": "B003", "message": "Update `os.environ` in place with `.clear()` and `.update()` instead of assigning a new mapping to it.", "suppress": { "noqa": { "codes": ["B003"] } } }
52
52
  }
53
53
  ]
54
54
  }
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b004-unreliable-callable-check",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B004 (unreliable-callable-check): `hasattr(x, \"__call__\")` with exactly two positional arguments, or `getattr(x, \"__call__\")` / `getattr(x, \"__call__\", default)` with two or three, no keyword arguments, the second argument a str literal (not bytes, an f- or t-string; parentheses transparent) whose value is `__call__` (escapes decoded, implicit concatenations joined). The callee (parentheses transparent) resolves to the builtin `hasattr`/`getattr` (Ruff's `resolve_builtin_symbol`, via `resolves`): the unshadowed name, or that attribute of the `builtins` module through the file's imports. Reported on the call.",
6
+ "description": "Use callable() instead of checking hasattr() or getattr() for __call__; the attribute check gives wrong answers for some objects.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b005-strip-with-multi-characters",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B005 (strip-with-multi-characters): `.strip`/`.lstrip`/`.rstrip` called with exactly one positional argument that is a str literal (not bytes, an f- or t-string; escapes decoded, implicit concatenations joined) whose value repeats a character, tested with a backreference (`(.).*\\1`). Reported on the call.",
6
+ "description": "Avoid strip, lstrip or rstrip with a multi-character string that repeats a character; the argument is a set of characters, not a substring to remove.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -117,7 +117,7 @@
117
117
  "violation": {
118
118
  "anchor": "witness.span",
119
119
  "code": "B005",
120
- "message": "Using `.strip()` with multi-character strings is misleading",
120
+ "message": "List each character once in this strip argument, or use `removeprefix()`/`removesuffix()` to remove a substring.",
121
121
  "suppress": {
122
122
  "noqa": {
123
123
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b007-unused-loop-control-variable",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B007 (unused-loop-control-variable) with the default `dummy-variable-rgx`: a name bound by a `for` loop's target (itself, or inside tuple/list/starred targets) that does not match `^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$` and never occurs as a name expression in the loop body (the `else` clause does not count; attribute members, keyword-argument names, def/class names, parameters, import and global/nonlocal names and except-handler names are not name expressions). The message says `may not be used` when the body calls `locals`/`globals`/`vars`/`exec`/`eval` (by spelling; Ruff checks they are builtins). Match-statement capture, keyword-pattern, star and `as` names are not name expressions either. Reported on the target name.",
6
+ "description": "Rename for-loop variables the loop body never uses to start with an underscore; it shows the value is deliberately ignored.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b009-get-attr-with-constant",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B009 (getattr-with-constant): `getattr(obj, \"name\")` with exactly two positional arguments and no keyword arguments, `obj` not starred, the second a str literal (not bytes, an f- or t-string; escapes decoded, implicit concatenations joined) whose value is a Python identifier (Unicode XID, not a keyword) and not a mangled private name (`__x` without a trailing `__`). The callee (parentheses transparent) resolves to the builtin `getattr` (Ruff's `match_builtin_expr`): the unshadowed name, or `getattr` of the `builtins` module through the file's imports. Reported on the call.",
6
+ "description": "Use plain attribute access instead of getattr() with a constant attribute name; it is no safer and harder to read.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b010-set-attr-with-constant",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B010 (set-attr-with-constant): `setattr(obj, \"name\", value)` used as an expression statement, with exactly three positional arguments and no keyword arguments, `obj` not starred, the name a str literal (not bytes, an f- or t-string; escapes decoded, implicit concatenations joined) whose value is a Python identifier (Unicode XID, not a keyword), not `__debug__` and not a mangled private name. The callee (parentheses transparent) resolves to the builtin `setattr` (Ruff's `match_builtin_expr`): the unshadowed name, or `setattr` of the `builtins` module through the file's imports. Reported on the call.",
6
+ "description": "Use plain attribute assignment instead of setattr() with a constant attribute name; it is no safer and harder to read.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -205,7 +205,7 @@
205
205
  "violation": {
206
206
  "anchor": "witness.span",
207
207
  "code": "B010",
208
- "message": "Do not call `setattr` with a constant attribute value. It is not any safer than normal property access.",
208
+ "message": "Replace this `setattr` call with a plain assignment, such as `obj.name = value`.",
209
209
  "suppress": {
210
210
  "noqa": {
211
211
  "codes": [
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b011-assert-false",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B011 (assert-false): an `assert` statement whose test is the literal `False` (Ruff's `is_const_false`; parentheses transparent), reported on the literal. Ported from the Ruff conformance suite (rerail/conformance/ruff/rules/B011.json at 3f102adcb), with Ruff's `# noqa` honoured as the Ruff CLI honours it.",
6
+ "description": "Raise AssertionError instead of assert False; assertions are stripped when Python runs with optimizations enabled.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b013-redundant-tuple-in-exception-handler",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B013 (redundant-tuple-in-exception-handler): the type of an `except` (or `except*`) handler is a parenthesized tuple with exactly one element that is not starred. Parentheses around the tuple are transparent, and an `as` name does not matter. Reported on the tuple.",
6
+ "description": "Remove the one-element tuple around a single exception type in an except clause; the parentheses and comma are redundant.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"
@@ -3,7 +3,7 @@
3
3
  "id": "ruff-b014-duplicate-handler-exception",
4
4
  "revision": 1,
5
5
  "mode": "steer",
6
- "description": "Port of Ruff's B014 (duplicate-handler-exception): the type of an `except` (or `except*`) handler is a tuple in which the same dotted name (a name or an attribute chain of names, Ruff's `UnqualifiedName`) occurs more than once (parentheses around an element are transparent). Reported once on the tuple, whatever the number of duplicates.",
6
+ "description": "Remove duplicate exception types from an except clause's tuple; naming one twice adds nothing.",
7
7
  "scope": {
8
8
  "include": [
9
9
  "**/*"