How to use passenv method in tox

Best Python code snippet using tox_python

test_config.py

Source:test_config.py Github

copy

Full Screen

1import sys2from textwrap import dedent3import py4import pytest5import tox6import tox.config7from tox.config import * # noqa8from tox.venv import VirtualEnv9class TestVenvConfig:10 def test_config_parsing_minimal(self, tmpdir, newconfig):11 config = newconfig([], """12 [testenv:py1]13 """)14 assert len(config.envconfigs) == 115 assert config.toxworkdir.realpath() == tmpdir.join(".tox").realpath()16 assert config.envconfigs['py1'].basepython == sys.executable17 assert config.envconfigs['py1'].deps == []18 assert config.envconfigs['py1'].platform == ".*"19 def test_config_parsing_multienv(self, tmpdir, newconfig):20 config = newconfig([], """21 [tox]22 toxworkdir = %s23 indexserver =24 xyz = xyz_repo25 [testenv:py1]26 deps=hello27 [testenv:py2]28 deps=29 world130 :xyz:http://hello/world31 """ % (tmpdir, ))32 assert config.toxworkdir == tmpdir33 assert len(config.envconfigs) == 234 assert config.envconfigs['py1'].envdir == tmpdir.join("py1")35 dep = config.envconfigs['py1'].deps[0]36 assert dep.name == "hello"37 assert dep.indexserver is None38 assert config.envconfigs['py2'].envdir == tmpdir.join("py2")39 dep1, dep2 = config.envconfigs['py2'].deps40 assert dep1.name == "world1"41 assert dep2.name == "http://hello/world"42 assert dep2.indexserver.name == "xyz"43 assert dep2.indexserver.url == "xyz_repo"44 def test_envdir_set_manually(self, tmpdir, newconfig):45 config = newconfig([], """46 [testenv:devenv]47 envdir = devenv48 """)49 envconfig = config.envconfigs['devenv']50 assert envconfig.envdir == tmpdir.join('devenv')51 def test_envdir_set_manually_with_substitutions(self, tmpdir, newconfig):52 config = newconfig([], """53 [testenv:devenv]54 envdir = {toxworkdir}/foobar55 """)56 envconfig = config.envconfigs['devenv']57 assert envconfig.envdir == config.toxworkdir.join('foobar')58 def test_force_dep_version(self, initproj):59 """60 Make sure we can override dependencies configured in tox.ini when using the command line61 option --force-dep.62 """63 initproj("example123-0.5", filedefs={64 'tox.ini': '''65 [tox]66 [testenv]67 deps=68 dep1==1.069 dep2>=2.070 dep371 dep4==4.072 '''73 })74 config = parseconfig(75 ['--force-dep=dep1==1.5', '--force-dep=dep2==2.1',76 '--force-dep=dep3==3.0'])77 assert config.option.force_dep == [78 'dep1==1.5', 'dep2==2.1', 'dep3==3.0']79 assert [str(x) for x in config.envconfigs['python'].deps] == [80 'dep1==1.5', 'dep2==2.1', 'dep3==3.0', 'dep4==4.0',81 ]82 def test_force_dep_with_url(self, initproj):83 initproj("example123-0.5", filedefs={84 'tox.ini': '''85 [tox]86 [testenv]87 deps=88 dep1==1.089 https://pypi.python.org/xyz/pkg1.tar.gz90 '''91 })92 config = parseconfig(93 ['--force-dep=dep1==1.5'])94 assert config.option.force_dep == [95 'dep1==1.5'96 ]97 assert [str(x) for x in config.envconfigs['python'].deps] == [98 'dep1==1.5', 'https://pypi.python.org/xyz/pkg1.tar.gz'99 ]100 def test_is_same_dep(self):101 """102 Ensure correct parseini._is_same_dep is working with a few samples.103 """104 assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3')105 assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3>=2.0')106 assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3>2.0')107 assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3<2.0')108 assert DepOption._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3<=2.0')109 assert not DepOption._is_same_dep('pkg_hello-world3==1.0', 'otherpkg>=2.0')110class TestConfigPlatform:111 def test_config_parse_platform(self, newconfig):112 config = newconfig([], """113 [testenv:py1]114 platform = linux2115 """)116 assert len(config.envconfigs) == 1117 assert config.envconfigs['py1'].platform == "linux2"118 def test_config_parse_platform_rex(self, newconfig, mocksession, monkeypatch):119 config = newconfig([], """120 [testenv:py1]121 platform = a123|b123122 """)123 assert len(config.envconfigs) == 1124 envconfig = config.envconfigs['py1']125 venv = VirtualEnv(envconfig, session=mocksession)126 assert not venv.matching_platform()127 monkeypatch.setattr(sys, "platform", "a123")128 assert venv.matching_platform()129 monkeypatch.setattr(sys, "platform", "b123")130 assert venv.matching_platform()131 monkeypatch.undo()132 assert not venv.matching_platform()133 @pytest.mark.parametrize("plat", ["win", "lin", ])134 def test_config_parse_platform_with_factors(self, newconfig, plat, monkeypatch):135 monkeypatch.setattr(sys, "platform", "win32")136 config = newconfig([], """137 [tox]138 envlist = py27-{win,lin,osx}139 [testenv]140 platform =141 win: win32142 lin: linux2143 """)144 assert len(config.envconfigs) == 3145 platform = config.envconfigs['py27-' + plat].platform146 expected = {"win": "win32", "lin": "linux2"}.get(plat)147 assert platform == expected148class TestConfigPackage:149 def test_defaults(self, tmpdir, newconfig):150 config = newconfig([], "")151 assert config.setupdir.realpath() == tmpdir.realpath()152 assert config.toxworkdir.realpath() == tmpdir.join(".tox").realpath()153 envconfig = config.envconfigs['python']154 assert envconfig.args_are_paths155 assert not envconfig.recreate156 assert not envconfig.pip_pre157 def test_defaults_distshare(self, tmpdir, newconfig):158 config = newconfig([], "")159 assert config.distshare == config.homedir.join(".tox", "distshare")160 def test_defaults_changed_dir(self, tmpdir, newconfig):161 tmpdir.mkdir("abc").chdir()162 config = newconfig([], "")163 assert config.setupdir.realpath() == tmpdir.realpath()164 assert config.toxworkdir.realpath() == tmpdir.join(".tox").realpath()165 def test_project_paths(self, tmpdir, newconfig):166 config = newconfig("""167 [tox]168 toxworkdir=%s169 """ % tmpdir)170 assert config.toxworkdir == tmpdir171class TestParseconfig:172 def test_search_parents(self, tmpdir):173 b = tmpdir.mkdir("a").mkdir("b")174 toxinipath = tmpdir.ensure("tox.ini")175 old = b.chdir()176 try:177 config = parseconfig([])178 finally:179 old.chdir()180 assert config.toxinipath == toxinipath181def test_get_homedir(monkeypatch):182 monkeypatch.setattr(py.path.local, "_gethomedir",183 classmethod(lambda x: {}[1]))184 assert not get_homedir()185 monkeypatch.setattr(py.path.local, "_gethomedir",186 classmethod(lambda x: 0 / 0))187 assert not get_homedir()188 monkeypatch.setattr(py.path.local, "_gethomedir",189 classmethod(lambda x: "123"))190 assert get_homedir() == "123"191class TestGetcontextname:192 def test_blank(self, monkeypatch):193 monkeypatch.setattr(os, "environ", {})194 assert getcontextname() is None195 def test_jenkins(self, monkeypatch):196 monkeypatch.setattr(os, "environ", {"JENKINS_URL": "xyz"})197 assert getcontextname() == "jenkins"198 def test_hudson_legacy(self, monkeypatch):199 monkeypatch.setattr(os, "environ", {"HUDSON_URL": "xyz"})200 assert getcontextname() == "jenkins"201class TestIniParserAgainstCommandsKey:202 """Test parsing commands with substitutions"""203 def test_command_substitution_from_other_section(self, newconfig):204 config = newconfig("""205 [section]206 key = whatever207 [testenv]208 commands =209 echo {[section]key}210 """)211 reader = SectionReader("testenv", config._cfg)212 x = reader.getargvlist("commands")213 assert x == [["echo", "whatever"]]214 def test_command_substitution_from_other_section_multiline(self, newconfig):215 """Ensure referenced multiline commands form from other section injected216 as multiple commands."""217 config = newconfig("""218 [section]219 commands =220 cmd1 param11 param12221 # comment is omitted222 cmd2 param21 \223 param22224 [base]225 commands = cmd 1 \226 2 3 4227 cmd 2228 [testenv]229 commands =230 {[section]commands}231 {[section]commands}232 # comment is omitted233 echo {[base]commands}234 """)235 reader = SectionReader("testenv", config._cfg)236 x = reader.getargvlist("commands")237 assert x == [238 "cmd1 param11 param12".split(),239 "cmd2 param21 param22".split(),240 "cmd1 param11 param12".split(),241 "cmd2 param21 param22".split(),242 ["echo", "cmd", "1", "2", "3", "4", "cmd", "2"],243 ]244 def test_command_substitution_from_other_section_posargs(self, newconfig):245 """Ensure subsitition from other section with posargs succeeds"""246 config = newconfig("""247 [section]248 key = thing {posargs} arg2249 [testenv]250 commands =251 {[section]key}252 """)253 reader = SectionReader("testenv", config._cfg)254 reader.addsubstitutions([r"argpos"])255 x = reader.getargvlist("commands")256 assert x == [['thing', 'argpos', 'arg2']]257 def test_command_section_and_posargs_substitution(self, newconfig):258 """Ensure subsitition from other section with posargs succeeds"""259 config = newconfig("""260 [section]261 key = thing arg1262 [testenv]263 commands =264 {[section]key} {posargs} endarg265 """)266 reader = SectionReader("testenv", config._cfg)267 reader.addsubstitutions([r"argpos"])268 x = reader.getargvlist("commands")269 assert x == [['thing', 'arg1', 'argpos', 'endarg']]270 def test_command_env_substitution(self, newconfig):271 """Ensure referenced {env:key:default} values are substituted correctly."""272 config = newconfig("""273 [testenv:py27]274 setenv =275 TEST=testvalue276 commands =277 ls {env:TEST}278 """)279 envconfig = config.envconfigs["py27"]280 assert envconfig.commands == [["ls", "testvalue"]]281 assert envconfig.setenv["TEST"] == "testvalue"282class TestIniParser:283 def test_getstring_single(self, tmpdir, newconfig):284 config = newconfig("""285 [section]286 key=value287 """)288 reader = SectionReader("section", config._cfg)289 x = reader.getstring("key")290 assert x == "value"291 assert not reader.getstring("hello")292 x = reader.getstring("hello", "world")293 assert x == "world"294 def test_missing_substitution(self, tmpdir, newconfig):295 config = newconfig("""296 [mydefault]297 key2={xyz}298 """)299 reader = SectionReader("mydefault", config._cfg, fallbacksections=['mydefault'])300 assert reader is not None301 with py.test.raises(tox.exception.ConfigError):302 reader.getstring("key2")303 def test_getstring_fallback_sections(self, tmpdir, newconfig):304 config = newconfig("""305 [mydefault]306 key2=value2307 [section]308 key=value309 """)310 reader = SectionReader("section", config._cfg, fallbacksections=['mydefault'])311 x = reader.getstring("key2")312 assert x == "value2"313 x = reader.getstring("key3")314 assert not x315 x = reader.getstring("key3", "world")316 assert x == "world"317 def test_getstring_substitution(self, tmpdir, newconfig):318 config = newconfig("""319 [mydefault]320 key2={value2}321 [section]322 key={value}323 """)324 reader = SectionReader("section", config._cfg, fallbacksections=['mydefault'])325 reader.addsubstitutions(value="newvalue", value2="newvalue2")326 x = reader.getstring("key2")327 assert x == "newvalue2"328 x = reader.getstring("key3")329 assert not x330 x = reader.getstring("key3", "{value2}")331 assert x == "newvalue2"332 def test_getlist(self, tmpdir, newconfig):333 config = newconfig("""334 [section]335 key2=336 item1337 {item2}338 """)339 reader = SectionReader("section", config._cfg)340 reader.addsubstitutions(item1="not", item2="grr")341 x = reader.getlist("key2")342 assert x == ['item1', 'grr']343 def test_getdict(self, tmpdir, newconfig):344 config = newconfig("""345 [section]346 key2=347 key1=item1348 key2={item2}349 """)350 reader = SectionReader("section", config._cfg)351 reader.addsubstitutions(item1="not", item2="grr")352 x = reader.getdict("key2")353 assert 'key1' in x354 assert 'key2' in x355 assert x['key1'] == 'item1'356 assert x['key2'] == 'grr'357 x = reader.getdict("key3", {1: 2})358 assert x == {1: 2}359 def test_getstring_environment_substitution(self, monkeypatch, newconfig):360 monkeypatch.setenv("KEY1", "hello")361 config = newconfig("""362 [section]363 key1={env:KEY1}364 key2={env:KEY2}365 """)366 reader = SectionReader("section", config._cfg)367 x = reader.getstring("key1")368 assert x == "hello"369 with py.test.raises(tox.exception.ConfigError):370 reader.getstring("key2")371 def test_getstring_environment_substitution_with_default(self, monkeypatch, newconfig):372 monkeypatch.setenv("KEY1", "hello")373 config = newconfig("""374 [section]375 key1={env:KEY1:DEFAULT_VALUE}376 key2={env:KEY2:DEFAULT_VALUE}377 key3={env:KEY3:}378 """)379 reader = SectionReader("section", config._cfg)380 x = reader.getstring("key1")381 assert x == "hello"382 x = reader.getstring("key2")383 assert x == "DEFAULT_VALUE"384 x = reader.getstring("key3")385 assert x == ""386 def test_value_matches_section_substituion(self):387 assert is_section_substitution("{[setup]commands}")388 def test_value_doesn_match_section_substitution(self):389 assert is_section_substitution("{[ ]commands}") is None390 assert is_section_substitution("{[setup]}") is None391 assert is_section_substitution("{[setup] commands}") is None392 def test_getstring_other_section_substitution(self, newconfig):393 config = newconfig("""394 [section]395 key = rue396 [testenv]397 key = t{[section]key}398 """)399 reader = SectionReader("testenv", config._cfg)400 x = reader.getstring("key")401 assert x == "true"402 def test_argvlist(self, tmpdir, newconfig):403 config = newconfig("""404 [section]405 key2=406 cmd1 {item1} {item2}407 cmd2 {item2}408 """)409 reader = SectionReader("section", config._cfg)410 reader.addsubstitutions(item1="with space", item2="grr")411 # py.test.raises(tox.exception.ConfigError,412 # "reader.getargvlist('key1')")413 assert reader.getargvlist('key1') == []414 x = reader.getargvlist("key2")415 assert x == [["cmd1", "with", "space", "grr"],416 ["cmd2", "grr"]]417 def test_argvlist_windows_escaping(self, tmpdir, newconfig):418 config = newconfig("""419 [section]420 comm = py.test {posargs}421 """)422 reader = SectionReader("section", config._cfg)423 reader.addsubstitutions([r"hello\this"])424 argv = reader.getargv("comm")425 assert argv == ["py.test", "hello\\this"]426 def test_argvlist_multiline(self, tmpdir, newconfig):427 config = newconfig("""428 [section]429 key2=430 cmd1 {item1} \431 {item2}432 """)433 reader = SectionReader("section", config._cfg)434 reader.addsubstitutions(item1="with space", item2="grr")435 # py.test.raises(tox.exception.ConfigError,436 # "reader.getargvlist('key1')")437 assert reader.getargvlist('key1') == []438 x = reader.getargvlist("key2")439 assert x == [["cmd1", "with", "space", "grr"]]440 def test_argvlist_quoting_in_command(self, tmpdir, newconfig):441 config = newconfig("""442 [section]443 key1=444 cmd1 'part one' \445 'part two'446 """)447 reader = SectionReader("section", config._cfg)448 x = reader.getargvlist("key1")449 assert x == [["cmd1", "part one", "part two"]]450 def test_argvlist_comment_after_command(self, tmpdir, newconfig):451 config = newconfig("""452 [section]453 key1=454 cmd1 --flag # run the flag on the command455 """)456 reader = SectionReader("section", config._cfg)457 x = reader.getargvlist("key1")458 assert x == [["cmd1", "--flag"]]459 def test_argvlist_command_contains_hash(self, tmpdir, newconfig):460 config = newconfig("""461 [section]462 key1=463 cmd1 --re "use the # symbol for an arg"464 """)465 reader = SectionReader("section", config._cfg)466 x = reader.getargvlist("key1")467 assert x == [["cmd1", "--re", "use the # symbol for an arg"]]468 def test_argvlist_positional_substitution(self, tmpdir, newconfig):469 config = newconfig("""470 [section]471 key2=472 cmd1 []473 cmd2 {posargs:{item2} \474 other}475 """)476 reader = SectionReader("section", config._cfg)477 posargs = ['hello', 'world']478 reader.addsubstitutions(posargs, item2="value2")479 # py.test.raises(tox.exception.ConfigError,480 # "reader.getargvlist('key1')")481 assert reader.getargvlist('key1') == []482 argvlist = reader.getargvlist("key2")483 assert argvlist[0] == ["cmd1"] + posargs484 assert argvlist[1] == ["cmd2"] + posargs485 reader = SectionReader("section", config._cfg)486 reader.addsubstitutions([], item2="value2")487 # py.test.raises(tox.exception.ConfigError,488 # "reader.getargvlist('key1')")489 assert reader.getargvlist('key1') == []490 argvlist = reader.getargvlist("key2")491 assert argvlist[0] == ["cmd1"]492 assert argvlist[1] == ["cmd2", "value2", "other"]493 def test_argvlist_quoted_posargs(self, tmpdir, newconfig):494 config = newconfig("""495 [section]496 key2=497 cmd1 --foo-args='{posargs}'498 cmd2 -f '{posargs}'499 cmd3 -f {posargs}500 """)501 reader = SectionReader("section", config._cfg)502 reader.addsubstitutions(["foo", "bar"])503 assert reader.getargvlist('key1') == []504 x = reader.getargvlist("key2")505 assert x == [["cmd1", "--foo-args=foo bar"],506 ["cmd2", "-f", "foo bar"],507 ["cmd3", "-f", "foo", "bar"]]508 def test_argvlist_posargs_with_quotes(self, tmpdir, newconfig):509 config = newconfig("""510 [section]511 key2=512 cmd1 -f {posargs}513 """)514 reader = SectionReader("section", config._cfg)515 reader.addsubstitutions(["foo", "'bar", "baz'"])516 assert reader.getargvlist('key1') == []517 x = reader.getargvlist("key2")518 assert x == [["cmd1", "-f", "foo", "bar baz"]]519 def test_positional_arguments_are_only_replaced_when_standing_alone(self, tmpdir, newconfig):520 config = newconfig("""521 [section]522 key=523 cmd0 []524 cmd1 -m '[abc]'525 cmd2 -m '\'something\'' []526 cmd3 something[]else527 """)528 reader = SectionReader("section", config._cfg)529 posargs = ['hello', 'world']530 reader.addsubstitutions(posargs)531 argvlist = reader.getargvlist('key')532 assert argvlist[0] == ['cmd0'] + posargs533 assert argvlist[1] == ['cmd1', '-m', '[abc]']534 assert argvlist[2] == ['cmd2', '-m', "something"] + posargs535 assert argvlist[3] == ['cmd3', 'something[]else']536 def test_substitution_with_multiple_words(self, newconfig):537 inisource = """538 [section]539 key = py.test -n5 --junitxml={envlogdir}/junit-{envname}.xml []540 """541 config = newconfig(inisource)542 reader = SectionReader("section", config._cfg)543 posargs = ['hello', 'world']544 reader.addsubstitutions(posargs, envlogdir='ENV_LOG_DIR', envname='ENV_NAME')545 expected = [546 'py.test', '-n5', '--junitxml=ENV_LOG_DIR/junit-ENV_NAME.xml', 'hello', 'world'547 ]548 assert reader.getargvlist('key')[0] == expected549 def test_getargv(self, newconfig):550 config = newconfig("""551 [section]552 key=some command "with quoting"553 """)554 reader = SectionReader("section", config._cfg)555 expected = ['some', 'command', 'with quoting']556 assert reader.getargv('key') == expected557 def test_getpath(self, tmpdir, newconfig):558 config = newconfig("""559 [section]560 path1={HELLO}561 """)562 reader = SectionReader("section", config._cfg)563 reader.addsubstitutions(toxinidir=tmpdir, HELLO="mypath")564 x = reader.getpath("path1", tmpdir)565 assert x == tmpdir.join("mypath")566 def test_getbool(self, tmpdir, newconfig):567 config = newconfig("""568 [section]569 key1=True570 key2=False571 key1a=true572 key2a=falsE573 key5=yes574 """)575 reader = SectionReader("section", config._cfg)576 assert reader.getbool("key1") is True577 assert reader.getbool("key1a") is True578 assert reader.getbool("key2") is False579 assert reader.getbool("key2a") is False580 py.test.raises(KeyError, 'reader.getbool("key3")')581 py.test.raises(tox.exception.ConfigError, 'reader.getbool("key5")')582class TestIniParserPrefix:583 def test_basic_section_access(self, tmpdir, newconfig):584 config = newconfig("""585 [p:section]586 key=value587 """)588 reader = SectionReader("section", config._cfg, prefix="p")589 x = reader.getstring("key")590 assert x == "value"591 assert not reader.getstring("hello")592 x = reader.getstring("hello", "world")593 assert x == "world"594 def test_fallback_sections(self, tmpdir, newconfig):595 config = newconfig("""596 [p:mydefault]597 key2=value2598 [p:section]599 key=value600 """)601 reader = SectionReader("section", config._cfg, prefix="p",602 fallbacksections=['p:mydefault'])603 x = reader.getstring("key2")604 assert x == "value2"605 x = reader.getstring("key3")606 assert not x607 x = reader.getstring("key3", "world")608 assert x == "world"609 def test_value_matches_prefixed_section_substituion(self):610 assert is_section_substitution("{[p:setup]commands}")611 def test_value_doesn_match_prefixed_section_substitution(self):612 assert is_section_substitution("{[p: ]commands}") is None613 assert is_section_substitution("{[p:setup]}") is None614 assert is_section_substitution("{[p:setup] commands}") is None615 def test_other_section_substitution(self, newconfig):616 config = newconfig("""617 [p:section]618 key = rue619 [p:testenv]620 key = t{[p:section]key}621 """)622 reader = SectionReader("testenv", config._cfg, prefix="p")623 x = reader.getstring("key")624 assert x == "true"625class TestConfigTestEnv:626 def test_commentchars_issue33(self, tmpdir, newconfig):627 config = newconfig("""628 [testenv] # hello629 deps = http://abc#123630 commands=631 python -c "x ; y"632 """)633 envconfig = config.envconfigs["python"]634 assert envconfig.deps[0].name == "http://abc#123"635 assert envconfig.commands[0] == ["python", "-c", "x ; y"]636 def test_defaults(self, tmpdir, newconfig):637 config = newconfig("""638 [testenv]639 commands=640 xyz --abc641 """)642 assert len(config.envconfigs) == 1643 envconfig = config.envconfigs['python']644 assert envconfig.commands == [["xyz", "--abc"]]645 assert envconfig.changedir == config.setupdir646 assert envconfig.sitepackages is False647 assert envconfig.usedevelop is False648 assert envconfig.ignore_errors is False649 assert envconfig.envlogdir == envconfig.envdir.join("log")650 assert list(envconfig.setenv.definitions.keys()) == ['PYTHONHASHSEED']651 hashseed = envconfig.setenv['PYTHONHASHSEED']652 assert isinstance(hashseed, str)653 # The following line checks that hashseed parses to an integer.654 int_hashseed = int(hashseed)655 # hashseed is random by default, so we can't assert a specific value.656 assert int_hashseed > 0657 assert envconfig.ignore_outcome is False658 def test_sitepackages_switch(self, tmpdir, newconfig):659 config = newconfig(["--sitepackages"], "")660 envconfig = config.envconfigs['python']661 assert envconfig.sitepackages is True662 def test_installpkg_tops_develop(self, newconfig):663 config = newconfig(["--installpkg=abc"], """664 [testenv]665 usedevelop = True666 """)667 assert not config.envconfigs["python"].usedevelop668 def test_specific_command_overrides(self, tmpdir, newconfig):669 config = newconfig("""670 [testenv]671 commands=xyz672 [testenv:py]673 commands=abc674 """)675 assert len(config.envconfigs) == 1676 envconfig = config.envconfigs['py']677 assert envconfig.commands == [["abc"]]678 def test_whitelist_externals(self, tmpdir, newconfig):679 config = newconfig("""680 [testenv]681 whitelist_externals = xyz682 commands=xyz683 [testenv:x]684 [testenv:py]685 whitelist_externals = xyz2686 commands=abc687 """)688 assert len(config.envconfigs) == 2689 envconfig = config.envconfigs['py']690 assert envconfig.commands == [["abc"]]691 assert envconfig.whitelist_externals == ["xyz2"]692 envconfig = config.envconfigs['x']693 assert envconfig.whitelist_externals == ["xyz"]694 def test_changedir(self, tmpdir, newconfig):695 config = newconfig("""696 [testenv]697 changedir=xyz698 """)699 assert len(config.envconfigs) == 1700 envconfig = config.envconfigs['python']701 assert envconfig.changedir.basename == "xyz"702 assert envconfig.changedir == config.toxinidir.join("xyz")703 def test_ignore_errors(self, tmpdir, newconfig):704 config = newconfig("""705 [testenv]706 ignore_errors=True707 """)708 assert len(config.envconfigs) == 1709 envconfig = config.envconfigs['python']710 assert envconfig.ignore_errors is True711 def test_envbindir(self, tmpdir, newconfig):712 config = newconfig("""713 [testenv]714 basepython=python715 """)716 assert len(config.envconfigs) == 1717 envconfig = config.envconfigs['python']718 assert envconfig.envpython == envconfig.envbindir.join("python")719 @pytest.mark.parametrize("bp", ["jython", "pypy", "pypy3"])720 def test_envbindir_jython(self, tmpdir, newconfig, bp):721 config = newconfig("""722 [testenv]723 basepython=%s724 """ % bp)725 assert len(config.envconfigs) == 1726 envconfig = config.envconfigs['python']727 # on win32 and linux virtualenv uses "bin" for pypy/jython728 assert envconfig.envbindir.basename == "bin"729 if bp == "jython":730 assert envconfig.envpython == envconfig.envbindir.join(bp)731 @pytest.mark.parametrize("plat", ["win32", "linux2"])732 def test_passenv_as_multiline_list(self, tmpdir, newconfig, monkeypatch, plat):733 monkeypatch.setattr(sys, "platform", plat)734 monkeypatch.setenv("A123A", "a")735 monkeypatch.setenv("A123B", "b")736 monkeypatch.setenv("BX23", "0")737 config = newconfig("""738 [testenv]739 passenv =740 A123*741 # isolated comment742 B?23743 """)744 assert len(config.envconfigs) == 1745 envconfig = config.envconfigs['python']746 if plat == "win32":747 assert "PATHEXT" in envconfig.passenv748 assert "SYSTEMDRIVE" in envconfig.passenv749 assert "SYSTEMROOT" in envconfig.passenv750 assert "TEMP" in envconfig.passenv751 assert "TMP" in envconfig.passenv752 else:753 assert "TMPDIR" in envconfig.passenv754 assert "PATH" in envconfig.passenv755 assert "PIP_INDEX_URL" in envconfig.passenv756 assert "LANG" in envconfig.passenv757 assert "LD_LIBRARY_PATH" in envconfig.passenv758 assert "A123A" in envconfig.passenv759 assert "A123B" in envconfig.passenv760 @pytest.mark.parametrize("plat", ["win32", "linux2"])761 def test_passenv_as_space_separated_list(self, tmpdir, newconfig, monkeypatch, plat):762 monkeypatch.setattr(sys, "platform", plat)763 monkeypatch.setenv("A123A", "a")764 monkeypatch.setenv("A123B", "b")765 monkeypatch.setenv("BX23", "0")766 config = newconfig("""767 [testenv]768 passenv =769 # comment770 A123* B?23771 """)772 assert len(config.envconfigs) == 1773 envconfig = config.envconfigs['python']774 if plat == "win32":775 assert "PATHEXT" in envconfig.passenv776 assert "SYSTEMDRIVE" in envconfig.passenv777 assert "SYSTEMROOT" in envconfig.passenv778 assert "TEMP" in envconfig.passenv779 assert "TMP" in envconfig.passenv780 else:781 assert "TMPDIR" in envconfig.passenv782 assert "PATH" in envconfig.passenv783 assert "PIP_INDEX_URL" in envconfig.passenv784 assert "LANG" in envconfig.passenv785 assert "A123A" in envconfig.passenv786 assert "A123B" in envconfig.passenv787 def test_passenv_with_factor(self, tmpdir, newconfig, monkeypatch):788 monkeypatch.setenv("A123A", "a")789 monkeypatch.setenv("A123B", "b")790 monkeypatch.setenv("A123C", "c")791 monkeypatch.setenv("A123D", "d")792 monkeypatch.setenv("BX23", "0")793 monkeypatch.setenv("CCA43", "3")794 monkeypatch.setenv("CB21", "4")795 config = newconfig("""796 [tox]797 envlist = {x1,x2}798 [testenv]799 passenv =800 x1: A123A CC*801 x1: CB21802 # passed to both environments803 A123C804 x2: A123B A123D805 """)806 assert len(config.envconfigs) == 2807 assert "A123A" in config.envconfigs["x1"].passenv808 assert "A123C" in config.envconfigs["x1"].passenv809 assert "CCA43" in config.envconfigs["x1"].passenv810 assert "CB21" in config.envconfigs["x1"].passenv811 assert "A123B" not in config.envconfigs["x1"].passenv812 assert "A123D" not in config.envconfigs["x1"].passenv813 assert "BX23" not in config.envconfigs["x1"].passenv814 assert "A123B" in config.envconfigs["x2"].passenv815 assert "A123D" in config.envconfigs["x2"].passenv816 assert "A123A" not in config.envconfigs["x2"].passenv817 assert "A123C" in config.envconfigs["x2"].passenv818 assert "CCA43" not in config.envconfigs["x2"].passenv819 assert "CB21" not in config.envconfigs["x2"].passenv820 assert "BX23" not in config.envconfigs["x2"].passenv821 def test_passenv_from_global_env(self, tmpdir, newconfig, monkeypatch):822 monkeypatch.setenv("A1", "a1")823 monkeypatch.setenv("A2", "a2")824 monkeypatch.setenv("TOX_TESTENV_PASSENV", "A1")825 config = newconfig("""826 [testenv]827 passenv = A2828 """)829 env = config.envconfigs["python"]830 assert "A1" in env.passenv831 assert "A2" in env.passenv832 def test_changedir_override(self, tmpdir, newconfig):833 config = newconfig("""834 [testenv]835 changedir=xyz836 [testenv:python]837 changedir=abc838 basepython=python2.6839 """)840 assert len(config.envconfigs) == 1841 envconfig = config.envconfigs['python']842 assert envconfig.changedir.basename == "abc"843 assert envconfig.changedir == config.setupdir.join("abc")844 def test_install_command_setting(self, newconfig):845 config = newconfig("""846 [testenv]847 install_command=some_install {packages}848 """)849 envconfig = config.envconfigs['python']850 assert envconfig.install_command == [851 'some_install', '{packages}']852 def test_install_command_must_contain_packages(self, newconfig):853 py.test.raises(tox.exception.ConfigError, newconfig, """854 [testenv]855 install_command=pip install856 """)857 def test_install_command_substitutions(self, newconfig):858 config = newconfig("""859 [testenv]860 install_command=some_install --arg={toxinidir}/foo \861 {envname} {opts} {packages}862 """)863 envconfig = config.envconfigs['python']864 assert envconfig.install_command == [865 'some_install', '--arg=%s/foo' % config.toxinidir, 'python',866 '{opts}', '{packages}']867 def test_pip_pre(self, newconfig):868 config = newconfig("""869 [testenv]870 pip_pre=true871 """)872 envconfig = config.envconfigs['python']873 assert envconfig.pip_pre874 def test_pip_pre_cmdline_override(self, newconfig):875 config = newconfig(876 ['--pre'],877 """878 [testenv]879 pip_pre=false880 """)881 envconfig = config.envconfigs['python']882 assert envconfig.pip_pre883 def test_downloadcache(self, newconfig, monkeypatch):884 monkeypatch.delenv("PIP_DOWNLOAD_CACHE", raising=False)885 config = newconfig("""886 [testenv]887 downloadcache=thecache888 """)889 envconfig = config.envconfigs['python']890 assert envconfig.downloadcache.basename == 'thecache'891 def test_downloadcache_env_override(self, newconfig, monkeypatch):892 monkeypatch.setenv("PIP_DOWNLOAD_CACHE", 'fromenv')893 config = newconfig("""894 [testenv]895 downloadcache=somepath896 """)897 envconfig = config.envconfigs['python']898 assert envconfig.downloadcache.basename == "fromenv"899 def test_downloadcache_only_if_in_config(self, newconfig, tmpdir,900 monkeypatch):901 monkeypatch.setenv("PIP_DOWNLOAD_CACHE", tmpdir)902 config = newconfig('')903 envconfig = config.envconfigs['python']904 assert not envconfig.downloadcache905 def test_simple(tmpdir, newconfig):906 config = newconfig("""907 [testenv:py26]908 basepython=python2.6909 [testenv:py27]910 basepython=python2.7911 """)912 assert len(config.envconfigs) == 2913 assert "py26" in config.envconfigs914 assert "py27" in config.envconfigs915 def test_substitution_error(tmpdir, newconfig):916 py.test.raises(tox.exception.ConfigError, newconfig, """917 [testenv:py27]918 basepython={xyz}919 """)920 def test_substitution_defaults(tmpdir, newconfig):921 config = newconfig("""922 [testenv:py27]923 commands =924 {toxinidir}925 {toxworkdir}926 {envdir}927 {envbindir}928 {envtmpdir}929 {envpython}930 {homedir}931 {distshare}932 {envlogdir}933 """)934 conf = config.envconfigs['py27']935 argv = conf.commands936 assert argv[0][0] == config.toxinidir937 assert argv[1][0] == config.toxworkdir938 assert argv[2][0] == conf.envdir939 assert argv[3][0] == conf.envbindir940 assert argv[4][0] == conf.envtmpdir941 assert argv[5][0] == conf.envpython942 assert argv[6][0] == str(config.homedir)943 assert argv[7][0] == config.homedir.join(".tox", "distshare")944 assert argv[8][0] == conf.envlogdir945 def test_substitution_notfound_issue246(tmpdir, newconfig):946 config = newconfig("""947 [testenv:py27]948 setenv =949 FOO={envbindir}950 BAR={envsitepackagesdir}951 """)952 conf = config.envconfigs['py27']953 env = conf.setenv954 assert 'FOO' in env955 assert 'BAR' in env956 def test_substitution_positional(self, newconfig):957 inisource = """958 [testenv:py27]959 commands =960 cmd1 [hello] \961 world962 cmd1 {posargs:hello} \963 world964 """965 conf = newconfig([], inisource).envconfigs['py27']966 argv = conf.commands967 assert argv[0] == ["cmd1", "[hello]", "world"]968 assert argv[1] == ["cmd1", "hello", "world"]969 conf = newconfig(['brave', 'new'], inisource).envconfigs['py27']970 argv = conf.commands971 assert argv[0] == ["cmd1", "[hello]", "world"]972 assert argv[1] == ["cmd1", "brave", "new", "world"]973 def test_substitution_noargs_issue240(self, newconfig):974 inisource = """975 [testenv]976 commands = echo {posargs:foo}977 """978 conf = newconfig([""], inisource).envconfigs['python']979 argv = conf.commands980 assert argv[0] == ["echo"]981 def test_substitution_double(self, newconfig):982 inisource = """983 [params]984 foo = bah985 foo2 = [params]foo986 [testenv:py27]987 commands =988 echo {{[params]foo2}}989 """990 conf = newconfig([], inisource).envconfigs['py27']991 argv = conf.commands992 assert argv[0] == ['echo', 'bah']993 def test_posargs_backslashed_or_quoted(self, tmpdir, newconfig):994 inisource = """995 [testenv:py27]996 commands =997 echo "\{posargs\}" = {posargs}998 echo "posargs = " "{posargs}"999 """1000 conf = newconfig([], inisource).envconfigs['py27']1001 argv = conf.commands1002 assert argv[0] == ['echo', '{posargs}', '=']1003 assert argv[1] == ['echo', 'posargs = ', ""]1004 conf = newconfig(['dog', 'cat'], inisource).envconfigs['py27']1005 argv = conf.commands1006 assert argv[0] == ['echo', '{posargs}', '=', 'dog', 'cat']1007 assert argv[1] == ['echo', 'posargs = ', 'dog cat']1008 def test_rewrite_posargs(self, tmpdir, newconfig):1009 inisource = """1010 [testenv:py27]1011 args_are_paths = True1012 changedir = tests1013 commands = cmd1 {posargs:hello}1014 """1015 conf = newconfig([], inisource).envconfigs['py27']1016 argv = conf.commands1017 assert argv[0] == ["cmd1", "hello"]1018 conf = newconfig(["tests/hello"], inisource).envconfigs['py27']1019 argv = conf.commands1020 assert argv[0] == ["cmd1", "tests/hello"]1021 tmpdir.ensure("tests", "hello")1022 conf = newconfig(["tests/hello"], inisource).envconfigs['py27']1023 argv = conf.commands1024 assert argv[0] == ["cmd1", "hello"]1025 def test_rewrite_simple_posargs(self, tmpdir, newconfig):1026 inisource = """1027 [testenv:py27]1028 args_are_paths = True1029 changedir = tests1030 commands = cmd1 {posargs}1031 """1032 conf = newconfig([], inisource).envconfigs['py27']1033 argv = conf.commands1034 assert argv[0] == ["cmd1"]1035 conf = newconfig(["tests/hello"], inisource).envconfigs['py27']1036 argv = conf.commands1037 assert argv[0] == ["cmd1", "tests/hello"]1038 tmpdir.ensure("tests", "hello")1039 conf = newconfig(["tests/hello"], inisource).envconfigs['py27']1040 argv = conf.commands1041 assert argv[0] == ["cmd1", "hello"]1042 def test_take_dependencies_from_other_testenv(self, newconfig):1043 inisource = """1044 [testenv]1045 deps=1046 pytest1047 pytest-cov1048 [testenv:py27]1049 deps=1050 {[testenv]deps}1051 fun1052 """1053 conf = newconfig([], inisource).envconfigs['py27']1054 packages = [dep.name for dep in conf.deps]1055 assert packages == ['pytest', 'pytest-cov', 'fun']1056 def test_take_dependencies_from_other_section(self, newconfig):1057 inisource = """1058 [testing:pytest]1059 deps=1060 pytest1061 pytest-cov1062 [testing:mock]1063 deps=1064 mock1065 [testenv]1066 deps=1067 {[testing:pytest]deps}1068 {[testing:mock]deps}1069 fun1070 """1071 conf = newconfig([], inisource)1072 env = conf.envconfigs['python']1073 packages = [dep.name for dep in env.deps]1074 assert packages == ['pytest', 'pytest-cov', 'mock', 'fun']1075 def test_multilevel_substitution(self, newconfig):1076 inisource = """1077 [testing:pytest]1078 deps=1079 pytest1080 pytest-cov1081 [testing:mock]1082 deps=1083 mock1084 [testing]1085 deps=1086 {[testing:pytest]deps}1087 {[testing:mock]deps}1088 [testenv]1089 deps=1090 {[testing]deps}1091 fun1092 """1093 conf = newconfig([], inisource)1094 env = conf.envconfigs['python']1095 packages = [dep.name for dep in env.deps]1096 assert packages == ['pytest', 'pytest-cov', 'mock', 'fun']1097 def test_recursive_substitution_cycle_fails(self, newconfig):1098 inisource = """1099 [testing:pytest]1100 deps=1101 {[testing:mock]deps}1102 [testing:mock]1103 deps=1104 {[testing:pytest]deps}1105 [testenv]1106 deps=1107 {[testing:pytest]deps}1108 """1109 py.test.raises(ValueError, newconfig, [], inisource)1110 def test_single_value_from_other_secton(self, newconfig, tmpdir):1111 inisource = """1112 [common]1113 changedir = testing1114 [testenv]1115 changedir = {[common]changedir}1116 """1117 conf = newconfig([], inisource).envconfigs['python']1118 assert conf.changedir.basename == 'testing'1119 assert conf.changedir.dirpath().realpath() == tmpdir.realpath()1120 def test_factors(self, newconfig):1121 inisource = """1122 [tox]1123 envlist = a-x,b1124 [testenv]1125 deps=1126 dep-all1127 a: dep-a1128 b: dep-b1129 x: dep-x1130 """1131 conf = newconfig([], inisource)1132 configs = conf.envconfigs1133 assert [dep.name for dep in configs['a-x'].deps] == \1134 ["dep-all", "dep-a", "dep-x"]1135 assert [dep.name for dep in configs['b'].deps] == ["dep-all", "dep-b"]1136 def test_factor_ops(self, newconfig):1137 inisource = """1138 [tox]1139 envlist = {a,b}-{x,y}1140 [testenv]1141 deps=1142 a,b: dep-a-or-b1143 a-x: dep-a-and-x1144 {a,b}-y: dep-ab-and-y1145 """1146 configs = newconfig([], inisource).envconfigs1147 get_deps = lambda env: [dep.name for dep in configs[env].deps]1148 assert get_deps("a-x") == ["dep-a-or-b", "dep-a-and-x"]1149 assert get_deps("a-y") == ["dep-a-or-b", "dep-ab-and-y"]1150 assert get_deps("b-x") == ["dep-a-or-b"]1151 assert get_deps("b-y") == ["dep-a-or-b", "dep-ab-and-y"]1152 def test_default_factors(self, newconfig):1153 inisource = """1154 [tox]1155 envlist = py{26,27,33,34}-dep1156 [testenv]1157 deps=1158 dep: dep1159 """1160 conf = newconfig([], inisource)1161 configs = conf.envconfigs1162 for name, config in configs.items():1163 assert config.basepython == 'python%s.%s' % (name[2], name[3])1164 @pytest.mark.issue1881165 def test_factors_in_boolean(self, newconfig):1166 inisource = """1167 [tox]1168 envlist = py{27,33}1169 [testenv]1170 recreate =1171 py27: True1172 """1173 configs = newconfig([], inisource).envconfigs1174 assert configs["py27"].recreate1175 assert not configs["py33"].recreate1176 @pytest.mark.issue1901177 def test_factors_in_setenv(self, newconfig):1178 inisource = """1179 [tox]1180 envlist = py27,py261181 [testenv]1182 setenv =1183 py27: X = 11184 """1185 configs = newconfig([], inisource).envconfigs1186 assert configs["py27"].setenv["X"] == "1"1187 assert "X" not in configs["py26"].setenv1188 @pytest.mark.issue1911189 def test_factor_use_not_checked(self, newconfig):1190 inisource = """1191 [tox]1192 envlist = py27-{a,b}1193 [testenv]1194 deps = b: test1195 """1196 configs = newconfig([], inisource).envconfigs1197 assert set(configs.keys()) == set(['py27-a', 'py27-b'])1198 @pytest.mark.issue1981199 def test_factors_groups_touch(self, newconfig):1200 inisource = """1201 [tox]1202 envlist = {a,b}{-x,}1203 [testenv]1204 deps=1205 a,b,x,y: dep1206 """1207 configs = newconfig([], inisource).envconfigs1208 assert set(configs.keys()) == set(['a', 'a-x', 'b', 'b-x'])1209 def test_period_in_factor(self, newconfig):1210 inisource = """1211 [tox]1212 envlist = py27-{django1.6,django1.7}1213 [testenv]1214 deps =1215 django1.6: Django==1.61216 django1.7: Django==1.71217 """1218 configs = newconfig([], inisource).envconfigs1219 assert sorted(configs) == ["py27-django1.6", "py27-django1.7"]1220 assert [d.name for d in configs["py27-django1.6"].deps] \1221 == ["Django==1.6"]1222 def test_ignore_outcome(self, newconfig):1223 inisource = """1224 [testenv]1225 ignore_outcome=True1226 """1227 config = newconfig([], inisource).envconfigs1228 assert config["python"].ignore_outcome is True1229class TestGlobalOptions:1230 def test_notest(self, newconfig):1231 config = newconfig([], "")1232 assert not config.option.notest1233 config = newconfig(["--notest"], "")1234 assert config.option.notest1235 def test_verbosity(self, newconfig):1236 config = newconfig([], "")1237 assert config.option.verbosity == 01238 config = newconfig(["-v"], "")1239 assert config.option.verbosity == 11240 config = newconfig(["-vv"], "")1241 assert config.option.verbosity == 21242 def test_substitution_jenkins_default(self, tmpdir,1243 monkeypatch, newconfig):1244 monkeypatch.setenv("HUDSON_URL", "xyz")1245 config = newconfig("""1246 [testenv:py27]1247 commands =1248 {distshare}1249 """)1250 conf = config.envconfigs['py27']1251 argv = conf.commands1252 expect_path = config.toxworkdir.join("distshare")1253 assert argv[0][0] == expect_path1254 def test_substitution_jenkins_context(self, tmpdir, monkeypatch, newconfig):1255 monkeypatch.setenv("HUDSON_URL", "xyz")1256 monkeypatch.setenv("WORKSPACE", tmpdir)1257 config = newconfig("""1258 [tox:jenkins]1259 distshare = {env:WORKSPACE}/hello1260 [testenv:py27]1261 commands =1262 {distshare}1263 """)1264 conf = config.envconfigs['py27']1265 argv = conf.commands1266 assert argv[0][0] == config.distshare1267 assert config.distshare == tmpdir.join("hello")1268 def test_sdist_specification(self, tmpdir, newconfig):1269 config = newconfig("""1270 [tox]1271 sdistsrc = {distshare}/xyz.zip1272 """)1273 assert config.sdistsrc == config.distshare.join("xyz.zip")1274 config = newconfig([], "")1275 assert not config.sdistsrc1276 def test_env_selection(self, tmpdir, newconfig, monkeypatch):1277 inisource = """1278 [tox]1279 envlist = py261280 [testenv:py26]1281 basepython=python2.61282 [testenv:py31]1283 basepython=python3.11284 [testenv:py27]1285 basepython=python2.71286 """1287 # py.test.raises(tox.exception.ConfigError,1288 # "newconfig(['-exyz'], inisource)")1289 config = newconfig([], inisource)1290 assert config.envlist == ["py26"]1291 config = newconfig(["-epy31"], inisource)1292 assert config.envlist == ["py31"]1293 monkeypatch.setenv("TOXENV", "py31,py26")1294 config = newconfig([], inisource)1295 assert config.envlist == ["py31", "py26"]1296 monkeypatch.setenv("TOXENV", "ALL")1297 config = newconfig([], inisource)1298 assert config.envlist == ['py26', 'py27', 'py31']1299 config = newconfig(["-eALL"], inisource)1300 assert config.envlist == ['py26', 'py27', 'py31']1301 def test_py_venv(self, tmpdir, newconfig, monkeypatch):1302 config = newconfig(["-epy"], "")1303 env = config.envconfigs['py']1304 assert str(env.basepython) == sys.executable1305 def test_default_environments(self, tmpdir, newconfig, monkeypatch):1306 envs = "py26,py27,py32,py33,py34,py35,py36,jython,pypy,pypy3"1307 inisource = """1308 [tox]1309 envlist = %s1310 """ % envs1311 config = newconfig([], inisource)1312 envlist = envs.split(",")1313 assert config.envlist == envlist1314 for name in config.envlist:1315 env = config.envconfigs[name]1316 if name == "jython":1317 assert env.basepython == "jython"1318 elif name.startswith("pypy"):1319 assert env.basepython == name1320 else:1321 assert name.startswith("py")1322 bp = "python%s.%s" % (name[2], name[3])1323 assert env.basepython == bp1324 def test_envlist_expansion(self, newconfig):1325 inisource = """1326 [tox]1327 envlist = py{26,27},docs1328 """1329 config = newconfig([], inisource)1330 assert config.envlist == ["py26", "py27", "docs"]1331 def test_envlist_cross_product(self, newconfig):1332 inisource = """1333 [tox]1334 envlist = py{26,27}-dep{1,2}1335 """1336 config = newconfig([], inisource)1337 assert config.envlist == \1338 ["py26-dep1", "py26-dep2", "py27-dep1", "py27-dep2"]1339 def test_envlist_multiline(self, newconfig):1340 inisource = """1341 [tox]1342 envlist =1343 py271344 py341345 """1346 config = newconfig([], inisource)1347 assert config.envlist == \1348 ["py27", "py34"]1349 def test_minversion(self, tmpdir, newconfig, monkeypatch):1350 inisource = """1351 [tox]1352 minversion = 10.01353 """1354 with py.test.raises(tox.exception.MinVersionError):1355 newconfig([], inisource)1356 def test_skip_missing_interpreters_true(self, tmpdir, newconfig, monkeypatch):1357 inisource = """1358 [tox]1359 skip_missing_interpreters = True1360 """1361 config = newconfig([], inisource)1362 assert config.option.skip_missing_interpreters1363 def test_skip_missing_interpreters_false(self, tmpdir, newconfig, monkeypatch):1364 inisource = """1365 [tox]1366 skip_missing_interpreters = False1367 """1368 config = newconfig([], inisource)1369 assert not config.option.skip_missing_interpreters1370 def test_defaultenv_commandline(self, tmpdir, newconfig, monkeypatch):1371 config = newconfig(["-epy27"], "")1372 env = config.envconfigs['py27']1373 assert env.basepython == "python2.7"1374 assert not env.commands1375 def test_defaultenv_partial_override(self, tmpdir, newconfig, monkeypatch):1376 inisource = """1377 [tox]1378 envlist = py271379 [testenv:py27]1380 commands= xyz1381 """1382 config = newconfig([], inisource)1383 env = config.envconfigs['py27']1384 assert env.basepython == "python2.7"1385 assert env.commands == [['xyz']]1386class TestHashseedOption:1387 def _get_envconfigs(self, newconfig, args=None, tox_ini=None,1388 make_hashseed=None):1389 if args is None:1390 args = []1391 if tox_ini is None:1392 tox_ini = """1393 [testenv]1394 """1395 if make_hashseed is None:1396 make_hashseed = lambda: '123456789'1397 original_make_hashseed = tox.config.make_hashseed1398 tox.config.make_hashseed = make_hashseed1399 try:1400 config = newconfig(args, tox_ini)1401 finally:1402 tox.config.make_hashseed = original_make_hashseed1403 return config.envconfigs1404 def _get_envconfig(self, newconfig, args=None, tox_ini=None):1405 envconfigs = self._get_envconfigs(newconfig, args=args,1406 tox_ini=tox_ini)1407 return envconfigs["python"]1408 def _check_hashseed(self, envconfig, expected):1409 assert envconfig.setenv['PYTHONHASHSEED'] == expected1410 def _check_testenv(self, newconfig, expected, args=None, tox_ini=None):1411 envconfig = self._get_envconfig(newconfig, args=args, tox_ini=tox_ini)1412 self._check_hashseed(envconfig, expected)1413 def test_default(self, tmpdir, newconfig):1414 self._check_testenv(newconfig, '123456789')1415 def test_passing_integer(self, tmpdir, newconfig):1416 args = ['--hashseed', '1']1417 self._check_testenv(newconfig, '1', args=args)1418 def test_passing_string(self, tmpdir, newconfig):1419 args = ['--hashseed', 'random']1420 self._check_testenv(newconfig, 'random', args=args)1421 def test_passing_empty_string(self, tmpdir, newconfig):1422 args = ['--hashseed', '']1423 self._check_testenv(newconfig, '', args=args)1424 @pytest.mark.xfail(sys.version_info >= (3, 2),1425 reason="at least Debian python 3.2/3.3 have a bug: "1426 "http://bugs.python.org/issue11884")1427 def test_passing_no_argument(self, tmpdir, newconfig):1428 """Test that passing no arguments to --hashseed is not allowed."""1429 args = ['--hashseed']1430 try:1431 self._check_testenv(newconfig, '', args=args)1432 except SystemExit:1433 e = sys.exc_info()[1]1434 assert e.code == 21435 return1436 assert False # getting here means we failed the test.1437 def test_setenv(self, tmpdir, newconfig):1438 """Check that setenv takes precedence."""1439 tox_ini = """1440 [testenv]1441 setenv =1442 PYTHONHASHSEED = 21443 """1444 self._check_testenv(newconfig, '2', tox_ini=tox_ini)1445 args = ['--hashseed', '1']1446 self._check_testenv(newconfig, '2', args=args, tox_ini=tox_ini)1447 def test_noset(self, tmpdir, newconfig):1448 args = ['--hashseed', 'noset']1449 envconfig = self._get_envconfig(newconfig, args=args)1450 assert not envconfig.setenv.definitions1451 def test_noset_with_setenv(self, tmpdir, newconfig):1452 tox_ini = """1453 [testenv]1454 setenv =1455 PYTHONHASHSEED = 21456 """1457 args = ['--hashseed', 'noset']1458 self._check_testenv(newconfig, '2', args=args, tox_ini=tox_ini)1459 def test_one_random_hashseed(self, tmpdir, newconfig):1460 """Check that different testenvs use the same random seed."""1461 tox_ini = """1462 [testenv:hash1]1463 [testenv:hash2]1464 """1465 next_seed = [1000]1466 # This function is guaranteed to generate a different value each time.1467 def make_hashseed():1468 next_seed[0] += 11469 return str(next_seed[0])1470 # Check that make_hashseed() works.1471 assert make_hashseed() == '1001'1472 envconfigs = self._get_envconfigs(newconfig, tox_ini=tox_ini,1473 make_hashseed=make_hashseed)1474 self._check_hashseed(envconfigs["hash1"], '1002')1475 # Check that hash2's value is not '1003', for example.1476 self._check_hashseed(envconfigs["hash2"], '1002')1477 def test_setenv_in_one_testenv(self, tmpdir, newconfig):1478 """Check using setenv in one of multiple testenvs."""1479 tox_ini = """1480 [testenv:hash1]1481 setenv =1482 PYTHONHASHSEED = 21483 [testenv:hash2]1484 """1485 envconfigs = self._get_envconfigs(newconfig, tox_ini=tox_ini)1486 self._check_hashseed(envconfigs["hash1"], '2')1487 self._check_hashseed(envconfigs["hash2"], '123456789')1488class TestSetenv:1489 def test_getdict_lazy(self, tmpdir, newconfig, monkeypatch):1490 monkeypatch.setenv("X", "2")1491 config = newconfig("""1492 [testenv:X]1493 key0 =1494 key1 = {env:X}1495 key2 = {env:Y:1}1496 """)1497 envconfig = config.envconfigs["X"]1498 val = envconfig._reader.getdict_setenv("key0")1499 assert val["key1"] == "2"1500 assert val["key2"] == "1"1501 def test_getdict_lazy_update(self, tmpdir, newconfig, monkeypatch):1502 monkeypatch.setenv("X", "2")1503 config = newconfig("""1504 [testenv:X]1505 key0 =1506 key1 = {env:X}1507 key2 = {env:Y:1}1508 """)1509 envconfig = config.envconfigs["X"]1510 val = envconfig._reader.getdict_setenv("key0")1511 d = {}1512 d.update(val)1513 assert d == {"key1": "2", "key2": "1"}1514 def test_setenv_uses_os_environ(self, tmpdir, newconfig, monkeypatch):1515 monkeypatch.setenv("X", "1")1516 config = newconfig("""1517 [testenv:env1]1518 setenv =1519 X = {env:X}1520 """)1521 assert config.envconfigs["env1"].setenv["X"] == "1"1522 def test_setenv_default_os_environ(self, tmpdir, newconfig, monkeypatch):1523 monkeypatch.delenv("X", raising=False)1524 config = newconfig("""1525 [testenv:env1]1526 setenv =1527 X = {env:X:2}1528 """)1529 assert config.envconfigs["env1"].setenv["X"] == "2"1530 def test_setenv_uses_other_setenv(self, tmpdir, newconfig):1531 config = newconfig("""1532 [testenv:env1]1533 setenv =1534 Y = 51535 X = {env:Y}1536 """)1537 assert config.envconfigs["env1"].setenv["X"] == "5"1538 def test_setenv_recursive_direct(self, tmpdir, newconfig):1539 config = newconfig("""1540 [testenv:env1]1541 setenv =1542 X = {env:X:3}1543 """)1544 assert config.envconfigs["env1"].setenv["X"] == "3"1545 def test_setenv_overrides(self, tmpdir, newconfig):1546 config = newconfig("""1547 [testenv]1548 setenv =1549 PYTHONPATH = something1550 ANOTHER_VAL=else1551 """)1552 assert len(config.envconfigs) == 11553 envconfig = config.envconfigs['python']1554 assert 'PYTHONPATH' in envconfig.setenv1555 assert 'ANOTHER_VAL' in envconfig.setenv1556 assert envconfig.setenv['PYTHONPATH'] == 'something'1557 assert envconfig.setenv['ANOTHER_VAL'] == 'else'1558 def test_setenv_with_envdir_and_basepython(self, tmpdir, newconfig):1559 config = newconfig("""1560 [testenv]1561 setenv =1562 VAL = {envdir}1563 basepython = {env:VAL}1564 """)1565 assert len(config.envconfigs) == 11566 envconfig = config.envconfigs['python']1567 assert 'VAL' in envconfig.setenv1568 assert envconfig.setenv['VAL'] == envconfig.envdir1569 assert envconfig.basepython == envconfig.envdir1570 def test_setenv_ordering_1(self, tmpdir, newconfig):1571 config = newconfig("""1572 [testenv]1573 setenv=1574 VAL={envdir}1575 commands=echo {env:VAL}1576 """)1577 assert len(config.envconfigs) == 11578 envconfig = config.envconfigs['python']1579 assert 'VAL' in envconfig.setenv1580 assert envconfig.setenv['VAL'] == envconfig.envdir1581 assert str(envconfig.envdir) in envconfig.commands[0]1582 def test_setenv_cross_section_subst_issue294(self, monkeypatch, newconfig):1583 """test that we can do cross-section substitution with setenv"""1584 monkeypatch.delenv('TEST', raising=False)1585 config = newconfig("""1586 [section]1587 x =1588 NOT_TEST={env:TEST:defaultvalue}1589 [testenv]1590 setenv = {[section]x}1591 """)1592 envconfig = config.envconfigs["python"]1593 assert envconfig.setenv["NOT_TEST"] == "defaultvalue"1594 def test_setenv_cross_section_subst_twice(self, monkeypatch, newconfig):1595 """test that we can do cross-section substitution with setenv"""1596 monkeypatch.delenv('TEST', raising=False)1597 config = newconfig("""1598 [section]1599 x = NOT_TEST={env:TEST:defaultvalue}1600 [section1]1601 y = {[section]x}1602 [testenv]1603 setenv = {[section1]y}1604 """)1605 envconfig = config.envconfigs["python"]1606 assert envconfig.setenv["NOT_TEST"] == "defaultvalue"1607 def test_setenv_cross_section_mixed(self, monkeypatch, newconfig):1608 """test that we can do cross-section substitution with setenv"""1609 monkeypatch.delenv('TEST', raising=False)1610 config = newconfig("""1611 [section]1612 x = NOT_TEST={env:TEST:defaultvalue}1613 [testenv]1614 setenv = {[section]x}1615 y = 71616 """)1617 envconfig = config.envconfigs["python"]1618 assert envconfig.setenv["NOT_TEST"] == "defaultvalue"1619 assert envconfig.setenv["y"] == "7"1620class TestIndexServer:1621 def test_indexserver(self, tmpdir, newconfig):1622 config = newconfig("""1623 [tox]1624 indexserver =1625 name1 = XYZ1626 name2 = ABC1627 """)1628 assert config.indexserver['default'].url is None1629 assert config.indexserver['name1'].url == "XYZ"1630 assert config.indexserver['name2'].url == "ABC"1631 def test_parse_indexserver(self, newconfig):1632 inisource = """1633 [tox]1634 indexserver =1635 default = http://pypi.testrun.org1636 name1 = whatever1637 """1638 config = newconfig([], inisource)1639 assert config.indexserver['default'].url == "http://pypi.testrun.org"1640 assert config.indexserver['name1'].url == "whatever"1641 config = newconfig(['-i', 'qwe'], inisource)1642 assert config.indexserver['default'].url == "qwe"1643 assert config.indexserver['name1'].url == "whatever"1644 config = newconfig(['-i', 'name1=abc', '-i', 'qwe2'], inisource)1645 assert config.indexserver['default'].url == "qwe2"1646 assert config.indexserver['name1'].url == "abc"1647 config = newconfig(["-i", "ALL=xzy"], inisource)1648 assert len(config.indexserver) == 21649 assert config.indexserver["default"].url == "xzy"1650 assert config.indexserver["name1"].url == "xzy"1651 def test_multiple_homedir_relative_local_indexservers(self, newconfig):1652 inisource = """1653 [tox]1654 indexserver =1655 default = file://{homedir}/.pip/downloads/simple1656 local1 = file://{homedir}/.pip/downloads/simple1657 local2 = file://{toxinidir}/downloads/simple1658 pypi = http://pypi.python.org/simple1659 """1660 config = newconfig([], inisource)1661 expected = "file://%s/.pip/downloads/simple" % config.homedir1662 assert config.indexserver['default'].url == expected1663 assert config.indexserver['local1'].url == config.indexserver['default'].url1664class TestParseEnv:1665 def test_parse_recreate(self, newconfig):1666 inisource = ""1667 config = newconfig([], inisource)1668 assert not config.envconfigs['python'].recreate1669 config = newconfig(['--recreate'], inisource)1670 assert config.envconfigs['python'].recreate1671 config = newconfig(['-r'], inisource)1672 assert config.envconfigs['python'].recreate1673 inisource = """1674 [testenv:hello]1675 recreate = True1676 """1677 config = newconfig([], inisource)1678 assert config.envconfigs['hello'].recreate1679class TestCmdInvocation:1680 def test_help(self, cmd):1681 result = cmd.run("tox", "-h")1682 assert not result.ret1683 result.stdout.fnmatch_lines([1684 "*help*",1685 ])1686 def test_version(self, cmd):1687 result = cmd.run("tox", "--version")1688 assert not result.ret1689 stdout = result.stdout.str()1690 assert tox.__version__ in stdout1691 assert "imported from" in stdout1692 def test_listenvs(self, cmd, initproj):1693 initproj('listenvs', filedefs={1694 'tox.ini': '''1695 [tox]1696 envlist=py26,py27,py33,pypy,docs1697 [testenv:notincluded]1698 changedir = whatever1699 [testenv:docs]1700 changedir = docs1701 ''',1702 })1703 result = cmd.run("tox", "-l")1704 result.stdout.fnmatch_lines("""1705 *py26*1706 *py27*1707 *py33*1708 *pypy*1709 *docs*1710 """)1711 def test_config_specific_ini(self, tmpdir, cmd):1712 ini = tmpdir.ensure("hello.ini")1713 result = cmd.run("tox", "-c", ini, "--showconfig")1714 assert not result.ret1715 result.stdout.fnmatch_lines([1716 "*config-file*hello.ini*",1717 ])1718 def test_no_tox_ini(self, cmd, initproj):1719 initproj("noini-0.5", )1720 result = cmd.run("tox")1721 assert result.ret1722 result.stderr.fnmatch_lines([1723 "*ERROR*tox.ini*not*found*",1724 ])1725 def test_override_workdir(self, tmpdir, cmd, initproj):1726 baddir = "badworkdir-123"1727 gooddir = "overridden-234"1728 initproj("overrideworkdir-0.5", filedefs={1729 'tox.ini': '''1730 [tox]1731 toxworkdir=%s1732 ''' % baddir,1733 })1734 result = cmd.run("tox", "--workdir", gooddir, "--showconfig")1735 assert not result.ret1736 stdout = result.stdout.str()1737 assert gooddir in stdout1738 assert baddir not in stdout1739 assert py.path.local(gooddir).check()1740 assert not py.path.local(baddir).check()1741 def test_showconfig_with_force_dep_version(self, cmd, initproj):1742 initproj('force_dep_version', filedefs={1743 'tox.ini': '''1744 [tox]1745 [testenv]1746 deps=1747 dep1==2.31748 dep21749 ''',1750 })1751 result = cmd.run("tox", "--showconfig")1752 assert result.ret == 01753 result.stdout.fnmatch_lines([1754 r'*deps*dep1==2.3, dep2*',1755 ])1756 # override dep1 specific version, and force version for dep21757 result = cmd.run("tox", "--showconfig", "--force-dep=dep1",1758 "--force-dep=dep2==5.0")1759 assert result.ret == 01760 result.stdout.fnmatch_lines([1761 r'*deps*dep1, dep2==5.0*',1762 ])1763@pytest.mark.parametrize("cmdline,envlist", [1764 ("-e py26", ['py26']),1765 ("-e py26,py33", ['py26', 'py33']),1766 ("-e py26,py26", ['py26', 'py26']),1767 ("-e py26,py33 -e py33,py27", ['py26', 'py33', 'py33', 'py27'])1768])1769def test_env_spec(cmdline, envlist):1770 args = cmdline.split()1771 config = parseconfig(args)1772 assert config.envlist == envlist1773class TestCommandParser:1774 def test_command_parser_for_word(self):1775 p = CommandParser('word')1776 # import pytest; pytest.set_trace()1777 assert list(p.words()) == ['word']1778 def test_command_parser_for_posargs(self):1779 p = CommandParser('[]')1780 assert list(p.words()) == ['[]']1781 def test_command_parser_for_multiple_words(self):1782 p = CommandParser('w1 w2 w3 ')1783 assert list(p.words()) == ['w1', ' ', 'w2', ' ', 'w3']1784 def test_command_parser_for_substitution_with_spaces(self):1785 p = CommandParser('{sub:something with spaces}')1786 assert list(p.words()) == ['{sub:something with spaces}']1787 def test_command_parser_with_complex_word_set(self):1788 complex_case = (1789 'word [] [literal] {something} {some:other thing} w{ord} w{or}d w{ord} '1790 'w{o:rd} w{o:r}d {w:or}d w[]ord {posargs:{a key}}')1791 p = CommandParser(complex_case)1792 parsed = list(p.words())1793 expected = [1794 'word', ' ', '[]', ' ', '[literal]', ' ', '{something}', ' ', '{some:other thing}',1795 ' ', 'w', '{ord}', ' ', 'w', '{or}', 'd', ' ', 'w', '{ord}', ' ', 'w', '{o:rd}', ' ',1796 'w', '{o:r}', 'd', ' ', '{w:or}', 'd',1797 ' ', 'w[]ord', ' ', '{posargs:{a key}}',1798 ]1799 assert parsed == expected1800 def test_command_with_runs_of_whitespace(self):1801 cmd = "cmd1 {item1}\n {item2}"1802 p = CommandParser(cmd)1803 parsed = list(p.words())1804 assert parsed == ['cmd1', ' ', '{item1}', '\n ', '{item2}']1805 def test_command_with_split_line_in_subst_arguments(self):1806 cmd = dedent(""" cmd2 {posargs:{item2}1807 other}""")1808 p = CommandParser(cmd)1809 parsed = list(p.words())1810 assert parsed == ['cmd2', ' ', '{posargs:{item2}\n other}']1811 def test_command_parsing_for_issue_10(self):1812 cmd = "nosetests -v -a !deferred --with-doctest []"1813 p = CommandParser(cmd)1814 parsed = list(p.words())1815 assert parsed == [1816 'nosetests', ' ', '-v', ' ', '-a', ' ', '!deferred', ' ',1817 '--with-doctest', ' ', '[]'1818 ]1819 @pytest.mark.skipif("sys.platform != 'win32'")1820 def test_commands_with_backslash(self, newconfig):1821 config = newconfig([r"hello\world"], """1822 [testenv:py26]1823 commands = some {posargs}1824 """)1825 envconfig = config.envconfigs["py26"]...

Full Screen

Full Screen

commands.py

Source:commands.py Github

copy

Full Screen

1"""2 lager.exec.commands3 Run commands in a docker container4"""5import subprocess6import platform7import os8import click9from ..config import (10 write_config_file,11 get_global_config_file_path,12 add_devenv_command,13 get_devenv_config,14 DEVENV_SECTION_NAME,15 LAGER_CONFIG_FILE_NAME,16)17from ..context import get_ci_environment, CIEnvironment, is_container_ci18from ..paramtypes import EnvVarType19def _run_command_host(section, path, cmd_to_run, mount, extra_args, debug, interactive, tty, user, group, macaddr, hostname, env, passenv):20 """21 Run a command from the host (which means, run it in a docker container)22 """23 full_command = ' '.join((cmd_to_run, *extra_args)).strip()24 image = section.get('image')25 source_dir = os.path.dirname(path)26 mount_dir = section.get('mount_dir')27 shell = section.get('shell')28 if debug:29 click.echo(full_command, err=True)30 env_vars = [var for var in os.environ if var.startswith('LAGER')]31 env_strings = [f'--env={var}={os.environ[var]}' for var in env_vars]32 base_command = ['docker', 'run', '--rm']33 if interactive:34 base_command.append('-i')35 if tty:36 base_command.append('-t')37 base_command.extend(env_strings)38 user_group_string = ''39 if user:40 user_group_string += user41 if group:42 user_group_string += f':{group}'43 if user_group_string:44 base_command.extend(['-u', user_group_string])45 global_config_path = get_global_config_file_path()46 if os.path.exists(global_config_path):47 base_command.extend([48 '--env=LAGER_CONFIG_FILE_DIR=/lager',49 '-v',50 f'{global_config_path}:/lager/{LAGER_CONFIG_FILE_NAME}'51 ])52 if mount:53 base_command.extend([54 '--mount',55 f'source={mount},target={mount_dir}',56 ])57 else:58 base_command.extend([59 '-v',60 f'{source_dir}:{mount_dir}',61 ])62 if macaddr:63 base_command.append(f'--mac-address={macaddr}')64 if hostname:65 base_command.append(f'--hostname={hostname}')66 for env_var in env:67 base_command.append(f'--env={env_var}')68 for var_name in passenv:69 if var_name in os.environ:70 base_command.append(f'--env={var_name}={os.environ[var_name]}')71 base_command.extend([72 '-w',73 mount_dir,74 image,75 shell,76 '-c',77 full_command78 ])79 proc = subprocess.run(base_command, check=False)80 return proc.returncode81def _run_command_container(section, cmd_to_run, extra_args, debug):82 """83 Run a command directly - assume we are in a container with all necessary software84 installed already.85 """86 shell = section.get('shell')87 full_command = ' '.join((cmd_to_run, *extra_args))88 if debug:89 click.echo(full_command, err=True)90 proc = subprocess.run([shell, '-c', full_command], check=False)91 return proc.returncode92def _run_command(section, path, cmd_to_run, mount, extra_args, debug, interactive, tty, user, group, macaddr, hostname, env, passenv):93 ci_env = get_ci_environment()94 if is_container_ci(ci_env):95 return _run_command_container(section, cmd_to_run, extra_args, debug)96 if ci_env in (CIEnvironment.HOST, CIEnvironment.JENKINS):97 return _run_command_host(section, path, cmd_to_run, mount, extra_args, debug, interactive, tty, user, group, macaddr, hostname, env, passenv)98 raise ValueError(f'Unknown CI environment {ci_env}')99@click.command(name='exec', context_settings={"ignore_unknown_options": True})100@click.pass_context101@click.argument('cmd_name', required=False, metavar='COMMAND')102@click.argument('extra_args', required=False, nargs=-1, metavar='EXTRA_ARGS')103@click.option('--command', help='Raw commandline to execute in docker container', metavar='\'<cmdline>\'')104@click.option('--save-as', default=None, help='Alias under which to save command specified with --command', metavar='<alias>', show_default=True)105@click.option('--warn/--no-warn', default=True, help='Whether to print a warning if overwriting an existing command.', show_default=True)106@click.option(107 '--env',108 multiple=True, type=EnvVarType(), help='Environment variables to set for the python script. '109 'Format is `--env FOO=BAR` - this will set an environment varialbe named `FOO` to the value `BAR`')110@click.option(111 '--passenv',112 multiple=True, help='Environment variables to inherit from the current environment and pass to the python script. '113 'This option is useful for secrets, tokens, passwords, or any other values that you do not want to appear on the '114 'command line. Example: `--passenv FOO` will set an environment variable named `FOO` in the python script to the value'115 'of `FOO` in the current environment.')116@click.option('--mount', '-m', help='Name of volume to mount', required=False)117@click.option('--interactive/--no-interactive', '-i', is_flag=True, help='Keep STDIN open even if not attached', default=True, show_default=True)118@click.option('--tty/--no-tty', '-t', is_flag=True, help='Allocate a pseudo-TTY', default=True, show_default=True)119@click.option('--user', '-u', help='User to run as in container', default=None)120@click.option('--group', '-g', help='Group to run as in container', default=None)121def exec_(ctx, cmd_name, extra_args, command, save_as, warn, env, passenv, mount, interactive, tty, user, group):122 """123 Execute COMMAND in a docker container. COMMAND is a named command which was previously saved using `--save-as`.124 If COMMAND is not provided, execute the command specified by --command. If --save-as is also provided,125 save the command under that name for later use with COMMAND. If EXTRA_ARGS are provided they will be appended126 to the command at runtime127 """128 if not cmd_name and not command:129 click.echo(exec_.get_help(ctx))130 ctx.exit(0)131 if user is None:132 try:133 user = str(os.getuid())134 except AttributeError:135 pass136 if group is None:137 try:138 group = str(os.getgid())139 except AttributeError:140 pass141 path, config = get_devenv_config()142 section = config[DEVENV_SECTION_NAME]143 if 'user' in section:144 user = section['user']145 if 'group' in section:146 group = section['group']147 macaddr = None148 if 'macaddr' in section:149 macaddr = section['macaddr']150 hostname = None151 if 'hostname' in section:152 hostname = section['hostname']153 if cmd_name and command:154 osname = platform.system()155 if osname == 'Windows':156 msg = 'If the command contains spaces, please wrap it in double quotes e.g. lager exec --command "ls -la"'157 else:158 msg = 'If the command contains spaces, please wrap it in single quotes e.g. lager exec --command \'ls -la\''159 raise click.UsageError(160 f'Cannot specify a command name and a command\n{msg}'161 )162 if cmd_name:163 key = f'cmd.{cmd_name}'164 if key not in section:165 raise click.UsageError(166 f'Command `{cmd_name}` not found',167 )168 cmd_to_run = section.get(key)169 else:170 cmd_to_run = command171 if save_as:172 add_devenv_command(section, save_as, cmd_to_run, warn)173 write_config_file(config, path)174 returncode = _run_command(section, path, cmd_to_run, mount, extra_args, ctx.obj.debug, interactive, tty, user, group, macaddr, hostname, env, passenv)...

Full Screen

Full Screen

private_registry.py

Source:private_registry.py Github

copy

Full Screen

1import os2import re3import base644import subprocess as sp5import requests as req6from pandas import DataFrame7from getpass import getpass8# import kivy9# kivy.require('1.0.6') # replace with your current kivy version !10# from kivy.app import App11# from kivy.uix.label import Label12# TODO: setup GUI to get input and display table of results; 13# See kivy for GUI: https://kivy.org/doc/stable/14# TODO: install password store and configure client environment to use password store15# TODO: install docker credentials helper in password store16class registry(object):17 #####################################################################18 def __init__(self, raw_url=None or str,username=None or str,passenv=None or str,passwd=None or str) -> None:19 """20 ## Docker Private Registry Tool:21 Interact with your private docker registry using this tool. 22 - access registry23 - print contents of private registry24 #### Create 3 environmentals in on your system for 25 - the private registry url environment variable26 - the private registry username environment variable27 - the private registry password store token environment variable28 :param raw_url: the private registry url environment variable29 :param username: the private registry username environment variable30 :param passenv: the private registry password store token environment variable31 :param passwd: the base64 encoded password string32 """33 try:34 raw_url = os.environ[raw_url]35 username = os.environ[username]36 passenv = os.environ[passenv]37 # print('URL: {}\nUSER: {}\nPASSENV: {}\n'.format(raw_url,username,passenv))38 self.raw_url = raw_url39 self.username = username40 self.passenv = passenv41 self.passwd = passwd42 # print('password: {}'.format(passwd))43 # super().__init__()44 except OSError as err:45 print('\nTheir was an error in your environment variable; parameter 2. \n{}'.format(err))46 except Exception as err: # last line of defense47 print('\nAn exception has occured.\n{}'.format(err))48 ##################################################################### 49 def get_registry(self,raw_url=None,username=None,passenv=None) -> DataFrame:50 """51 Gets the contents of your private container registry and organizes them into a table.52 This function uses "pass" as its password store. It takes your password store path to user password and accesses your password store securely.53 54 :param raw_url: the private registry url environment variable55 :param username: the private registry username environment variable56 :param passenv: the private registry password store token environment variable57 """58 tbl = []59 raw_url = self.raw_url if raw_url is None else os.environ[raw_url]60 username = self.username if username is None else os.environ[username]61 passenv = self.passenv if passenv is None else os.environ[passenv]62 try:63 ##############################################################64 url = raw_url if re.search('/v2', raw_url) else '{}/v2'.format(raw_url)65 # rauth = passenv if os.environ[passenv] is None else os.environ[passenv]66 rauth = passenv if re.search('docker-credential-helpers',passenv) else os.environ[passenv]67 # print('Docker Credential Token: {}\n'.format(rauth))68 # we are using a password store to access passwords on needed69 passwd = sp.check_output(["pass", rauth])70 passwd = passwd.decode("utf-8")71 # username = input("Enter Username: ")72 # passw = getpass("Enter Password: ")73 # print(passwd)74 uauth = (username,passwd)75 catelog = '{}/_catalog/'.format(url)76 # print(catelog)77 catelog = req.get(catelog, auth=uauth,timeout=(5, 10)) 78 # print(catelog.json())79 for a in catelog.json()['repositories']:80 # print(a)81 item_details = '{0}/{1}/tags/list/'.format(url,a)82 rsp = req.get(item_details, auth=uauth)83 json_rsp = rsp.json()84 # print(json_rsp)85 tbl.append(json_rsp)86 # print('[{} => {}]'.format(json_rsp['name'], json_rsp['tags']))87 # print(tbl)88 df = DataFrame(data=tbl)89 print('\n{}\n'.format(df))90 return df91 except req.exceptions.TooManyRedirects as err:92 print('{}'.format(err))93 except req.exceptions.ConnectionError as err:94 print('\nSorry, unable to connect to {}.\n\n{}'.format(raw_url,err)) 95 except req.exceptions.URLRequired as err:96 print('{}'.format(err))97 except req.exceptions.StreamConsumedError as err:98 print('{}'.format(err))99 except req.exceptions.ConnectTimeout as err:100 print('{}'.format(err))101 except req.exceptions.HTTPError as err:102 print('{}'.format(err))103 except req.exceptions.RequestException as err:104 print('{}'.format(err))105 except req.exceptions.Timeout as err:106 print('\nI\'m so sorry but the server request timed out...\n\n{}'.format(err))107 except OSError as err:108 print('\nTheir was an error in your environment variable; parameter 2. \n{}'.format(err))109 except KeyError as err:110 print(f'\nThe environment variable {err} does not match any found in our system.\n')111 except Exception as err: # last line of defense112 print('\nAn exception has occured.\n\n{}'.format(err))113 #####################################################################114#########################################################################115if __name__ == '__main__':116 # Create 3 environmentals in on your system for 117 # - the private registry url118 # - the private registry username119 # - the private registry password store token120 # Gets a table of your private registry objects121 url = 'PRIVATE_REGISTRY_URL'122 usr = 'PRIVATE_REGISTRY_USER'123 envpass = 'PRIVATE_REGISTRY_AUTH'124 reg = registry(url,usr,envpass)...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run tox automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful