You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

142 lines
3.8 KiB

  1. import os
  2. import sys
  3. from subprocess import Popen
  4. from typing import Any, Dict, List # noqa
  5. try:
  6. import click
  7. except ImportError:
  8. sys.stderr.write('It seems python-dotenv is not installed with cli option. \n'
  9. 'Run pip install "python-dotenv[cli]" to fix this.')
  10. sys.exit(1)
  11. from .main import dotenv_values, get_key, set_key, unset_key
  12. from .version import __version__
  13. @click.group()
  14. @click.option('-f', '--file', default=os.path.join(os.getcwd(), '.env'),
  15. type=click.Path(exists=True),
  16. help="Location of the .env file, defaults to .env file in current working directory.")
  17. @click.option('-q', '--quote', default='always',
  18. type=click.Choice(['always', 'never', 'auto']),
  19. help="Whether to quote or not the variable values. Default mode is always. This does not affect parsing.")
  20. @click.version_option(version=__version__)
  21. @click.pass_context
  22. def cli(ctx, file, quote):
  23. # type: (click.Context, Any, Any) -> None
  24. '''This script is used to set, get or unset values from a .env file.'''
  25. ctx.obj = {}
  26. ctx.obj['FILE'] = file
  27. ctx.obj['QUOTE'] = quote
  28. @cli.command()
  29. @click.pass_context
  30. def list(ctx):
  31. # type: (click.Context) -> None
  32. '''Display all the stored key/value.'''
  33. file = ctx.obj['FILE']
  34. dotenv_as_dict = dotenv_values(file)
  35. for k, v in dotenv_as_dict.items():
  36. click.echo('%s=%s' % (k, v))
  37. @cli.command()
  38. @click.pass_context
  39. @click.argument('key', required=True)
  40. @click.argument('value', required=True)
  41. def set(ctx, key, value):
  42. # type: (click.Context, Any, Any) -> None
  43. '''Store the given key/value.'''
  44. file = ctx.obj['FILE']
  45. quote = ctx.obj['QUOTE']
  46. success, key, value = set_key(file, key, value, quote)
  47. if success:
  48. click.echo('%s=%s' % (key, value))
  49. else:
  50. exit(1)
  51. @cli.command()
  52. @click.pass_context
  53. @click.argument('key', required=True)
  54. def get(ctx, key):
  55. # type: (click.Context, Any) -> None
  56. '''Retrieve the value for the given key.'''
  57. file = ctx.obj['FILE']
  58. stored_value = get_key(file, key)
  59. if stored_value:
  60. click.echo('%s=%s' % (key, stored_value))
  61. else:
  62. exit(1)
  63. @cli.command()
  64. @click.pass_context
  65. @click.argument('key', required=True)
  66. def unset(ctx, key):
  67. # type: (click.Context, Any) -> None
  68. '''Removes the given key.'''
  69. file = ctx.obj['FILE']
  70. quote = ctx.obj['QUOTE']
  71. success, key = unset_key(file, key, quote)
  72. if success:
  73. click.echo("Successfully removed %s" % key)
  74. else:
  75. exit(1)
  76. @cli.command(context_settings={'ignore_unknown_options': True})
  77. @click.pass_context
  78. @click.argument('commandline', nargs=-1, type=click.UNPROCESSED)
  79. def run(ctx, commandline):
  80. # type: (click.Context, List[str]) -> None
  81. """Run command with environment variables present."""
  82. file = ctx.obj['FILE']
  83. dotenv_as_dict = dotenv_values(file)
  84. if not commandline:
  85. click.echo('No command given.')
  86. exit(1)
  87. ret = run_command(commandline, dotenv_as_dict) # type: ignore
  88. exit(ret)
  89. def run_command(command, env):
  90. # type: (List[str], Dict[str, str]) -> int
  91. """Run command in sub process.
  92. Runs the command in a sub process with the variables from `env`
  93. added in the current environment variables.
  94. Parameters
  95. ----------
  96. command: List[str]
  97. The command and it's parameters
  98. env: Dict
  99. The additional environment variables
  100. Returns
  101. -------
  102. int
  103. The return code of the command
  104. """
  105. # copy the current environment variables and add the vales from
  106. # `env`
  107. cmd_env = os.environ.copy()
  108. cmd_env.update(env)
  109. p = Popen(command,
  110. universal_newlines=True,
  111. bufsize=0,
  112. shell=False,
  113. env=cmd_env)
  114. _, _ = p.communicate()
  115. return p.returncode
  116. if __name__ == "__main__":
  117. cli()