requirements: Update zulint with multiline pattern support.

https://github.com/zulip/zulint/pull/28

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2022-05-16 19:46:10 -07:00 committed by Tim Abbott
parent 3741c1c034
commit ecb900bd03
5 changed files with 41 additions and 65 deletions

View File

@ -57,7 +57,7 @@ python-digitalocean
pip-tools<6.3.0 # https://github.com/jazzband/pip-tools/pull/1455 breaks our hack for installing specific commits from Git pip-tools<6.3.0 # https://github.com/jazzband/pip-tools/pull/1455 breaks our hack for installing specific commits from Git
# zulip's linting framework - zulint # zulip's linting framework - zulint
https://github.com/zulip/zulint/archive/80a613cca5ec35bc5add7f3c70916ce269a9d27c.zip#egg=zulint==0.0.1 https://github.com/zulip/zulint/archive/34adbc13d54ebeb4291c8f91483f946fce18a160.zip#egg=zulint==0.0.1
-r mypy.in -r mypy.in

View File

@ -2398,8 +2398,8 @@ zope.interface==5.4.0 \
# via # via
# scrapy # scrapy
# twisted # twisted
https://github.com/zulip/zulint/archive/80a613cca5ec35bc5add7f3c70916ce269a9d27c.zip#egg=zulint==0.0.1 \ https://github.com/zulip/zulint/archive/34adbc13d54ebeb4291c8f91483f946fce18a160.zip#egg=zulint==0.0.1 \
--hash=sha256:e1e03c4599b0848f7e021a6f211d6ee06bf63602cbf25c7bb271ec51c911accf --hash=sha256:18dd1fd2d8f5b3feb8468151ccae4c0e8345c77142093988dd96739ac9becac2
# via -r requirements/dev.in # via -r requirements/dev.in
https://github.com/zulip/python-zulip-api/archive/0.8.2.zip#egg=zulip==0.8.2+git&subdirectory=zulip \ https://github.com/zulip/python-zulip-api/archive/0.8.2.zip#egg=zulip==0.8.2+git&subdirectory=zulip \
--hash=sha256:c85a2c76b265ef66478715bb2a38723c4942f84b2f876c3e0ba916962e3d0735 --hash=sha256:c85a2c76b265ef66478715bb2a38723c4942f84b2f876c3e0ba916962e3d0735

View File

@ -67,7 +67,7 @@ A few more details:
Slack-compatible format. Slack-compatible format.
This is the preferred bot type for interactive bots built on top of Zulip This is the preferred bot type for interactive bots built on top of Zulip
botserver. Botserver.
## Adding bots ## Adding bots

View File

@ -37,7 +37,7 @@ FILES_WITH_LEGACY_SUBJECT = {
shebang_rules: List["Rule"] = [ shebang_rules: List["Rule"] = [
{ {
"pattern": "^#!", "pattern": r"\A#!",
"description": "zerver library code shouldn't have a shebang line.", "description": "zerver library code shouldn't have a shebang line.",
"include_only": {"zerver/"}, "include_only": {"zerver/"},
}, },
@ -45,32 +45,35 @@ shebang_rules: List["Rule"] = [
# that NixOS provides at a fixed path (outside a # that NixOS provides at a fixed path (outside a
# buildFHSUserEnv sandbox). # buildFHSUserEnv sandbox).
{ {
"pattern": "^#!(?! *(?:/usr/bin/env|/bin/sh)(?: |$))", "pattern": r"\A#!(?! *(?:/usr/bin/env|/bin/sh)(?: |$))",
"description": "Use `#!/usr/bin/env foo` instead of `#!/path/foo`" "description": "Use `#!/usr/bin/env foo` instead of `#!/path/foo`"
" for interpreters other than sh.", " for interpreters other than sh.",
}, },
{ {
"pattern": "^#!/usr/bin/env python$", "pattern": r"\A#!/usr/bin/env python$",
"description": "Use `#!/usr/bin/env python3` instead of `#!/usr/bin/env python`.", "description": "Use `#!/usr/bin/env python3` instead of `#!/usr/bin/env python`.",
}, },
] ]
trailing_whitespace_rule: "Rule" = { base_whitespace_rules: List["Rule"] = [
"pattern": r"\s+$", {
"strip": "\n", "pattern": r"[\t ]+$",
"exclude": {"tools/ci/success-http-headers.template.txt"}, "exclude": {"tools/ci/success-http-headers.template.txt"},
"description": "Fix trailing whitespace", "description": "Fix trailing whitespace",
} },
{
"pattern": r"[^\n]\Z",
"description": "Missing newline at end of file",
},
]
whitespace_rules: List["Rule"] = [ whitespace_rules: List["Rule"] = [
# This linter should be first since bash_rules depends on it. *base_whitespace_rules,
trailing_whitespace_rule,
{ {
"pattern": "http://zulip.readthedocs.io", "pattern": "http://zulip.readthedocs.io",
"description": "Use HTTPS when linking to ReadTheDocs", "description": "Use HTTPS when linking to ReadTheDocs",
}, },
{ {
"pattern": "\t", "pattern": "\t",
"strip": "\n",
"description": "Fix tab-based whitespace", "description": "Fix tab-based whitespace",
}, },
] ]
@ -84,18 +87,16 @@ comma_whitespace_rule: List["Rule"] = [
}, },
] ]
markdown_whitespace_rules: List["Rule"] = [ markdown_whitespace_rules: List["Rule"] = [
*(rule for rule in whitespace_rules if rule["pattern"] != r"\s+$"), *(rule for rule in whitespace_rules if rule["pattern"] != r"[\t ]+$"),
# Two spaces trailing a line with other content is okay--it's a Markdown line break. # Two spaces trailing a line with other content is okay--it's a Markdown line break.
# This rule finds one space trailing a non-space, three or more trailing spaces, and # This rule finds one space trailing a non-space, three or more trailing spaces, and
# spaces on an empty line. # spaces on an empty line.
{ {
"pattern": r"((?<!\s)\s$)|(\s\s\s+$)|(^\s+$)", "pattern": r"((?<![\t ])[\t ]$)|([\t ][\t ][\t ]+$)|(^[\t ]+$)",
"strip": "\n",
"description": "Fix trailing whitespace", "description": "Fix trailing whitespace",
}, },
{ {
"pattern": "^#+[A-Za-z0-9]", "pattern": "^#+[A-Za-z0-9]",
"strip": "\n",
"description": "Missing space after # in heading", "description": "Missing space after # in heading",
"exclude_line": { "exclude_line": {
("docs/subsystems/hotspots.md", "#hotspot_new_hotspot_name_icon {"), ("docs/subsystems/hotspots.md", "#hotspot_new_hotspot_name_icon {"),
@ -247,13 +248,13 @@ python_rules = RuleList(
"description": 'Avoid using "msgid" as a variable name; use "message_id" instead.', "description": 'Avoid using "msgid" as a variable name; use "message_id" instead.',
}, },
{ {
"pattern": "^(?!#)@login_required", "pattern": r"^[\t ]*(?!#)@login_required",
"description": "@login_required is unsupported; use @zulip_login_required", "description": "@login_required is unsupported; use @zulip_login_required",
"good_lines": ["@zulip_login_required", "# foo @login_required"], "good_lines": ["@zulip_login_required", "# foo @login_required"],
"bad_lines": ["@login_required", " @login_required"], "bad_lines": ["@login_required", " @login_required"],
}, },
{ {
"pattern": "^user_profile[.]save[(][)]", "pattern": r"^[\t ]*user_profile[.]save[(][)]",
"description": "Always pass update_fields when saving user_profile objects", "description": "Always pass update_fields when saving user_profile objects",
"exclude_line": { "exclude_line": {
( (
@ -278,7 +279,7 @@ python_rules = RuleList(
"bad_lines": ["assertEquals(1, 2)"], "bad_lines": ["assertEquals(1, 2)"],
}, },
{ {
"pattern": "assertEqual[(]len[(][^ ]*[)],", "pattern": r"assertEqual[(]len[(][^\n ]*[)],",
"description": "Use the assert_length helper instead of assertEqual(len(..), ..).", "description": "Use the assert_length helper instead of assertEqual(len(..), ..).",
"good_lines": ["assert_length(data, 2)"], "good_lines": ["assert_length(data, 2)"],
"bad_lines": ["assertEqual(len(data), 2)"], "bad_lines": ["assertEqual(len(data), 2)"],
@ -288,7 +289,7 @@ python_rules = RuleList(
}, },
}, },
{ {
"pattern": "assertTrue[(]len[(][^ ]*[)]", "pattern": r"assertTrue[(]len[(][^\n ]*[)]",
"description": "Use assert_length or assertGreater helper instead of assertTrue(len(..) ..).", "description": "Use assert_length or assertGreater helper instead of assertTrue(len(..) ..).",
"good_lines": ["assert_length(data, 2)", "assertGreater(len(data), 2)"], "good_lines": ["assert_length(data, 2)", "assertGreater(len(data), 2)"],
"bad_lines": [ "bad_lines": [
@ -298,7 +299,7 @@ python_rules = RuleList(
], ],
}, },
{ {
"pattern": r"#\s*type:\s*ignore(?!\[[^][]+\] +# +\S)", "pattern": r"#[\t ]*type:[\t ]*ignore(?!\[[^]\n[]+\] +# +\S)",
"exclude": {"tools/tests", "zerver/lib/test_runner.py", "zerver/tests"}, "exclude": {"tools/tests", "zerver/lib/test_runner.py", "zerver/tests"},
"description": '"type: ignore" should always end with "# type: ignore[code] # explanation for why"', "description": '"type: ignore" should always end with "# type: ignore[code] # explanation for why"',
"good_lines": ["foo = bar # type: ignore[code] # explanation"], "good_lines": ["foo = bar # type: ignore[code] # explanation"],
@ -410,11 +411,11 @@ python_rules = RuleList(
"bad_lines": ["if my_django_model.pk == 42"], "bad_lines": ["if my_django_model.pk == 42"],
}, },
{ {
"pattern": r"^\s*#\s*type:", "pattern": r"^[\t ]*#[\t ]*type:",
"description": "Comment-style function type annotation. Use Python3 style annotations instead.", "description": "Comment-style function type annotation. Use Python3 style annotations instead.",
}, },
{ {
"pattern": r"\S\s*#\s*type:(?!\s*ignore)", "pattern": r"\S[\t ]*#[\t ]*type:(?![\t ]*ignore)",
"exclude": { "exclude": {
"scripts/lib/hash_reqs.py", "scripts/lib/hash_reqs.py",
"scripts/lib/setup_venv.py", "scripts/lib/setup_venv.py",
@ -426,7 +427,7 @@ python_rules = RuleList(
"bad_lines": ["a = [] # type: List[int]"], "bad_lines": ["a = [] # type: List[int]"],
}, },
{ {
"pattern": r": *(?!Optional)[^ ].*= models[.].*null=True", "pattern": r": *(?!Optional)[^\n ].*= models[.].*null=True",
"include_only": {"zerver/models.py"}, "include_only": {"zerver/models.py"},
"description": "Model variable with null=true not annotated as Optional.", "description": "Model variable with null=true not annotated as Optional.",
"good_lines": [ "good_lines": [
@ -463,7 +464,7 @@ python_rules = RuleList(
"exclude": {"zerver/management/commands/process_queue.py"}, "exclude": {"zerver/management/commands/process_queue.py"},
}, },
{ {
"pattern": ".is_realm_admin =", "pattern": r"\.is_realm_admin =",
"description": "Use do_change_user_role function rather than setting UserProfile's is_realm_admin attribute directly.", "description": "Use do_change_user_role function rather than setting UserProfile's is_realm_admin attribute directly.",
"exclude": { "exclude": {
"zerver/migrations/0248_userprofile_role_start.py", "zerver/migrations/0248_userprofile_role_start.py",
@ -471,7 +472,7 @@ python_rules = RuleList(
}, },
}, },
{ {
"pattern": ".is_guest =", "pattern": r"\.is_guest =",
"description": "Use do_change_user_role function rather than setting UserProfile's is_guest attribute directly.", "description": "Use do_change_user_role function rather than setting UserProfile's is_guest attribute directly.",
"exclude": { "exclude": {
"zerver/migrations/0248_userprofile_role_start.py", "zerver/migrations/0248_userprofile_role_start.py",
@ -487,9 +488,8 @@ python_rules = RuleList(
"description": "Use @transaction.atomic as function decorator for consistency.", "description": "Use @transaction.atomic as function decorator for consistency.",
}, },
*whitespace_rules, *whitespace_rules,
*shebang_rules,
], ],
max_length=110,
shebang_rules=shebang_rules,
) )
bash_rules = RuleList( bash_rules = RuleList(
@ -508,9 +508,9 @@ bash_rules = RuleList(
"scripts/lib/install", "scripts/lib/install",
}, },
}, },
*whitespace_rules[0:1], *base_whitespace_rules,
*shebang_rules,
], ],
shebang_rules=shebang_rules,
) )
css_rules = RuleList( css_rules = RuleList(
@ -522,12 +522,12 @@ css_rules = RuleList(
prose_style_rules: List["Rule"] = [ prose_style_rules: List["Rule"] = [
{ {
"pattern": r'^[^{].*?[^\/\#\-"]([jJ]avascript)', # exclude usage in hrefs/divs/custom-markdown "pattern": r'^[\t ]*[^\n{].*?[^\n\/\#\-"]([jJ]avascript)', # exclude usage in hrefs/divs/custom-markdown
"exclude": {"docs/documentation/api.md", "templates/corporate/policies/privacy.md"}, "exclude": {"docs/documentation/api.md", "templates/corporate/policies/privacy.md"},
"description": "javascript should be spelled JavaScript", "description": "javascript should be spelled JavaScript",
}, },
{ {
"pattern": r"""[^\/\-\."'\_\=\>]([gG]ithub)[^\.\-\_"\<]""", # exclude usage in hrefs/divs "pattern": r"""[^\n\/\-\."'\_\=\>]([gG]ithub)[^\n\.\-\_"\<]""", # exclude usage in hrefs/divs
"description": "github should be spelled GitHub", "description": "github should be spelled GitHub",
}, },
{ {
@ -820,10 +820,9 @@ json_rules = RuleList(
# version of the tab-based whitespace rule (we can't just use # version of the tab-based whitespace rule (we can't just use
# exclude in whitespace_rules, since we only want to ignore # exclude in whitespace_rules, since we only want to ignore
# JSON files with tab-based whitespace, not webhook code). # JSON files with tab-based whitespace, not webhook code).
trailing_whitespace_rule, *base_whitespace_rules,
{ {
"pattern": "\t", "pattern": "\t",
"strip": "\n",
"exclude": {"zerver/webhooks/"}, "exclude": {"zerver/webhooks/"},
"description": "Fix tab-based whitespace", "description": "Fix tab-based whitespace",
}, },
@ -835,27 +834,6 @@ json_rules = RuleList(
], ],
) )
markdown_docs_length_exclude = {
# Has some example Vagrant output that's very long
"docs/development/setup-vagrant.md",
# Have wide output in code blocks
"docs/subsystems/logging.md",
"docs/subsystems/schema-migrations.md",
# Have curl commands with JSON that would be messy to wrap
"zerver/webhooks/helloworld/doc.md",
"zerver/webhooks/trello/doc.md",
# Has a very long configuration line
"templates/zerver/integrations/perforce.md",
# Has some example code that could perhaps be wrapped
"templates/zerver/api/incoming-webhooks-walkthrough.md",
"templates/zerver/api/get-messages.md",
# This macro has a long indented URL
"templates/zerver/help/include/git-webhook-url-with-branches-indented.md",
# These two are the same file and have some too-long lines for GitHub badges
"README.md",
"docs/overview/readme.md",
}
markdown_rules = RuleList( markdown_rules = RuleList(
langs=["md"], langs=["md"],
rules=[ rules=[
@ -899,8 +877,6 @@ markdown_rules = RuleList(
"description": "Don't link directly to line numbers", "description": "Don't link directly to line numbers",
}, },
], ],
max_length=120,
length_exclude=markdown_docs_length_exclude,
exclude_files_in="templates/zerver/help/", exclude_files_in="templates/zerver/help/",
) )
@ -926,14 +902,14 @@ help_markdown_rules = RuleList(
"exclude_pattern": "(-realm-|[kK]eycloak)", "exclude_pattern": "(-realm-|[kK]eycloak)",
}, },
], ],
length_exclude=markdown_docs_length_exclude,
) )
puppet_rules = RuleList( puppet_rules = RuleList(
langs=["pp"], langs=["pp"],
rules=[ rules=[
*whitespace_rules,
{ {
"pattern": r"(include\s+|\$)zulip::(profile|base)\b", "pattern": r"(include[\t ]+|\$)zulip::(profile|base)\b",
"exclude": { "exclude": {
"puppet/zulip/manifests/profile/", "puppet/zulip/manifests/profile/",
"puppet/zulip_ops/manifests/", "puppet/zulip_ops/manifests/",
@ -942,7 +918,7 @@ puppet_rules = RuleList(
"description": "Abstraction layering violation; only profiles should reference profiles or zulip::base", "description": "Abstraction layering violation; only profiles should reference profiles or zulip::base",
}, },
{ {
"pattern": r"(include\s+|\$)zulip_ops::(profile|base)\b", "pattern": r"(include[\t ]+|\$)zulip_ops::(profile|base)\b",
"exclude": { "exclude": {
"puppet/zulip/manifests/", "puppet/zulip/manifests/",
"puppet/zulip_ops/manifests/profile/", "puppet/zulip_ops/manifests/profile/",

View File

@ -48,4 +48,4 @@ API_FEATURE_LEVEL = 132
# historical commits sharing the same major version, in which case a # historical commits sharing the same major version, in which case a
# minor version bump suffices. # minor version bump suffices.
PROVISION_VERSION = "188.1" PROVISION_VERSION = "189.0"