33import shlex
44import sys
55from contextlib import contextmanager
6- from typing import Any , Dict , IO , Iterator , List , Optional
6+ from typing import IO , Any , Dict , Iterator , List , Optional
77
8- if sys .platform == ' win32' :
8+ if sys .platform == " win32" :
99 from subprocess import Popen
1010
1111try :
1212 import click
1313except ImportError :
14- sys .stderr .write ('It seems python-dotenv is not installed with cli option. \n '
15- 'Run pip install "python-dotenv[cli]" to fix this.' )
14+ sys .stderr .write (
15+ "It seems python-dotenv is not installed with cli option. \n "
16+ 'Run pip install "python-dotenv[cli]" to fix this.'
17+ )
1618 sys .exit (1 )
1719
1820from .main import dotenv_values , set_key , unset_key
@@ -29,25 +31,37 @@ def enumerate_env() -> Optional[str]:
2931 cwd = os .getcwd ()
3032 except FileNotFoundError :
3133 return None
32- path = os .path .join (cwd , ' .env' )
34+ path = os .path .join (cwd , " .env" )
3335 return path
3436
3537
3638@click .group ()
37- @click .option ('-f' , '--file' , default = enumerate_env (),
38- type = click .Path (file_okay = True ),
39- help = "Location of the .env file, defaults to .env file in current working directory." )
40- @click .option ('-q' , '--quote' , default = 'always' ,
41- type = click .Choice (['always' , 'never' , 'auto' ]),
42- help = "Whether to quote or not the variable values. Default mode is always. This does not affect parsing." )
43- @click .option ('-e' , '--export' , default = False ,
44- type = click .BOOL ,
45- help = "Whether to write the dot file as an executable bash script." )
39+ @click .option (
40+ "-f" ,
41+ "--file" ,
42+ default = enumerate_env (),
43+ type = click .Path (file_okay = True ),
44+ help = "Location of the .env file, defaults to .env file in current working directory." ,
45+ )
46+ @click .option (
47+ "-q" ,
48+ "--quote" ,
49+ default = "always" ,
50+ type = click .Choice (["always" , "never" , "auto" ]),
51+ help = "Whether to quote or not the variable values. Default mode is always. This does not affect parsing." ,
52+ )
53+ @click .option (
54+ "-e" ,
55+ "--export" ,
56+ default = False ,
57+ type = click .BOOL ,
58+ help = "Whether to write the dot file as an executable bash script." ,
59+ )
4660@click .version_option (version = __version__ )
4761@click .pass_context
4862def cli (ctx : click .Context , file : Any , quote : Any , export : Any ) -> None :
4963 """This script is used to set, get or unset values from a .env file."""
50- ctx .obj = {' QUOTE' : quote , ' EXPORT' : export , ' FILE' : file }
64+ ctx .obj = {" QUOTE" : quote , " EXPORT" : export , " FILE" : file }
5165
5266
5367@contextmanager
@@ -66,53 +80,57 @@ def stream_file(path: os.PathLike) -> Iterator[IO[str]]:
6680 exit (2 )
6781
6882
69- @cli .command ()
83+ @cli .command (name = "list" )
7084@click .pass_context
71- @click .option ('--format' , default = 'simple' ,
72- type = click .Choice (['simple' , 'json' , 'shell' , 'export' ]),
73- help = "The format in which to display the list. Default format is simple, "
74- "which displays name=value without quotes." )
75- def list (ctx : click .Context , format : bool ) -> None :
85+ @click .option (
86+ "--format" ,
87+ "output_format" ,
88+ default = "simple" ,
89+ type = click .Choice (["simple" , "json" , "shell" , "export" ]),
90+ help = "The format in which to display the list. Default format is simple, "
91+ "which displays name=value without quotes." ,
92+ )
93+ def list_values (ctx : click .Context , output_format : str ) -> None :
7694 """Display all the stored key/value."""
77- file = ctx .obj [' FILE' ]
95+ file = ctx .obj [" FILE" ]
7896
7997 with stream_file (file ) as stream :
8098 values = dotenv_values (stream = stream )
8199
82- if format == ' json' :
100+ if output_format == " json" :
83101 click .echo (json .dumps (values , indent = 2 , sort_keys = True ))
84102 else :
85- prefix = ' export ' if format == ' export' else ''
103+ prefix = " export " if output_format == " export" else ""
86104 for k in sorted (values ):
87105 v = values [k ]
88106 if v is not None :
89- if format in (' export' , ' shell' ):
107+ if output_format in (" export" , " shell" ):
90108 v = shlex .quote (v )
91- click .echo (f' { prefix } { k } ={ v } ' )
109+ click .echo (f" { prefix } { k } ={ v } " )
92110
93111
94- @cli .command ()
112+ @cli .command (name = "set" )
95113@click .pass_context
96- @click .argument (' key' , required = True )
97- @click .argument (' value' , required = True )
98- def set (ctx : click .Context , key : Any , value : Any ) -> None :
114+ @click .argument (" key" , required = True )
115+ @click .argument (" value" , required = True )
116+ def set_value (ctx : click .Context , key : Any , value : Any ) -> None :
99117 """Store the given key/value."""
100- file = ctx .obj [' FILE' ]
101- quote = ctx .obj [' QUOTE' ]
102- export = ctx .obj [' EXPORT' ]
118+ file = ctx .obj [" FILE" ]
119+ quote = ctx .obj [" QUOTE" ]
120+ export = ctx .obj [" EXPORT" ]
103121 success , key , value = set_key (file , key , value , quote , export )
104122 if success :
105- click .echo (f' { key } ={ value } ' )
123+ click .echo (f" { key } ={ value } " )
106124 else :
107125 exit (1 )
108126
109127
110128@cli .command ()
111129@click .pass_context
112- @click .argument (' key' , required = True )
130+ @click .argument (" key" , required = True )
113131def get (ctx : click .Context , key : Any ) -> None :
114132 """Retrieve the value for the given key."""
115- file = ctx .obj [' FILE' ]
133+ file = ctx .obj [" FILE" ]
116134
117135 with stream_file (file ) as stream :
118136 values = dotenv_values (stream = stream )
@@ -126,33 +144,32 @@ def get(ctx: click.Context, key: Any) -> None:
126144
127145@cli .command ()
128146@click .pass_context
129- @click .argument (' key' , required = True )
147+ @click .argument (" key" , required = True )
130148def unset (ctx : click .Context , key : Any ) -> None :
131149 """Removes the given key."""
132- file = ctx .obj [' FILE' ]
133- quote = ctx .obj [' QUOTE' ]
150+ file = ctx .obj [" FILE" ]
151+ quote = ctx .obj [" QUOTE" ]
134152 success , key = unset_key (file , key , quote )
135153 if success :
136154 click .echo (f"Successfully removed { key } " )
137155 else :
138156 exit (1 )
139157
140158
141- @cli .command (context_settings = {' ignore_unknown_options' : True })
159+ @cli .command (context_settings = {" ignore_unknown_options" : True })
142160@click .pass_context
143161@click .option (
144162 "--override/--no-override" ,
145163 default = True ,
146164 help = "Override variables from the environment file with those from the .env file." ,
147165)
148- @click .argument (' commandline' , nargs = - 1 , type = click .UNPROCESSED )
166+ @click .argument (" commandline" , nargs = - 1 , type = click .UNPROCESSED )
149167def run (ctx : click .Context , override : bool , commandline : List [str ]) -> None :
150168 """Run command with environment variables present."""
151- file = ctx .obj [' FILE' ]
169+ file = ctx .obj [" FILE" ]
152170 if not os .path .isfile (file ):
153171 raise click .BadParameter (
154- f'Invalid value for \' -f\' "{ file } " does not exist.' ,
155- ctx = ctx
172+ f"Invalid value for '-f' \" { file } \" does not exist." , ctx = ctx
156173 )
157174 dotenv_as_dict = {
158175 k : v
@@ -161,7 +178,7 @@ def run(ctx: click.Context, override: bool, commandline: List[str]) -> None:
161178 }
162179
163180 if not commandline :
164- click .echo (' No command given.' )
181+ click .echo (" No command given." )
165182 exit (1 )
166183 run_command (commandline , dotenv_as_dict )
167184
@@ -190,14 +207,10 @@ def run_command(command: List[str], env: Dict[str, str]) -> None:
190207 cmd_env = os .environ .copy ()
191208 cmd_env .update (env )
192209
193- if sys .platform == ' win32' :
210+ if sys .platform == " win32" :
194211 # execvpe on Windows returns control immediately
195212 # rather than once the command has finished.
196- p = Popen (command ,
197- universal_newlines = True ,
198- bufsize = 0 ,
199- shell = False ,
200- env = cmd_env )
213+ p = Popen (command , universal_newlines = True , bufsize = 0 , shell = False , env = cmd_env )
201214 _ , _ = p .communicate ()
202215
203216 exit (p .returncode )
0 commit comments