File: main.py

package info (click to toggle)
python-invoke 1.4.1%2Bds-0.1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,704 kB
  • sloc: python: 11,377; makefile: 18; sh: 12
file content (183 lines) | stat: -rw-r--r-- 6,051 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import io
import os
import sys

from pytest import skip
from pytest_relaxed import trap

from invoke.util import six

from invoke import run
from invoke._version import __version__
from invoke.terminals import WINDOWS

from _util import only_utf8


def _output_eq(cmd, expected):
    assert run(cmd, hide=True).stdout == expected


def _setup(self):
    self.cwd = os.getcwd()
    # Enter integration/ so Invoke loads its local tasks.py
    os.chdir(os.path.dirname(__file__))


class Main:
    def setup(self):
        # MEH
        _setup(self)

    def teardown(self):
        os.chdir(self.cwd)

    class basics:
        @trap
        def basic_invocation(self):
            _output_eq("invoke print-foo", "foo\n")

        @trap
        def version_output(self):
            _output_eq("invoke --version", "Invoke {}\n".format(__version__))

        @trap
        def help_output(self):
            assert "Usage: inv[oke] " in run("invoke --help").stdout

        @trap
        def per_task_help(self):
            assert "Frobazz" in run("invoke -c _explicit foo --help").stdout

        @trap
        def shorthand_binary_name(self):
            _output_eq("inv print-foo", "foo\n")

        @trap
        def explicit_task_module(self):
            _output_eq("inv --collection _explicit foo", "Yup\n")

        @trap
        def invocation_with_args(self):
            _output_eq("inv print-name --name whatevs", "whatevs\n")

        @trap
        def bad_collection_exits_nonzero(self):
            result = run("inv -c nope -l", warn=True)
            assert result.exited == 1
            assert not result.stdout
            assert result.stderr

        def loads_real_user_config(self):
            path = os.path.expanduser("~/.invoke.yaml")
            try:
                with open(path, "w") as fd:
                    fd.write("foo: bar")
                _output_eq("inv print-config", "bar\n")
            finally:
                try:
                    os.unlink(path)
                except OSError:
                    pass

        @trap
        def invocable_via_python_dash_m(self):
            # TODO: replace with pytest marker after pytest port
            if sys.version_info < (2, 7):
                skip()
            _output_eq(
                "python -m invoke print-name --name mainline", "mainline\n"
            )

    class funky_characters_in_stdout:
        def setup(self):
            class BadlyBehavedStdout(io.TextIOBase):
                def write(self, data):
                    if six.PY2 and not isinstance(data, six.binary_type):
                        data.encode("ascii")

            self.bad_stdout = BadlyBehavedStdout()
            # Mehhh at 'subclassing' via inner classes =/
            _setup(self)

        @only_utf8
        def basic_nonstandard_characters(self):
            os.chdir("_support")
            # Crummy "doesn't explode with decode errors" test
            cmd = ("type" if WINDOWS else "cat") + " tree.out"
            run(cmd, hide="stderr", out_stream=self.bad_stdout)

        @only_utf8
        def nonprinting_bytes(self):
            # Seriously non-printing characters (i.e. non UTF8) also don't
            # asplode (they would print as escapes normally, but still)
            run("echo '\xff'", hide="stderr", out_stream=self.bad_stdout)

        @only_utf8
        def nonprinting_bytes_pty(self):
            if WINDOWS:
                return
            # PTY use adds another utf-8 decode spot which can also fail.
            run(
                "echo '\xff'",
                pty=True,
                hide="stderr",
                out_stream=self.bad_stdout,
            )

    class ptys:
        def complex_nesting_under_ptys_doesnt_break(self):
            if WINDOWS:  # Not sure how to make this work on Windows
                return
            # GH issue 191
            substr = "      hello\t\t\nworld with spaces"
            cmd = """ eval 'echo "{}" ' """.format(substr)
            expected = "      hello\t\t\r\nworld with spaces\r\n"
            assert run(cmd, pty=True, hide="both").stdout == expected

        def pty_puts_both_streams_in_stdout(self):
            if WINDOWS:
                return
            os.chdir("_support")
            err_echo = "{} err.py".format(sys.executable)
            command = "echo foo && {} bar".format(err_echo)
            r = run(command, hide="both", pty=True)
            assert r.stdout == "foo\r\nbar\r\n"
            assert r.stderr == ""

        def simple_command_with_pty(self):
            """
            Run command under PTY
            """
            # Most Unix systems should have stty, which asplodes when not run
            # under a pty, and prints useful info otherwise
            result = run("stty -a", hide=True, pty=True)
            # PTYs use \r\n, not \n, line separation
            assert "\r\n" in result.stdout
            assert result.pty is True

        def pty_size_is_realistic(self):
            # When we don't explicitly set pty size, 'stty size' sees it as
            # 0x0.
            # When we do set it, it should be some non 0x0, non 80x24 (the
            # default) value. (yes, this means it fails if you really do have
            # an 80x24 terminal. but who does that?)
            size = run("stty size", hide=True, pty=True).stdout.strip()
            assert size != ""
            assert size != "0 0"
            assert size != "24 80"

    class parsing:
        def false_as_optional_arg_default_value_works_okay(self):
            # (Dis)proves #416. When bug present, parser gets very confused,
            # asks "what the hell is 'whee'?". See also a unit test for
            # Task.get_arguments.
            os.chdir("_support")
            for argstr, expected in (
                ("", "False"),
                ("--meh", "True"),
                ("--meh=whee", "whee"),
            ):
                _output_eq(
                    "inv -c parsing foo {}".format(argstr), expected + "\n"
                )