77class Formatter (string .Formatter ):
88 """A extended string formatter class to parse habitat configurations.
99
10- Adds support for the "!e" conversion flag. This will fill in the key as a properly
11- formatted environment variable specifier. For example ''{PATH!e}'' will be converted
12- to ``$PATH`` for the sh language, and ``%env:PATH`` for the ps language. You can
13- convert "!e" to "!s" by setting expand to True. This simulates `os.path.expandvars`.
10+ Adds support for the ``!e`` `conversion field`_. This will fill in the key as a
11+ properly formatted environment variable specifier. For example ``{PATH!e}`` will
12+ be converted to ``$PATH`` for the sh language, and ``%env:PATH`` for the ps language.
13+
14+ By setting expand to True the ``!e`` conversion field will be filled in with the
15+ environment variable for that key if the env variable is set. Otherwise it will
16+ fall back the environment variable specifier.
1417
1518 This also converts ``{;}`` to the language specific path separator for environment
1619 variables. On linux this is ``:`` on windows(even in bash) this is ``;``.
1720
18- You need to specify the desired language when initializing this class. This can be
19- one of the supported language keys in ''Formatter.shell_formats'', or you can pass
20- a file extension supported by `Formatter.language_from_ext`. If you pass None, it
21- will preserve the formatting markers so it can be converted later.
21+ Parameters:
22+ language: Specify the shell language to use when converting ``!e``. See
23+ :py:const:`Formatter.shell_formats` and :py:meth:`Formatter.language_from_ext`.
24+ for supported values. If you pass None, it will preserve the
25+ formatting markers so it can be converted later.
26+ expand(bool, optional): Should the ``!e`` conversion insert the shell
27+ environment variable specifier or the value of the env var?
28+
29+ .. _conversion field:
30+ https://docs.python.org/3/library/string.html#grammar-token-format-string-conversion
2231 """
2332
2433 shell_formats = {
@@ -50,28 +59,35 @@ class Formatter(string.Formatter):
5059 ";" : "{;}" ,
5160 },
5261 }
62+ """Information on how to generate shell specific environment variable references
63+ and the character to use for pathsep. For each shell ``env_var`` is a format
64+ string that accepts the env var name. ``;`` is the path separator to use.
65+ """
5366
5467 def __init__ (self , language , expand = False ):
5568 super ().__init__ ()
5669 self .language = self .language_from_ext (language )
57- self .current_field_name = None
5870 self .expand = expand
5971
60- def convert_field (self , value , conversion ):
61- if conversion == "e" :
62- # Expand the env var to the real string value simulating `os.path.expandvars`
63- if self .expand :
64- return super ().convert_field (value , "s" )
72+ def get_field (self , field_name , args , kwargs ):
73+ """Returns the object to be inserted for the given field_name.
6574
66- # Otherwise insert the correct shell script env var reference
67- return self . shell_formats [ self . language ][ "env_var" ]. format (
68- self . current_field_name
69- )
75+ If kwargs doesn't contain ``field_name`` but ``field_name`` is in the
76+ environment variables, the stored value is returned. This also returns
77+ the pathsep for the ``;`` field_name. Otherwise works the same as
78+ the standard `string.Formatter`_.
7079
71- return super ().convert_field (value , conversion )
80+ .. _`string.Formatter`:
81+ https://docs.python.org/3/library/string.html#string.Formatter.get_field
82+ """
83+ # If a field_name was not provided, use the value stored in os.environ
84+ if field_name not in kwargs and field_name in os .environ :
85+ return os .getenv (field_name ), field_name
86+ # Process the pathsep character
87+ if field_name == ";" :
88+ value = self .shell_formats [self .language ][";" ]
89+ return value , field_name
7290
73- def get_field (self , field_name , args , kwargs ):
74- self .current_field_name = field_name
7591 ret = super ().get_field (field_name , args , kwargs )
7692 return ret
7793
@@ -97,16 +113,19 @@ def language_from_ext(cls, ext):
97113 return "sh"
98114 return ext
99115
100- def merge_kwargs (self , kwargs ):
101- """Merge the provided kwargs on top of the current language's shell_formats
102- dict. This makes it so the default format options are added by default, but
103- still allows us to override them if required
104- """
105- ret = dict (self .shell_formats [self .language ], ** kwargs )
106- ret = dict (os .environ , ** ret )
107- return ret
108-
109- def vformat (self , format_string , args , kwargs ):
110- kwargs = self .merge_kwargs (kwargs )
111- ret = super ().vformat (format_string , args , kwargs )
112- return ret
116+ def parse (self , txt ):
117+ for literal_text , field_name , format_spec , conversion in super ().parse (txt ):
118+ # Non-hab specific operation, just use the super value unchanged
119+ if conversion != "e" :
120+ yield (literal_text , field_name , format_spec , conversion )
121+ continue
122+
123+ elif self .expand and field_name in os .environ :
124+ # Expand the env var to the env var value. Later `get_field`
125+ # will update kwargs with the existing env var value
126+ yield (literal_text , field_name , format_spec , "s" )
127+ continue
128+
129+ # Convert this !e conversion to the shell specific env var specifier
130+ value = self .shell_formats [self .language ]["env_var" ].format (field_name )
131+ yield (literal_text + value , None , None , None )
0 commit comments