Example #1
0
File: cli.py Project: alex/invoke
    def core_help_option_prints_core_help(self):
        # TODO: change dynamically based on parser contents?
        # e.g. no core args == no [--core-opts],
        # no tasks == no task stuff?
        # NOTE: test will trigger default pty size of 80x24, so the below
        # string is formatted appropriately.
        # TODO: add more unit-y tests for specific behaviors:
        # * fill terminal w/ columns + spacing
        # * line-wrap help text in its own column
        expected = """
Usage: inv[oke] [--core-opts] task1 [--task1-opts] ... taskN [--taskN-opts]

Core options:
  --no-dedupe                      Disable task deduplication
  -c STRING, --collection=STRING   Specify collection name to load. May be
                                   given >1 time.
  -h, --help                       Show this help message and exit.
  -l, --list                       List available tasks.
  -r STRING, --root=STRING         Change root directory used for finding task
                                   modules.
  -V, --version                    Show version and exit

""".lstrip()
        r1 = run("inv -h", hide='out')
        r2 = run("inv --help", hide='out')
        eq_(r1.stdout, expected)
        eq_(r2.stdout, expected)
Example #2
0
 def ensure_deepcopy_works(self):
     lex = Lexicon()
     lex['foo'] = 'bar'
     eq_(lex.foo, 'bar')
     lex2 = copy.deepcopy(lex)
     lex2.foo = 'biz'
     assert lex2.foo != lex.foo
Example #3
0
 def globbed_shortflags_with_multipass_parsing(self):
     "mytask -cb and -bc"
     for args in ('-bc', '-cb'):
         _, _, r = parse(['mytask4', args], self.c)
         a = r[0].args
         eq_(a.clean.value, True)
         eq_(a.browse.value, True)
Example #4
0
 def positionalness_and_optionalness_stick_together(self):
     # TODO: but do these even make sense on the same argument? For now,
     # best to have a nonsensical test than a missing one...
     eq_(
         repr(Argument('name', optional=True, positional=True)),
         "<Argument: name *?>",
     )
Example #5
0
    def core_help_option_prints_core_help(self):
        # TODO: change dynamically based on parser contents?
        # e.g. no core args == no [--core-opts],
        # no tasks == no task stuff?
        # NOTE: test will trigger default pty size of 80x24, so the below
        # string is formatted appropriately.
        # TODO: add more unit-y tests for specific behaviors:
        # * fill terminal w/ columns + spacing
        # * line-wrap help text in its own column
        expected = """
Usage: inv[oke] [--core-opts] task1 [--task1-opts] ... taskN [--taskN-opts]

Core options:
  --no-dedupe                      Disable task deduplication.
  -c STRING, --collection=STRING   Specify collection name to load. May be
                                   given >1 time.
  -e, --echo                       Echo executed commands before running.
  -h [STRING], --help[=STRING]     Show core or per-task help and exit.
  -H STRING, --hide=STRING         Set default value of run()'s 'hide' kwarg.
  -l, --list                       List available tasks.
  -p, --pty                        Use a pty when executing shell commands.
  -r STRING, --root=STRING         Change root directory used for finding task
                                   modules.
  -V, --version                    Show version and exit.
  -w, --warn-only                  Warn, instead of failing, when shell
                                   commands fail.

""".lstrip()
        r1 = run("inv -h", hide='out')
        r2 = run("inv --help", hide='out')
        eq_(r1.stdout, expected)
        eq_(r2.stdout, expected)
Example #6
0
    def no_deduping(self):
        expected = """
foo
foo
bar
""".lstrip()
        eq_(run("invoke -c integration --no-dedupe foo bar").stdout, expected)
Example #7
0
 def multiple_short_flags_adjacent(self):
     "mytask -bv (and inverse)"
     for args in ('-bv', '-vb'):
         r = self._parse("mytask %s" % args)
         a = r[0].args
         eq_(a.b.value, True)
         eq_(a.v.value, True)
Example #8
0
 def subcollections_sorted_in_depth_order(self):
     expected = self._listing(
         'toplevel',
         'a.subtask',
         'a.nother.subtask',
     )
     eq_(run("invoke -c deeper_ns_list --list").stdout, expected)
Example #9
0
 def default_tasks(self):
     # sub-ns default task display as "real.name (collection name)"
     expected = self._listing(
         'top_level (othertop)',
         'sub.sub_task (sub, sub.othersub)',
     )
     eq_(run("invoke -c explicit_root --list").stdout, expected)
Example #10
0
 def always_includes_initial_context_if_one_was_given(self):
     # Even if no core/initial flags were seen
     t1 = Context('t1')
     init = Context()
     result = Parser((t1,), initial=init).parse_argv(['t1'])
     eq_(result[0].name, None)
     eq_(result[1].name, 't1')
Example #11
0
 def submodule_names_are_stripped_to_last_chunk(self):
     with support_path():
         from package import module
     c = Collection.from_module(module)
     eq_(module.__name__, 'package.module')
     eq_(c.name, 'module')
     assert 'mytask' in c # Sanity
Example #12
0
 def release_line_bugfix_specifier(self):
     b50 = _issue('bug', '50')
     b42 = _issue('bug', '42', line='1.1')
     f25 = _issue('feature', '25')
     b35 = _issue('bug', '35')
     b34 = _issue('bug', '34')
     f22 = _issue('feature', '22')
     b20 = _issue('bug', '20')
     c = _changelog2dict(_releases(
         '1.2.1', '1.1.2', '1.0.3',
         b50, b42,
         '1.2.0', '1.1.1', '1.0.2',
         f25, b35, b34,
         '1.1.0', '1.0.1',
         f22, b20
     ))
     for rel, issues in (
         ('1.0.1', [b20]),
         ('1.1.0', [f22]),
         ('1.0.2', [b34, b35]),
         ('1.1.1', [b34, b35]),
         ('1.2.0', [f25]),
         ('1.0.3', [b50]), # the crux - is not b50 + b42
         ('1.1.2', [b50, b42]),
         ('1.2.1', [b50, b42]),
     ):
         eq_(set(c[rel]), set(issues))
Example #13
0
 def arguments_which_take_values_get_defaults_overridden_correctly(self):
     args = (Argument('arg', kind=str), Argument('arg2', kind=int))
     c = Context('mytask', args=args)
     argv = ['mytask', '--arg', 'myval', '--arg2', '25']
     result = Parser((c,)).parse_argv(argv)
     eq_(result[0].args['arg'].value, 'myval')
     eq_(result[0].args['arg2'].value, 25)
Example #14
0
 def replaced_stdin_objects_dont_explode(self, mock_sys):
     # Replace sys.stdin with an object lacking .fileno(), which
     # normally causes an AttributeError unless we are being careful.
     mock_sys.stdin = object()
     # Test. If bug is present, this will error.
     runner = Local(Context())
     eq_(runner.should_use_pty(pty=True, fallback=True), False)
Example #15
0
 def searches_towards_root_of_filesystem(self):
     # Loaded while root is in same dir as .py
     directly = self.l.load('foo')
     # Loaded while root is multiple dirs deeper than the .py
     deep = os.path.join(support, 'ignoreme', 'ignoremetoo')
     indirectly = FSLoader(start=deep).load('foo')
     eq_(directly, indirectly)
Example #16
0
 def yaml_prevents_json_or_python(self):
     c = Config(
         system_prefix=join(CONFIGS_PATH, 'all-three', 'invoke'))
     ok_('json-only' not in c)
     ok_('python_only' not in c)
     ok_('yaml-only' in c)
     eq_(c.shared, 'yaml-value')
Example #17
0
 def return_code_in_result(self):
     """
     Result has .return_code (and .exited) containing exit code int
     """
     r = run(self.out, hide='both')
     eq_(r.return_code, 0)
     eq_(r.exited, 0)
Example #18
0
 def env_vars_override_project(self):
     os.environ['HOORAY'] = 'env'
     c = Config(
         project_home=join(CONFIGS_PATH, 'yaml'),
     )
     c.load_shell_env()
     eq_(c.hooray, 'env')
Example #19
0
 def env_vars_override_systemwide(self):
     os.environ['HOORAY'] = 'env'
     c = Config(
         system_prefix=join(CONFIGS_PATH, 'yaml', 'invoke'),
     )
     c.load_shell_env()
     eq_(c.hooray, 'env')
Example #20
0
 def non_spurious_OSErrors_bubble_up(self):
     try:
         self._run(_, pty=True)
     except ThreadException as e:
         e = e.exceptions[0]
         eq_(e.type, OSError)
         eq_(str(e.value), "wat")
Example #21
0
 def subkeys_get_merged_not_overwritten(self):
     # Ensures nested keys merge deeply instead of shallowly.
     defaults = {'foo': {'bar': 'baz'}}
     overrides = {'foo': {'notbar': 'notbaz'}}
     c = Config(defaults=defaults, overrides=overrides)
     eq_(c.foo.notbar, 'notbaz')
     eq_(c.foo.bar, 'baz')
Example #22
0
 def env_vars_override_user(self):
     os.environ['OUTER_INNER_HOORAY'] = 'env'
     c = Config(
         user_prefix=join(CONFIGS_PATH, 'yaml', 'invoke'),
     )
     c.load_shell_env()
     eq_(c.outer.inner.hooray, 'env')
Example #23
0
 def unsets_aliases(self):
     ad = AliasDict()
     ad['realkey'] = 'value'
     ad.alias('myalias', to='realkey')
     eq_(ad['myalias'], 'value')
     ad.unalias('myalias')
     assert 'myalias' not in ad
Example #24
0
 def can_clone_into_a_subclass(self):
     orig = Call(self.task)
     class MyCall(Call):
         pass
     clone = orig.clone(into=MyCall)
     eq_(clone, orig)
     ok_(isinstance(clone, MyCall))
Example #25
0
 def deletion_is_recursive(self):
     ad = self._recursive_aliases()
     del ad['alias2']
     assert 'realkey' not in ad
     ad['realkey'] = 'newvalue'
     assert 'alias1' in ad
     eq_(ad['alias1'], 'newvalue')
Example #26
0
 def ensure_deepcopy_works(self):
     ad = AttributeDict()
     ad['foo'] = 'bar'
     eq_(ad.foo, 'bar')
     ad2 = copy.deepcopy(ad)
     ad2.foo = 'biz'
     assert ad2.foo != ad.foo
Example #27
0
 def multiple_short_flags_adjacent(self):
     "mytask -bv (and inverse)"
     for args in ("-bv", "-vb"):
         r = self._parse("mytask {0}".format(args))
         a = r[0].args
         eq_(a.b.value, True)
         eq_(a.v.value, True)
Example #28
0
 def comparison_looks_at_merged_config(self):
     c1 = Config(defaults={'foo': {'bar': 'biz'}})
     # Empty defaults to suppress global_defaults
     c2 = Config(defaults={}, overrides={'foo': {'bar': 'biz'}})
     ok_(c1 is not c2)
     ok_(c1._defaults != c2._defaults)
     eq_(c1, c2)
Example #29
0
 def simple_command(self):
     group = Group('localhost', '127.0.0.1')
     result = group.run('echo foo', hide=True)
     eq_(
         [x.stdout.strip() for x in result.values()],
         ['foo', 'foo'],
     )
Example #30
0
 def release_line_bugfix_specifier(self):
     b50 = b(50)
     b42 = b(42, spec='1.1+')
     f25 = f(25)
     b35 = b(35)
     b34 = b(34)
     f22 = f(22)
     b20 = b(20)
     c = changelog2dict(releases(
         '1.2.1', '1.1.2', '1.0.3',
         b50, b42,
         '1.2.0', '1.1.1', '1.0.2',
         f25, b35, b34,
         '1.1.0', '1.0.1',
         f22, b20
     ))
     for rel, issues in (
         ('1.0.1', [b20]),
         ('1.1.0', [f22]),
         ('1.0.2', [b34, b35]),
         ('1.1.1', [b34, b35]),
         ('1.2.0', [f25]),
         ('1.0.3', [b50]), # the crux - is not b50 + b42
         ('1.1.2', [b50, b42]),
         ('1.2.1', [b50, b42]),
     ):
         eq_(set(c[rel]), set(issues))
Example #31
0
 def equals_sign_for_long_form_only(self):
     eq_(self.tasked.help_for('--myarg'),
         ("-m STRING, --myarg=STRING", ""))
Example #32
0
 def exposed_as_Lexicon(self):
     eq_(self.c.args.bar, self.c.args['bar'])
Example #33
0
 def repr_is_str(self):
     "__repr__ mirrors __str__"
     c = Context('foo')
     eq_(str(c), repr(c))
Example #34
0
 def args_show_as_repr(self):
     eq_(str(Context('bar', args=[Argument('arg1')])),
         "<Context 'bar': {'arg1': <Argument: arg1>}>")
Example #35
0
 def with_no_args_output_is_simple(self):
     eq_(str(Context('foo')), "<Context 'foo'>")
Example #36
0
 def _assert_order(self, name_tuples, expected_flag_order):
     ctx = Context(args=[Argument(names=x) for x in name_tuples])
     return eq_(ctx.help_tuples(),
                [ctx.help_for(x) for x in expected_flag_order])
Example #37
0
 def shortflag_inputs_work_too(self):
     eq_(self.tasked.help_for('-m'), self.tasked.help_for('--myarg'))
Example #38
0
 def task_driven_no_helpstr(self):
     eq_(self.tasked.help_for('--myarg'),
         ("-m STRING, --myarg=STRING", ""))
Example #39
0
 def vanilla_with_helpstr(self):
     eq_(self.vanilla.help_for('--bar'),
         ("--bar=STRING", "bar the baz"))
Example #40
0
 def short_form_before_long_form(self):
     eq_(self.tasked.help_for('--myarg'),
         ("-m STRING, --myarg=STRING", ""))
Example #41
0
 def includes_arguments(self):
     eq_(len(self.new.args), 1)
     assert self.new.args['--boolean'] is not self.arg
Example #42
0
 def task_driven_with_helpstr(self):
     eq_(self.tasked.help_for('--otherarg'),
         ("-o STRING, --otherarg=STRING", "other help"))
Example #43
0
 def positional_arg_modifications_affect_args_copy(self):
     self.c.add_arg(name='hrm', positional=True)
     eq_(self.c.args['hrm'].value, self.c.positional_args[0].value)
     self.c.positional_args[0].value = 17
     eq_(self.c.args['hrm'].value, self.c.positional_args[0].value)
Example #44
0
 def vanilla_no_helpstr(self):
     eq_(self.vanilla.help_for('--foo'), ("--foo=STRING", ""))
Example #45
0
 def positional_args_filled_in_order(self):
     self.c.add_arg(name='pos1', positional=True)
     eq_(self.c.positional_args[0].name, 'pos1')
     self.c.add_arg(name='abc', positional=True)
     eq_(self.c.positional_args[1].name, 'abc')
Example #46
0
 def returns_correct_copy(self):
     assert self.new is not self.orig
     eq_(self.new.name, 'mytask')
     assert 'othername' in self.new.aliases
Example #47
0
 def adds_positional_args_to_positional_args(self):
     self.c.add_arg(name='pos', positional=True)
     eq_(self.c.positional_args[0].name, 'pos')
Example #48
0
 def may_have_a_name(self):
     c = Context(name='taskname')
     eq_(c.name, 'taskname')
Example #49
0
 def warn_kwarg_allows_continuing_past_failures(self):
     eq_(run("false", warn=True).exited, 1)
Example #50
0
 def positional_args_empty_when_none_given(self):
     eq_(len(self.c.positional_args), 0)
Example #51
0
 def failed_attr_indicates_failure(self):
     eq_(_run().failed, False)
     eq_(_run(returns={'exited': 1}, warn=True).failed, True)
Example #52
0
 def _hide_both(self, val):
     run(self.both, hide=val)
     eq_(sys.stdall.getvalue(), "")
Example #53
0
 def stderr_attribute_contains_stderr(self):
     eq_(run(self.err, hide='both').stderr, 'bar\n')
Example #54
0
 def has_exception_attr(self):
     eq_(_run().exception, None)
Example #55
0
 def nonzero_return_code_for_failures(self):
     result = run("false", warn=True)
     eq_(result.exited, 1)
     result = run("goobypls", warn=True, hide='both')
     eq_(result.exited, 127)
Example #56
0
 def ok_attr_indicates_success(self):
     eq_(_run().ok, True)
     eq_(_run(returns={'exited': 1}, warn=True).ok, False)
Example #57
0
 def stdout_contains_both_streams_under_pty(self):
     r = run(self.both, hide='both', pty=True)
     eq_(r.stdout, 'foo\r\nbar\r\n')
Example #58
0
 def stdout_attribute_contains_stdout(self):
     eq_(run(self.out, hide='both').stdout, 'foo\n')
Example #59
0
 def when_echo_True_commands_echoed_in_bold(self):
     run("echo hi", echo=True)
     expected = "\033[1;37mecho hi\033[0m\nhi"
     eq_(sys.stdout.getvalue().strip(), expected)
Example #60
0
 def stderr_is_empty_under_pty(self):
     r = run(self.both, hide='both', pty=True)
     eq_(r.stderr, '')