Skip to content

Commit ed129dc

Browse files
authored
Commit the generated .pyi files (#272)
* Commit the generated .pyi files This should simplify some of our tests, as well as allow external tools to run mypy on our repo (such as mypy_primer) * Black test_negative as well
1 parent ca0d7d3 commit ed129dc

29 files changed

+71
-110
lines changed

.gitattributes

-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
*.expected linguist-language=Python
21
test_negative/output.expected.2.7 linguist-generated=true
32
test_negative/output.expected.3.8 linguist-generated=true

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ jobs:
9595
- name: Run black
9696
run: |
9797
pip3 install black
98-
black --check mypy_protobuf/main.py test/
98+
black --check .
9999
100100
sanity_check_windows:
101101
name: Sanity Check Windows Executable

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ __pycache__/
88
/mypy_env/
99
*.pyc
1010
/test/generated/**/*.py
11-
/test/generated/**/*.pyi
1211
!/test/generated/**/__init__.py
1312
.pytest_cache
1413
/build/

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ Contributions to the implementation are welcome. Please run tests using `./run_t
196196
Ensure code is formatted using black.
197197
```
198198
pip3 install black
199-
black mypy_protobuf/main.py test/
199+
black .
200200
```
201201

202202
## Contributors

pyproject.toml

+3
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ requires = [
44
"wheel",
55
]
66
build-backend = "setuptools.build_meta"
7+
8+
[tool.black]
9+
extend-exclude = "(_pb2.pyi?$|_pb2_grpc.pyi?$)"

run_test.sh

+11-4
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ PY_VER_UNIT_TESTS="${PY_VER_UNIT_TESTS_3:=3.8.11} ${PY_VER_UNIT_TESTS_2:=2.7.18}
1212
PROTOC_ARGS="--proto_path=proto/ --experimental_allow_proto3_optional"
1313
GRPC_PROTOS=$(find proto/testproto/grpc -name "*.proto")
1414

15-
# Clean out generated/ directory - except for .generated / __init__.py
16-
find test/generated -type f -not \( -name "*.expected" -or -name "__init__.py" \) -delete
17-
1815
if [ -e $CUSTOM_TYPESHED_DIR ]; then
1916
export MYPYPATH=$CUSTOM_TYPESHED_DIR/stubs/protobuf
2017
fi
@@ -91,6 +88,11 @@ MYPY_PROTOBUF_VENV=venv_$PY_VER_MYPY_PROTOBUF
9188
exit 1
9289
fi
9390

91+
# CI Check to make sure generated files are committed
92+
SHA_BEFORE=$(find test/generated -name "*.pyi" | xargs sha1sum)
93+
# Clean out generated/ directory - except for __init__.py
94+
find test/generated -type f -not -name "__init__.py" -delete
95+
9496
# Compile protoc -> python
9597
$PROTOC $PROTOC_ARGS --python_out=test/generated `find proto -name "*.proto"`
9698

@@ -108,6 +110,11 @@ MYPY_PROTOBUF_VENV=venv_$PY_VER_MYPY_PROTOBUF
108110

109111
# Generate grpc protos
110112
$PROTOC $PROTOC_ARGS --mypy_grpc_out=test/generated $GRPC_PROTOS
113+
114+
if [[ -n $VALIDATE ]] && ! diff <(echo "$SHA_BEFORE") <(find test/generated -name "*.pyi" | xargs sha1sum); then
115+
echo -e "${RED}Some .pyi files did not match. Please commit those files${NC}"
116+
exit 1
117+
fi
111118
)
112119

113120
for PY_VER in $PY_VER_UNIT_TESTS; do
@@ -171,7 +178,7 @@ for PY_VER in $PY_VER_UNIT_TESTS; do
171178
)
172179

173180
(
174-
# Run unit tests. These tests generate .expected files
181+
# Run unit tests.
175182
source $UNIT_TESTS_VENV/bin/activate
176183
if [[ $PY_VER =~ ^2.* ]]; then IGNORE="--ignore=test/test_grpc_usage.py"; else IGNORE=""; fi
177184
PYTHONPATH=test/generated py.test --ignore=test/generated $IGNORE -v

test/generated/google/protobuf/empty_pb2.pyi.expected

-22
This file was deleted.

test/test_generated_mypy.py

+11-40
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
"""
2-
This file serves two purposes
3-
1) Run a test which ensures that mypy is producing the expected output. For
4-
developer convenience, in the case which it doesn't, it'll copy over the
5-
output to the expected output, so you can view the output diff in your
6-
code reviews. This will fail in CI if there is any inconsistency.
7-
8-
2) This is a file which should mypy with success. See test_negative for
2+
This is a file which should mypy with success. See test_negative for
93
a file that should have failures.
104
11-
Both of these tests are run by the run_test.sh script.
5+
This file contains a test to ensure that the test_negative failures
6+
are the expected failures
7+
8+
These tests can be set up and run by the run_test.sh script
129
"""
1310

1411
import glob
@@ -79,30 +76,6 @@ def _is_summary(l):
7976
return l.startswith("Found ") and l.endswith("source files)\n")
8077

8178

82-
def compare_pyi_to_expected(output_path):
83-
# type: (str) -> Optional[str]
84-
expected_path = output_path + ".expected"
85-
assert os.path.exists(output_path)
86-
87-
with open(output_path) as f:
88-
output_contents = f.read()
89-
90-
expected_contents = None # type: Optional[str]
91-
if os.path.exists(expected_path):
92-
with open(expected_path) as f:
93-
expected_contents = f.read()
94-
95-
if output_contents != expected_contents:
96-
with open(expected_path, "w") as f:
97-
f.write(output_contents)
98-
99-
return "{} doesn't match {}. This test will copy it over. Please rerun".format(
100-
output_path, expected_path
101-
)
102-
else:
103-
return None
104-
105-
10679
def test_generate_mypy_matches():
10780
# type: () -> None
10881
if sys.version_info < (3, 0):
@@ -129,18 +102,16 @@ def test_generate_mypy_matches():
129102

130103
output = os.path.join("test", "generated", *components)
131104

132-
failure_check_results.append(compare_pyi_to_expected(output))
105+
assert os.path.exists(output)
106+
failure_check_results.append(output)
133107
if "grpc" in components:
134108
grpc_output = output[:-4] + "_grpc.pyi"
135-
failure_check_results.append(compare_pyi_to_expected(grpc_output))
109+
assert os.path.exists(grpc_output)
110+
failure_check_results.append(grpc_output)
136111

137112
# Make sure we checked everything
138113
assert len(failure_check_results) == len(pyi_files)
139114

140-
failures = ["\n\t" + f for f in failure_check_results if f]
141-
if failures:
142-
raise Exception("".join(failures))
143-
144115

145116
def test_generate_negative_matches():
146117
# type: () -> None
@@ -176,8 +147,8 @@ def grab_expectations(filename, marker):
176147
assert errors_38 == expected_errors_38
177148

178149
# Some sanity checks to make sure we don't mess this up. Please update as necessary.
179-
assert len(errors_27) == 60
180-
assert len(errors_38) == 72
150+
assert len(errors_27) == 62
151+
assert len(errors_38) == 74
181152

182153

183154
def test_func():

test_negative/negative.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,11 @@
155155
s8.email_by_uid[55] = "[email protected]" # E:2.7 E:3.8
156156
s8.email_by_uid[UserId(55)] = "[email protected]" # E:2.7 E:3.8
157157
s8.email_by_uid[55] = Email("[email protected]") # E:2.7 E:3.8
158-
s8 = Simple1(user_id=55, email="[email protected]", email_by_uid={55: "[email protected]"}) # E:2.7 E:3.8
158+
s8 = Simple1(
159+
user_id=55, # E:2.7 E:3.8
160+
email="[email protected]", # E:2.7 E:3.8
161+
email_by_uid={55: "[email protected]"}, # E:2.7 E:3.8
162+
)
159163

160164
# Should not reexport inner.proto, since it doesn't have public tag.
161165
from testproto.reexport_pb2 import Inner # E:2.7 E:3.8

test_negative/negative_3.8.py

+21-21
Original file line numberDiff line numberDiff line change
@@ -50,58 +50,58 @@ def iter_requests() -> typing.Generator[DummyRequest, None, None]:
5050

5151
class GoodServicer(DummyServiceServicer):
5252
def UnaryUnary(
53-
self,
54-
request: DummyRequest,
55-
context: grpc.ServicerContext,
53+
self,
54+
request: DummyRequest,
55+
context: grpc.ServicerContext,
5656
) -> DummyReply:
5757
return DummyReply()
5858

5959
def UnaryStream(
60-
self,
61-
request: DummyRequest,
62-
context: grpc.ServicerContext,
60+
self,
61+
request: DummyRequest,
62+
context: grpc.ServicerContext,
6363
) -> typing.Iterator[DummyReply]:
6464
yield DummyReply()
6565

6666
def StreamUnary(
67-
self,
68-
request: typing.Iterator[DummyRequest],
69-
context: grpc.ServicerContext,
67+
self,
68+
request: typing.Iterator[DummyRequest],
69+
context: grpc.ServicerContext,
7070
) -> DummyReply:
7171
for data in request:
7272
pass
7373
return DummyReply()
7474

7575
def StreamStream(
76-
self,
77-
request: typing.Iterator[DummyRequest],
78-
context: grpc.ServicerContext,
76+
self,
77+
request: typing.Iterator[DummyRequest],
78+
context: grpc.ServicerContext,
7979
) -> typing.Iterator[DummyReply]:
8080
for data in request:
8181
yield DummyReply()
8282

8383

8484
class BadServicer(DummyServiceServicer):
8585
def UnaryUnary( # E:3.8
86-
self,
87-
request: typing.Iterator[DummyRequest],
88-
context: grpc.ServicerContext,
86+
self,
87+
request: typing.Iterator[DummyRequest],
88+
context: grpc.ServicerContext,
8989
) -> typing.Iterator[DummyReply]:
9090
for data in request:
9191
yield DummyReply()
9292

9393
def UnaryStream( # E:3.8
94-
self,
95-
request: typing.Iterator[DummyRequest],
96-
context: grpc.ServicerContext,
94+
self,
95+
request: typing.Iterator[DummyRequest],
96+
context: grpc.ServicerContext,
9797
) -> DummyReply:
9898
for data in request:
9999
pass
100100
return DummyReply()
101101

102102
def StreamUnary( # E:3.8
103-
self,
104-
request: DummyRequest,
105-
context: grpc.ServicerContext,
103+
self,
104+
request: DummyRequest,
105+
context: grpc.ServicerContext,
106106
) -> typing.Iterator[DummyReply]:
107107
yield DummyReply()

test_negative/output.expected.2.7

+9-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test_negative/output.expected.3.8

+9-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)