python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.18k stars 2.78k forks source link

Capitalize error messages consistently #15125

Closed JukkaL closed 1 year ago

JukkaL commented 1 year ago

Most error messages start with a capital letter, but syntax errors in particular start with a lowercase letter. Example program:

x y

Error message:

t.py:1: error: invalid syntax  [syntax]

The desired message would be like this:

t.py:1: error: Invalid syntax  [syntax]

You can search for the regexp # E: [a-z] under test-data/ to find most of these inconsistent error messages. We should make the error messages consistent.

Note that some error messages are from the Python ast module which we use for parsing. We can probably just capitalize the first letter of all of these errors.

mparigi commented 1 year ago

In the above PR, I left some errors as they are, specifically if they reference an identifier or if they are part of a comment.

Here are the errors left intact, found by searching with regex # E: [a-z]:

mypy/test/data.py:
  518  def expand_errors(input: list[str], output: list[str], fnam: str) -> None:
  519:     """Transform comments such as '# E: message' or
  520      '# E:3: message' in input.

mypy/test/testcmdline.py:
  111          expected_out = testcase.output if step == 1 else testcase.output2[step]
  112:         # Strip "tmp/" out of the test so that # E: works...
  113          expected_out = [s.replace("tmp" + os.sep, "") for s in expected_out]

mypyc/test-data/commandline.test:
  113  def busted(b: bool) -> None:
  114:     for i in range(1, 10, 0):  # E: range() step can't be zero
  115          try:
  116              if i == 5:
  117:                 break  # E: break inside try/finally block is unimplemented
  118              elif i == 4:
  119:                 continue  # E: continue inside try/finally block is unimplemented
  120          finally:

  218  async def async_generators() -> AsyncIterable[int]:
  219:     yield 1  # E: async generators are unimplemented
  220

test-data/unit/check-attr.test:
  288
  289: @attrs(order=True, eq=False)  # E: eq must be True if order is True
  290  class Confused:

  826  class C:
  827:     x: str = attr.ib(convert=convert)  # E: convert is deprecated, use converter
  828

test-data/unit/check-errorcodes.test:
  978  [case testRecommendErrorCode]
  979: # type: ignore[whatever]  # E: type ignore with error code is not supported for modules; use `# mypy: disable-error-code="whatever"`  [syntax]
  980  1 + "asdf"

  982  [case testRecommendErrorCode2]
  983: # type: ignore[whatever, other]  # E: type ignore with error code is not supported for modules; use `# mypy: disable-error-code="whatever, other"`  [syntax]
  984  1 + "asdf"

test-data/unit/check-singledispatch.test:
  60  @singledispatch
  61: def f(arg: int) -> None: # E: singledispatch implementation 1 will never be used: implementation 2's dispatch type is the same
  62      pass

test-data/unit/check-super.test:
  280  class C:
  281:     a = super().whatever  # E: super() outside of a method is not supported
  282

  368      def g() -> None: # E: Method must have at least one argument. Did you forget the "self" argument?
  369:         super().f() # E: super() requires one or more positional arguments in enclosing function
  370      def h(self) -> None:
  371          def a() -> None:
  372:             super().f() # E: super() requires one or more positional arguments in enclosing function
  373

test-data/unit/README.md:
  28  - optional `# flags: ` indicates which flags to use for this unit test
  29: - `# E: abc...` indicates that this line should result in type check error
  30  with text "abc..."
JelleZijlstra commented 1 year ago

Perhaps these should be quoted, e.g. # E: "super()" outside ....

mparigi commented 1 year ago

That sounds reasonable, but would we need to quote identifiers like that if they appear after the first word of the error? e.g. # E: break inside try/finally block is unimplemented becomes # E: "break" inside "try"/"finally" block is unimplemented