Skip to content

Commit 0124f7e

Browse files
committed
Merge branch '906-int'
2 parents 4a48966 + e01da1a commit 0124f7e

File tree

8 files changed

+35
-31
lines changed

8 files changed

+35
-31
lines changed

.circleci/config.yml

+11
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ jobs:
3535
- run: inv www.doctest
3636
- orb/debug
3737

38+
typecheck:
39+
executor:
40+
name: orb/default
41+
version: "3.6"
42+
steps:
43+
- orb/setup
44+
- run: mypy .
45+
- orb/debug
46+
3847

3948
workflows:
4049
main:
@@ -43,6 +52,8 @@ workflows:
4352
name: Lint
4453
- orb/format:
4554
name: Style check
55+
- typecheck:
56+
name: Types check
4657
- coverage:
4758
name: Test
4859
- regression:

dev-requirements.txt

-1
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,4 @@ setuptools>56
2121
icecream>=2.1
2222
# typing
2323
mypy==0.971
24-
typed-ast==1.5.4
2524
types-PyYAML==6.0.12.4
File renamed without changes.

integration/main.py

+6-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
from pathlib import Path
23
import sys
34

45
import pytest
@@ -15,18 +16,13 @@ def _output_eq(cmd, expected):
1516
assert run(cmd, hide=True).stdout == expected
1617

1718

18-
def _setup(self):
19-
self.cwd = os.getcwd()
20-
# Enter integration/ so Invoke loads its local tasks.py
21-
os.chdir(os.path.dirname(__file__))
22-
23-
2419
class Main:
25-
def setup(self):
26-
# MEH
27-
_setup(self)
20+
def setup_method(self):
21+
self.cwd = os.getcwd()
22+
# Enter integration/_support as all support files are in there now
23+
os.chdir(Path(__file__).parent / "_support")
2824

29-
def teardown(self):
25+
def teardown_method(self):
3026
os.chdir(self.cwd)
3127

3228
class basics:
@@ -86,7 +82,6 @@ def invocable_via_python_dash_m(self):
8682
class funky_characters_in_stdout:
8783
@only_utf8
8884
def basic_nonstandard_characters(self):
89-
os.chdir("_support")
9085
# Crummy "doesn't explode with decode errors" test
9186
cmd = ("type" if WINDOWS else "cat") + " tree.out"
9287
run(cmd, hide="stderr")
@@ -117,7 +112,6 @@ def complex_nesting_under_ptys_doesnt_break(self):
117112
def pty_puts_both_streams_in_stdout(self):
118113
if WINDOWS:
119114
return
120-
os.chdir("_support")
121115
err_echo = "{} err.py".format(sys.executable)
122116
command = "echo foo && {} bar".format(err_echo)
123117
r = run(command, hide="both", pty=True)
@@ -152,7 +146,6 @@ def false_as_optional_arg_default_value_works_okay(self):
152146
# (Dis)proves #416. When bug present, parser gets very confused,
153147
# asks "what the hell is 'whee'?". See also a unit test for
154148
# Task.get_arguments.
155-
os.chdir("_support")
156149
for argstr, expected in (
157150
("", "False"),
158151
("--meh", "True"),

invoke/runners.py

+16-11
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
Optional,
2020
Tuple,
2121
Type,
22-
Union,
2322
)
2423

2524
# Import some platform-specific things at top level so they can be mocked for
@@ -1075,7 +1074,7 @@ def start_timer(self, timeout: int) -> None:
10751074
self._timer = threading.Timer(timeout, self.kill)
10761075
self._timer.start()
10771076

1078-
def read_proc_stdout(self, num_bytes: int) -> Union[bytes, str, None]:
1077+
def read_proc_stdout(self, num_bytes: int) -> Optional[bytes]:
10791078
"""
10801079
Read ``num_bytes`` from the running process' stdout stream.
10811080
@@ -1087,7 +1086,7 @@ def read_proc_stdout(self, num_bytes: int) -> Union[bytes, str, None]:
10871086
"""
10881087
raise NotImplementedError
10891088

1090-
def read_proc_stderr(self, num_bytes: int) -> Union[bytes, str, None]:
1089+
def read_proc_stderr(self, num_bytes: int) -> Optional[bytes]:
10911090
"""
10921091
Read ``num_bytes`` from the running process' stderr stream.
10931092
@@ -1154,11 +1153,13 @@ def send_interrupt(self, interrupt: "KeyboardInterrupt") -> None:
11541153
"""
11551154
self.write_proc_stdin("\x03")
11561155

1157-
def returncode(self) -> int:
1156+
def returncode(self) -> Optional[int]:
11581157
"""
11591158
Return the numeric return/exit code resulting from command execution.
11601159
1161-
:returns: `int`
1160+
:returns:
1161+
`int`, if any reasonable return code could be determined, or
1162+
``None`` in corner cases where that was not possible.
11621163
11631164
.. versionadded:: 1.0
11641165
"""
@@ -1238,7 +1239,7 @@ def should_use_pty(self, pty: bool = False, fallback: bool = True) -> bool:
12381239
use_pty = False
12391240
return use_pty
12401241

1241-
def read_proc_stdout(self, num_bytes: int) -> Union[bytes, str, None]:
1242+
def read_proc_stdout(self, num_bytes: int) -> Optional[bytes]:
12421243
# Obtain useful read-some-bytes function
12431244
if self.using_pty:
12441245
# Need to handle spurious OSErrors on some Linux platforms.
@@ -1265,7 +1266,7 @@ def read_proc_stdout(self, num_bytes: int) -> Union[bytes, str, None]:
12651266
data = None
12661267
return data
12671268

1268-
def read_proc_stderr(self, num_bytes: int) -> Union[bytes, str, None]:
1269+
def read_proc_stderr(self, num_bytes: int) -> Optional[bytes]:
12691270
# NOTE: when using a pty, this will never be called.
12701271
# TODO: do we ever get those OSErrors on stderr? Feels like we could?
12711272
if self.process and self.process.stderr:
@@ -1280,7 +1281,9 @@ def _write_proc_stdin(self, data: bytes) -> None:
12801281
elif self.process and self.process.stdin:
12811282
fd = self.process.stdin.fileno()
12821283
else:
1283-
raise SubprocessPipeError("No stdin process exists")
1284+
raise SubprocessPipeError(
1285+
"Unable to write to missing subprocess or stdin!"
1286+
)
12841287
# Try to write, ignoring broken pipes if encountered (implies child
12851288
# process exited before the process piping stdin to us finished;
12861289
# there's nothing we can do about that!)
@@ -1298,7 +1301,9 @@ def close_proc_stdin(self) -> None:
12981301
elif self.process and self.process.stdin:
12991302
self.process.stdin.close()
13001303
else:
1301-
raise SubprocessPipeError("No stdin process exists")
1304+
raise SubprocessPipeError(
1305+
"Unable to close missing subprocess or stdin!"
1306+
)
13021307

13031308
def start(self, command: str, shell: str, env: Dict[str, Any]) -> None:
13041309
if self.using_pty:
@@ -1358,15 +1363,15 @@ def process_is_finished(self) -> bool:
13581363
else:
13591364
return self.process.poll() is not None
13601365

1361-
def returncode(self) -> int:
1366+
def returncode(self) -> Optional[int]:
13621367
if self.using_pty:
13631368
# No subprocess.returncode available; use WIFEXITED/WIFSIGNALED to
13641369
# determine whch of WEXITSTATUS / WTERMSIG to use.
13651370
# TODO: is it safe to just say "call all WEXITSTATUS/WTERMSIG and
13661371
# return whichever one of them is nondefault"? Probably not?
13671372
# NOTE: doing this in an arbitrary order should be safe since only
13681373
# one of the WIF* methods ought to ever return True.
1369-
code = 0
1374+
code = None
13701375
if os.WIFEXITED(self.status):
13711376
code = os.WEXITSTATUS(self.status)
13721377
elif os.WIFSIGNALED(self.status):

invoke/tasks.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ class Task(Generic[T]):
5959
def __init__(
6060
self,
6161
body: Callable,
62-
/,
6362
name: Optional[str] = None,
6463
aliases: Iterable[str] = (),
6564
positional: Optional[Iterable[str]] = None,
@@ -484,7 +483,7 @@ def clone(
484483
return klass(**data)
485484

486485

487-
def call(task: "Task", /, *args: Any, **kwargs: Any) -> "Call":
486+
def call(task: "Task", *args: Any, **kwargs: Any) -> "Call":
488487
"""
489488
Describes execution of a `.Task`, typically with pre-supplied arguments.
490489

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ disallow_untyped_defs = true
1616
# "unused-awaitable",
1717
#
1818
exclude = [
19-
"integration/", "tests/", "setup.py", "sites/www/conf.py"
19+
"integration/", "tests/", "setup.py", "sites/www/conf.py", "build/",
2020
]
2121
ignore_missing_imports = true
2222
# implicit_reexport = False

tasks.py

-3
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ def test(
5151
)
5252

5353

54-
print('test', vars(test), type(test))
55-
56-
5754
# TODO: replace with invocations' once the "call truly local tester" problem is
5855
# solved (see other TODOs). For now this is just a copy/paste/modify.
5956
@task(help=test.help) # type: ignore

0 commit comments

Comments
 (0)