test_basic.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import uuid
  4. import click
  5. def test_basic_functionality(runner):
  6. @click.command()
  7. def cli():
  8. """Hello World!"""
  9. click.echo("I EXECUTED")
  10. result = runner.invoke(cli, ["--help"])
  11. assert not result.exception
  12. assert "Hello World!" in result.output
  13. assert "Show this message and exit." in result.output
  14. assert result.exit_code == 0
  15. assert "I EXECUTED" not in result.output
  16. result = runner.invoke(cli, [])
  17. assert not result.exception
  18. assert "I EXECUTED" in result.output
  19. assert result.exit_code == 0
  20. def test_repr():
  21. @click.command()
  22. def command():
  23. pass
  24. @click.group()
  25. def group():
  26. pass
  27. @group.command()
  28. def subcommand():
  29. pass
  30. assert repr(command) == "<Command command>"
  31. assert repr(group) == "<Group group>"
  32. assert repr(subcommand) == "<Command subcommand>"
  33. def test_return_values():
  34. @click.command()
  35. def cli():
  36. return 42
  37. with cli.make_context("foo", []) as ctx:
  38. rv = cli.invoke(ctx)
  39. assert rv == 42
  40. def test_basic_group(runner):
  41. @click.group()
  42. def cli():
  43. """This is the root."""
  44. click.echo("ROOT EXECUTED")
  45. @cli.command()
  46. def subcommand():
  47. """This is a subcommand."""
  48. click.echo("SUBCOMMAND EXECUTED")
  49. result = runner.invoke(cli, ["--help"])
  50. assert not result.exception
  51. assert "COMMAND [ARGS]..." in result.output
  52. assert "This is the root" in result.output
  53. assert "This is a subcommand." in result.output
  54. assert result.exit_code == 0
  55. assert "ROOT EXECUTED" not in result.output
  56. result = runner.invoke(cli, ["subcommand"])
  57. assert not result.exception
  58. assert result.exit_code == 0
  59. assert "ROOT EXECUTED" in result.output
  60. assert "SUBCOMMAND EXECUTED" in result.output
  61. def test_basic_option(runner):
  62. @click.command()
  63. @click.option("--foo", default="no value")
  64. def cli(foo):
  65. click.echo(u"FOO:[{}]".format(foo))
  66. result = runner.invoke(cli, [])
  67. assert not result.exception
  68. assert "FOO:[no value]" in result.output
  69. result = runner.invoke(cli, ["--foo=42"])
  70. assert not result.exception
  71. assert "FOO:[42]" in result.output
  72. result = runner.invoke(cli, ["--foo"])
  73. assert result.exception
  74. assert "--foo option requires an argument" in result.output
  75. result = runner.invoke(cli, ["--foo="])
  76. assert not result.exception
  77. assert "FOO:[]" in result.output
  78. result = runner.invoke(cli, [u"--foo=\N{SNOWMAN}"])
  79. assert not result.exception
  80. assert u"FOO:[\N{SNOWMAN}]" in result.output
  81. def test_int_option(runner):
  82. @click.command()
  83. @click.option("--foo", default=42)
  84. def cli(foo):
  85. click.echo("FOO:[{}]".format(foo * 2))
  86. result = runner.invoke(cli, [])
  87. assert not result.exception
  88. assert "FOO:[84]" in result.output
  89. result = runner.invoke(cli, ["--foo=23"])
  90. assert not result.exception
  91. assert "FOO:[46]" in result.output
  92. result = runner.invoke(cli, ["--foo=bar"])
  93. assert result.exception
  94. assert "Invalid value for '--foo': bar is not a valid integer" in result.output
  95. def test_uuid_option(runner):
  96. @click.command()
  97. @click.option(
  98. "--u", default="ba122011-349f-423b-873b-9d6a79c688ab", type=click.UUID
  99. )
  100. def cli(u):
  101. assert type(u) is uuid.UUID
  102. click.echo("U:[{}]".format(u))
  103. result = runner.invoke(cli, [])
  104. assert not result.exception
  105. assert "U:[ba122011-349f-423b-873b-9d6a79c688ab]" in result.output
  106. result = runner.invoke(cli, ["--u=821592c1-c50e-4971-9cd6-e89dc6832f86"])
  107. assert not result.exception
  108. assert "U:[821592c1-c50e-4971-9cd6-e89dc6832f86]" in result.output
  109. result = runner.invoke(cli, ["--u=bar"])
  110. assert result.exception
  111. assert "Invalid value for '--u': bar is not a valid UUID value" in result.output
  112. def test_float_option(runner):
  113. @click.command()
  114. @click.option("--foo", default=42, type=click.FLOAT)
  115. def cli(foo):
  116. assert type(foo) is float
  117. click.echo("FOO:[{}]".format(foo))
  118. result = runner.invoke(cli, [])
  119. assert not result.exception
  120. assert "FOO:[42.0]" in result.output
  121. result = runner.invoke(cli, ["--foo=23.5"])
  122. assert not result.exception
  123. assert "FOO:[23.5]" in result.output
  124. result = runner.invoke(cli, ["--foo=bar"])
  125. assert result.exception
  126. assert "Invalid value for '--foo': bar is not a valid float" in result.output
  127. def test_boolean_option(runner):
  128. for default in True, False:
  129. @click.command()
  130. @click.option("--with-foo/--without-foo", default=default)
  131. def cli(with_foo):
  132. click.echo(with_foo)
  133. result = runner.invoke(cli, ["--with-foo"])
  134. assert not result.exception
  135. assert result.output == "True\n"
  136. result = runner.invoke(cli, ["--without-foo"])
  137. assert not result.exception
  138. assert result.output == "False\n"
  139. result = runner.invoke(cli, [])
  140. assert not result.exception
  141. assert result.output == "{}\n".format(default)
  142. for default in True, False:
  143. @click.command()
  144. @click.option("--flag", is_flag=True, default=default)
  145. def cli(flag):
  146. click.echo(flag)
  147. result = runner.invoke(cli, ["--flag"])
  148. assert not result.exception
  149. assert result.output == "{}\n".format(not default)
  150. result = runner.invoke(cli, [])
  151. assert not result.exception
  152. assert result.output == "{}\n".format(default)
  153. def test_boolean_conversion(runner):
  154. for default in True, False:
  155. @click.command()
  156. @click.option("--flag", default=default, type=bool)
  157. def cli(flag):
  158. click.echo(flag)
  159. for value in "true", "t", "1", "yes", "y":
  160. result = runner.invoke(cli, ["--flag", value])
  161. assert not result.exception
  162. assert result.output == "True\n"
  163. for value in "false", "f", "0", "no", "n":
  164. result = runner.invoke(cli, ["--flag", value])
  165. assert not result.exception
  166. assert result.output == "False\n"
  167. result = runner.invoke(cli, [])
  168. assert not result.exception
  169. assert result.output == "{}\n".format(default)
  170. def test_file_option(runner):
  171. @click.command()
  172. @click.option("--file", type=click.File("w"))
  173. def input(file):
  174. file.write("Hello World!\n")
  175. @click.command()
  176. @click.option("--file", type=click.File("r"))
  177. def output(file):
  178. click.echo(file.read())
  179. with runner.isolated_filesystem():
  180. result_in = runner.invoke(input, ["--file=example.txt"])
  181. result_out = runner.invoke(output, ["--file=example.txt"])
  182. assert not result_in.exception
  183. assert result_in.output == ""
  184. assert not result_out.exception
  185. assert result_out.output == "Hello World!\n\n"
  186. def test_file_lazy_mode(runner):
  187. do_io = False
  188. @click.command()
  189. @click.option("--file", type=click.File("w"))
  190. def input(file):
  191. if do_io:
  192. file.write("Hello World!\n")
  193. @click.command()
  194. @click.option("--file", type=click.File("r"))
  195. def output(file):
  196. pass
  197. with runner.isolated_filesystem():
  198. os.mkdir("example.txt")
  199. do_io = True
  200. result_in = runner.invoke(input, ["--file=example.txt"])
  201. assert result_in.exit_code == 1
  202. do_io = False
  203. result_in = runner.invoke(input, ["--file=example.txt"])
  204. assert result_in.exit_code == 0
  205. result_out = runner.invoke(output, ["--file=example.txt"])
  206. assert result_out.exception
  207. @click.command()
  208. @click.option("--file", type=click.File("w", lazy=False))
  209. def input_non_lazy(file):
  210. file.write("Hello World!\n")
  211. with runner.isolated_filesystem():
  212. os.mkdir("example.txt")
  213. result_in = runner.invoke(input_non_lazy, ["--file=example.txt"])
  214. assert result_in.exit_code == 2
  215. assert (
  216. "Invalid value for '--file': Could not open file: example.txt"
  217. in result_in.output
  218. )
  219. def test_path_option(runner):
  220. @click.command()
  221. @click.option("-O", type=click.Path(file_okay=False, exists=True, writable=True))
  222. def write_to_dir(o):
  223. with open(os.path.join(o, "foo.txt"), "wb") as f:
  224. f.write(b"meh\n")
  225. with runner.isolated_filesystem():
  226. os.mkdir("test")
  227. result = runner.invoke(write_to_dir, ["-O", "test"])
  228. assert not result.exception
  229. with open("test/foo.txt", "rb") as f:
  230. assert f.read() == b"meh\n"
  231. result = runner.invoke(write_to_dir, ["-O", "test/foo.txt"])
  232. assert "is a file" in result.output
  233. @click.command()
  234. @click.option("-f", type=click.Path(exists=True))
  235. def showtype(f):
  236. click.echo("is_file={}".format(os.path.isfile(f)))
  237. click.echo("is_dir={}".format(os.path.isdir(f)))
  238. with runner.isolated_filesystem():
  239. result = runner.invoke(showtype, ["-f", "xxx"])
  240. assert "does not exist" in result.output
  241. result = runner.invoke(showtype, ["-f", "."])
  242. assert "is_file=False" in result.output
  243. assert "is_dir=True" in result.output
  244. @click.command()
  245. @click.option("-f", type=click.Path())
  246. def exists(f):
  247. click.echo("exists={}".format(os.path.exists(f)))
  248. with runner.isolated_filesystem():
  249. result = runner.invoke(exists, ["-f", "xxx"])
  250. assert "exists=False" in result.output
  251. result = runner.invoke(exists, ["-f", "."])
  252. assert "exists=True" in result.output
  253. def test_choice_option(runner):
  254. @click.command()
  255. @click.option("--method", type=click.Choice(["foo", "bar", "baz"]))
  256. def cli(method):
  257. click.echo(method)
  258. result = runner.invoke(cli, ["--method=foo"])
  259. assert not result.exception
  260. assert result.output == "foo\n"
  261. result = runner.invoke(cli, ["--method=meh"])
  262. assert result.exit_code == 2
  263. assert (
  264. "Invalid value for '--method': invalid choice: meh."
  265. " (choose from foo, bar, baz)" in result.output
  266. )
  267. result = runner.invoke(cli, ["--help"])
  268. assert "--method [foo|bar|baz]" in result.output
  269. def test_datetime_option_default(runner):
  270. @click.command()
  271. @click.option("--start_date", type=click.DateTime())
  272. def cli(start_date):
  273. click.echo(start_date.strftime("%Y-%m-%dT%H:%M:%S"))
  274. result = runner.invoke(cli, ["--start_date=2015-09-29"])
  275. assert not result.exception
  276. assert result.output == "2015-09-29T00:00:00\n"
  277. result = runner.invoke(cli, ["--start_date=2015-09-29T09:11:22"])
  278. assert not result.exception
  279. assert result.output == "2015-09-29T09:11:22\n"
  280. result = runner.invoke(cli, ["--start_date=2015-09"])
  281. assert result.exit_code == 2
  282. assert (
  283. "Invalid value for '--start_date':"
  284. " invalid datetime format: 2015-09."
  285. " (choose from %Y-%m-%d, %Y-%m-%dT%H:%M:%S, %Y-%m-%d %H:%M:%S)"
  286. ) in result.output
  287. result = runner.invoke(cli, ["--help"])
  288. assert (
  289. "--start_date [%Y-%m-%d|%Y-%m-%dT%H:%M:%S|%Y-%m-%d %H:%M:%S]" in result.output
  290. )
  291. def test_datetime_option_custom(runner):
  292. @click.command()
  293. @click.option("--start_date", type=click.DateTime(formats=["%A %B %d, %Y"]))
  294. def cli(start_date):
  295. click.echo(start_date.strftime("%Y-%m-%dT%H:%M:%S"))
  296. result = runner.invoke(cli, ["--start_date=Wednesday June 05, 2010"])
  297. assert not result.exception
  298. assert result.output == "2010-06-05T00:00:00\n"
  299. def test_int_range_option(runner):
  300. @click.command()
  301. @click.option("--x", type=click.IntRange(0, 5))
  302. def cli(x):
  303. click.echo(x)
  304. result = runner.invoke(cli, ["--x=5"])
  305. assert not result.exception
  306. assert result.output == "5\n"
  307. result = runner.invoke(cli, ["--x=6"])
  308. assert result.exit_code == 2
  309. assert (
  310. "Invalid value for '--x': 6 is not in the valid range of 0 to 5.\n"
  311. in result.output
  312. )
  313. @click.command()
  314. @click.option("--x", type=click.IntRange(0, 5, clamp=True))
  315. def clamp(x):
  316. click.echo(x)
  317. result = runner.invoke(clamp, ["--x=5"])
  318. assert not result.exception
  319. assert result.output == "5\n"
  320. result = runner.invoke(clamp, ["--x=6"])
  321. assert not result.exception
  322. assert result.output == "5\n"
  323. result = runner.invoke(clamp, ["--x=-1"])
  324. assert not result.exception
  325. assert result.output == "0\n"
  326. def test_float_range_option(runner):
  327. @click.command()
  328. @click.option("--x", type=click.FloatRange(0, 5))
  329. def cli(x):
  330. click.echo(x)
  331. result = runner.invoke(cli, ["--x=5.0"])
  332. assert not result.exception
  333. assert result.output == "5.0\n"
  334. result = runner.invoke(cli, ["--x=6.0"])
  335. assert result.exit_code == 2
  336. assert (
  337. "Invalid value for '--x': 6.0 is not in the valid range of 0 to 5.\n"
  338. in result.output
  339. )
  340. @click.command()
  341. @click.option("--x", type=click.FloatRange(0, 5, clamp=True))
  342. def clamp(x):
  343. click.echo(x)
  344. result = runner.invoke(clamp, ["--x=5.0"])
  345. assert not result.exception
  346. assert result.output == "5.0\n"
  347. result = runner.invoke(clamp, ["--x=6.0"])
  348. assert not result.exception
  349. assert result.output == "5\n"
  350. result = runner.invoke(clamp, ["--x=-1.0"])
  351. assert not result.exception
  352. assert result.output == "0\n"
  353. def test_required_option(runner):
  354. @click.command()
  355. @click.option("--foo", required=True)
  356. def cli(foo):
  357. click.echo(foo)
  358. result = runner.invoke(cli, [])
  359. assert result.exit_code == 2
  360. assert "Missing option '--foo'" in result.output
  361. def test_evaluation_order(runner):
  362. called = []
  363. def memo(ctx, param, value):
  364. called.append(value)
  365. return value
  366. @click.command()
  367. @click.option("--missing", default="missing", is_eager=False, callback=memo)
  368. @click.option("--eager-flag1", flag_value="eager1", is_eager=True, callback=memo)
  369. @click.option("--eager-flag2", flag_value="eager2", is_eager=True, callback=memo)
  370. @click.option("--eager-flag3", flag_value="eager3", is_eager=True, callback=memo)
  371. @click.option("--normal-flag1", flag_value="normal1", is_eager=False, callback=memo)
  372. @click.option("--normal-flag2", flag_value="normal2", is_eager=False, callback=memo)
  373. @click.option("--normal-flag3", flag_value="normal3", is_eager=False, callback=memo)
  374. def cli(**x):
  375. pass
  376. result = runner.invoke(
  377. cli,
  378. [
  379. "--eager-flag2",
  380. "--eager-flag1",
  381. "--normal-flag2",
  382. "--eager-flag3",
  383. "--normal-flag3",
  384. "--normal-flag3",
  385. "--normal-flag1",
  386. "--normal-flag1",
  387. ],
  388. )
  389. assert not result.exception
  390. assert called == [
  391. "eager2",
  392. "eager1",
  393. "eager3",
  394. "normal2",
  395. "normal3",
  396. "normal1",
  397. "missing",
  398. ]
  399. def test_hidden_option(runner):
  400. @click.command()
  401. @click.option("--nope", hidden=True)
  402. def cli(nope):
  403. click.echo(nope)
  404. result = runner.invoke(cli, ["--help"])
  405. assert result.exit_code == 0
  406. assert "--nope" not in result.output
  407. def test_hidden_command(runner):
  408. @click.group()
  409. def cli():
  410. pass
  411. @cli.command(hidden=True)
  412. def nope():
  413. pass
  414. result = runner.invoke(cli, ["--help"])
  415. assert result.exit_code == 0
  416. assert "nope" not in result.output
  417. def test_hidden_group(runner):
  418. @click.group()
  419. def cli():
  420. pass
  421. @cli.group(hidden=True)
  422. def subgroup():
  423. pass
  424. @subgroup.command()
  425. def nope():
  426. pass
  427. result = runner.invoke(cli, ["--help"])
  428. assert result.exit_code == 0
  429. assert "subgroup" not in result.output
  430. assert "nope" not in result.output