Skip to content

Commit

Permalink
Add --strict-bytes flag (#18263)
Browse files Browse the repository at this point in the history
Closes #18256
  • Loading branch information
hamdanal authored Dec 10, 2024
1 parent 568648d commit 6427ef1
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 0 deletions.
29 changes: 29 additions & 0 deletions docs/source/command_line.rst
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,35 @@ of the above sections.
assert text is not None # OK, check against None is allowed as a special case.
.. option:: --strict-bytes

By default, mypy treats ``bytearray`` and ``memoryview`` as subtypes of ``bytes`` which
is not true at runtime. Use this flag to disable this behavior. ``--strict-bytes`` will
be enabled by default in *mypy 2.0*.

.. code-block:: python
def f(buf: bytes) -> None:
assert isinstance(buf, bytes) # Raises runtime AssertionError with bytearray/memoryview
with open("binary_file", "wb") as fp:
fp.write(buf)
f(bytearray(b"")) # error: Argument 1 to "f" has incompatible type "bytearray"; expected "bytes"
f(memoryview(b"")) # error: Argument 1 to "f" has incompatible type "memoryview"; expected "bytes"
# If `f` accepts any object that implements the buffer protocol, consider using:
from collections.abc import Buffer # "from typing_extensions" in Python 3.11 and earlier
def f(buf: Buffer) -> None:
with open("binary_file", "wb") as fp:
fp.write(buf)
f(b"") # Ok
f(bytearray(b"")) # Ok
f(memoryview(b"")) # Ok
.. option:: --extra-checks

This flag enables additional checks that are technically correct but may be
Expand Down
8 changes: 8 additions & 0 deletions docs/source/config_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,14 @@ section of the command line docs.
Prohibit equality checks, identity checks, and container checks between
non-overlapping types.

.. confval:: strict_bytes

:type: boolean
:default: False

Disable treating ``bytearray`` and ``memoryview`` as subtypes of ``bytes``.
This will be enabled by default in *mypy 2.0*.

.. confval:: strict

:type: boolean
Expand Down
13 changes: 13 additions & 0 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,14 @@ def add_invertible_flag(
group=strictness_group,
)

add_invertible_flag(
"--strict-bytes",
default=False,
strict_flag=False,
help="Disable treating bytearray and memoryview as subtypes of bytes",
group=strictness_group,
)

add_invertible_flag(
"--extra-checks",
default=False,
Expand Down Expand Up @@ -1386,6 +1394,11 @@ def set_strict_flags() -> None:

process_cache_map(parser, special_opts, options)

# Process --strict-bytes
if options.strict_bytes:
options.disable_bytearray_promotion = True
options.disable_memoryview_promotion = True

# An explicitly specified cache_fine_grained implies local_partial_types
# (because otherwise the cache is not compatible with dmypy)
if options.cache_fine_grained:
Expand Down
4 changes: 4 additions & 0 deletions mypy/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class BuildType:
"plugins",
"disable_bytearray_promotion",
"disable_memoryview_promotion",
"strict_bytes",
}
) - {"debug_cache"}

Expand Down Expand Up @@ -215,6 +216,9 @@ def __init__(self) -> None:
# This makes 1 == '1', 1 in ['1'], and 1 is '1' errors.
self.strict_equality = False

# Disable treating bytearray and memoryview as subtypes of bytes
self.strict_bytes = False

# Deprecated, use extra_checks instead.
self.strict_concatenate = False

Expand Down
14 changes: 14 additions & 0 deletions test-data/unit/check-flags.test
Original file line number Diff line number Diff line change
Expand Up @@ -2393,6 +2393,20 @@ def f(x: bytes, y: bytearray, z: memoryview) -> None:
x in z
[builtins fixtures/primitives.pyi]

[case testStrictBytes]
# flags: --strict-bytes
def f(x: bytes) -> None: ...
f(bytearray(b"asdf")) # E: Argument 1 to "f" has incompatible type "bytearray"; expected "bytes"
f(memoryview(b"asdf")) # E: Argument 1 to "f" has incompatible type "memoryview"; expected "bytes"
[builtins fixtures/primitives.pyi]

[case testNoStrictBytes]
# flags: --no-strict-bytes
def f(x: bytes) -> None: ...
f(bytearray(b"asdf"))
f(memoryview(b"asdf"))
[builtins fixtures/primitives.pyi]

[case testNoCrashFollowImportsForStubs]
# flags: --config-file tmp/mypy.ini
{**{"x": "y"}}
Expand Down

0 comments on commit 6427ef1

Please sign in to comment.