Skip to content

Commit b65f65f

Browse files
committed
Merge remote-tracking branch 'upstream/master' into try-native-parser
2 parents e875d15 + e8e1a63 commit b65f65f

32 files changed

Lines changed: 695 additions & 60 deletions

mypy-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ mypy_extensions>=1.0.0
66
pathspec>=1.0.0
77
tomli>=1.1.0; python_version<'3.11'
88
librt>=0.9.0; platform_python_implementation != 'PyPy'
9-
ast-serialize>=0.2.2,<1.0.0
9+
ast-serialize>=0.2.3,<1.0.0

mypy/build.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3314,7 +3314,9 @@ def semantic_analysis_pass1(self) -> None:
33143314
#
33153315
# TODO: This should not be considered as a semantic analysis
33163316
# pass -- it's an independent pass.
3317-
if not options.native_parser:
3317+
if not options.native_parser or not self.manager.fscache.exists(
3318+
self.xpath, real_only=True
3319+
):
33183320
analyzer = SemanticAnalyzerPreAnalysis()
33193321
with self.wrap_context():
33203322
analyzer.visit_file(self.tree, self.xpath, self.id, options)

mypy/checker.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6910,6 +6910,10 @@ def narrow_type_by_identity_equality(
69106910
if should_coerce_literals:
69116911
target_type = coerce_to_literal(target_type)
69126912

6913+
# Morally what we want to do is narrow for each branch based on:
6914+
# `if_type, else_type = conditional_types(expr_type, target)`
6915+
# What we actually do is first munge expr_type based on target_type to handle some
6916+
# special cased known `__eq__` implementations.
69136917
narrowable_expr_type, ambiguous_expr_type = partition_equality_ambiguous_types(
69146918
expr_type, target_type, is_identity=is_identity_comparison
69156919
)
@@ -6964,8 +6968,8 @@ def narrow_type_by_identity_equality(
69646968
continue
69656969
union_expr_type = get_proper_type(operand_types[i])
69666970
if not isinstance(union_expr_type, UnionType):
6967-
# Here we won't be able to do any positive narrowing, because we can't conclude
6968-
# anything from a custom __eq__ returning True.
6971+
# Here we don't do any positive narrowing, because we can't conclude much
6972+
# from a custom __eq__ returning True.
69696973
# But we might be able to do some negative narrowing, since we can assume
69706974
# a custom __eq__ is reflexive. This should only apply to custom __eq__ enums,
69716975
# see testNarrowingEqualityCustomEqualityEnum
@@ -7038,7 +7042,10 @@ def narrow_type_by_identity_equality(
70387042
if_map, else_map = conditional_types_to_typemaps(
70397043
operands[i], if_type, else_type
70407044
)
7041-
or_if_maps.append(if_map)
7045+
if not isinstance(get_proper_type(expr_type), AnyType):
7046+
# We avoid positive narrowing for Any here, for consistency with the
7047+
# non-union branch above and to preserve the gradual guarantee
7048+
or_if_maps.append(if_map)
70427049
if is_target_for_value_narrowing(get_proper_type(target_type)):
70437050
or_else_maps.append(else_map)
70447051

mypy/nativeparse.py

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -715,14 +715,14 @@ def read_class_def(state: State, data: ReadBuffer) -> ClassDef:
715715
keywords.append((key, value))
716716

717717
metaclass = dict(keywords).get("metaclass") if keywords else None
718-
filtered_keywords = [(k, v) for k, v in keywords if k != "metaclass"] if keywords else None
719718

720719
class_def = ClassDef(
721720
name,
722721
body,
723722
base_type_exprs=base_type_exprs if base_type_exprs else None,
724723
metaclass=metaclass,
725-
keywords=filtered_keywords,
724+
# Note we keep metaclass in keywords as well, to match the old parser.
725+
keywords=keywords if keywords else None,
726726
type_args=type_params,
727727
)
728728
class_def.decorators = decorators
@@ -1329,15 +1329,16 @@ def read_expression(state: State, data: ReadBuffer) -> Expression:
13291329
op = bool_ops[read_int(data)]
13301330
values = read_expression_list(state, data)
13311331
# Convert list of values to nested OpExpr nodes
1332-
# E.g., [a, b, c] with "and" becomes OpExpr("and", OpExpr("and", a, b), c)
1332+
# E.g., [a, b, c] with "and" becomes OpExpr("and", a, OpExpr("and", b, c))
1333+
# This matches the old parser behavior, on which we may implicitly rely.
13331334
assert len(values) >= 2
1334-
result = values[0]
1335-
for val in values[1:]:
1336-
result = OpExpr(op, result, val)
1337-
result.line = values[0].line
1338-
result.column = values[0].column
1339-
result.end_line = val.end_line
1340-
result.end_column = val.end_column
1335+
result = last = values[-1]
1336+
for val in values[-2::-1]:
1337+
result = OpExpr(op, val, result)
1338+
result.line = val.line
1339+
result.column = val.column
1340+
result.end_line = last.end_line
1341+
result.end_column = last.end_column
13411342
read_loc(data, result)
13421343
expect_end_tag(data)
13431344
return result
@@ -1375,7 +1376,7 @@ def read_expression(state: State, data: ReadBuffer) -> Expression:
13751376
s = StrExpr(read_str(data))
13761377
read_loc(data, s)
13771378
fitems.append(s)
1378-
expr = build_fstring_join(state, data, fitems)
1379+
expr = build_fstring_join(data, fitems)
13791380
expect_end_tag(data)
13801381
return expr
13811382
elif tag == nodes.LIST_COMPREHENSION:
@@ -1576,22 +1577,17 @@ def read_expression(state: State, data: ReadBuffer) -> Expression:
15761577

15771578

15781579
def read_fstring_items(state: State, data: ReadBuffer) -> Expression:
1579-
items = []
15801580
n = read_int(data)
1581-
items = [read_fstring_item(state, data) for i in range(n)]
1582-
return build_fstring_join(state, data, items)
1581+
items = [read_fstring_item(state, data) for _ in range(n)]
1582+
return build_fstring_join(data, items)
15831583

15841584

1585-
def build_fstring_join(state: State, data: ReadBuffer, items: list[Expression]) -> Expression:
1585+
def build_fstring_join(data: ReadBuffer, items: list[Expression]) -> Expression:
1586+
items = collapse_consecutive_str_items(items)
15861587
if len(items) == 1:
15871588
expr = items[0]
15881589
read_loc(data, expr)
15891590
return expr
1590-
if all(isinstance(item, StrExpr) for item in items):
1591-
s = "".join([cast(StrExpr, item).value for item in items])
1592-
expr = StrExpr(s)
1593-
read_loc(data, expr)
1594-
return expr
15951591
args = ListExpr(items)
15961592
str_expr = StrExpr("")
15971593
member = MemberExpr(str_expr, "join")
@@ -1603,6 +1599,22 @@ def build_fstring_join(state: State, data: ReadBuffer, items: list[Expression])
16031599
return call
16041600

16051601

1602+
def collapse_consecutive_str_items(items: list[Expression]) -> list[Expression]:
1603+
if len(items) <= 1:
1604+
return items
1605+
last = items[0]
1606+
new_items = [last]
1607+
for item in items[1:]:
1608+
if isinstance(last, StrExpr) and isinstance(item, StrExpr):
1609+
last.value += item.value
1610+
last.end_line = item.end_line
1611+
last.end_column = item.end_column
1612+
else:
1613+
new_items.append(item)
1614+
last = item
1615+
return new_items
1616+
1617+
16061618
def read_fstring_item(state: State, data: ReadBuffer) -> Expression:
16071619
t = read_tag(data)
16081620
if t == LITERAL_STR:

mypy/plugins/dataclasses.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ def collect_attributes(self) -> list[DataclassAttribute] | None:
662662

663663
# Allow bare x: Final[int] in class body, since it will be set in the generated
664664
# __init__() method (unless it is an InitVar), to match regular class semantics.
665-
if node.is_final and not node.is_classvar and node.final_unset_in_class:
665+
if node.is_final and node.final_unset_in_class:
666666
if is_init_var:
667667
self._api.fail("InitVar cannot be final", stmt.rvalue)
668668
else:

mypyc/doc/conf.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
# Add any Sphinx extension module names here, as strings. They can be
3737
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
3838
# ones.
39-
extensions: list[str] = []
39+
extensions = ["sphinx.ext.intersphinx"]
40+
41+
intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
4042

4143
# Add any paths that contain templates here, relative to this directory.
4244
templates_path = ["_templates"]

mypyc/doc/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ generate fast code.
3333

3434
librt
3535
librt_base64
36+
librt_strings
37+
librt_time
3638

3739
.. toctree::
3840
:maxdepth: 2

mypyc/doc/librt.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Librt overview
44
==============
55

6-
The `librt <https://pypi.org/project/librt/>`_ package defines fast
6+
The `librt <https://pypi.org/project/librt/>`__ package defines fast
77
primitive operations that are optimized for code compiled
88
using mypyc. It has carefully selected efficient alternatives for
99
certain Python standard library features.
@@ -26,6 +26,10 @@ Follow submodule links in the table to a detailed description of each submodule.
2626
- Description
2727
* - :doc:`librt.base64 <librt_base64>`
2828
- Fast Base64 encoding and decoding
29+
* - :doc:`librt.strings <librt_strings>`
30+
- String and bytes utilities
31+
* - :doc:`librt.time <librt_time>`
32+
- Time utilities
2933

3034
Installing librt
3135
----------------

0 commit comments

Comments
 (0)