3232def config (
3333 * configs : Iterable ,
3434 prefix : str = "" ,
35+ strip_prefix : bool = True ,
3536 separator : Optional [str ] = None ,
3637 remove_level : int = 1 ,
3738 lowercase_keys : bool = False ,
@@ -44,6 +45,7 @@ def config(
4445 Params:
4546 configs: iterable of configurations
4647 prefix: prefix to filter environment variables with
48+ strip_prefix: whether to strip the prefix
4749 remove_level: how many levels to remove from the resulting config
4850 lowercase_keys: whether to convert every key to lower case.
4951 ignore_missing_paths: whether to ignore failures from missing files/folders.
@@ -71,6 +73,9 @@ def config(
7173 if isinstance (config_ , Mapping ):
7274 instances .append (config_from_dict (config_ , ** default_kwargs ))
7375 continue
76+ elif isinstance (config_ , Configuration ):
77+ instances .append (config_ )
78+ continue
7479 elif isinstance (config_ , str ):
7580 if config_ .endswith (".py" ):
7681 config_ = ("python" , config_ , * default_args )
@@ -82,8 +87,8 @@ def config(
8287 config_ = ("toml" , config_ , True )
8388 elif config_ .endswith (".ini" ):
8489 config_ = ("ini" , config_ , True )
85- elif config_ .endswith (".env" ):
86- config_ = ("dotenv" , config_ , True )
90+ elif config_ .endswith (".env" ) or config_ . startswith ( ".env" ) :
91+ config_ = ("dotenv" , config_ , True , * default_args )
8792 elif os .path .isdir (config_ ):
8893 config_ = ("path" , config_ , remove_level )
8994 elif config_ in ("env" , "environment" ):
@@ -103,7 +108,13 @@ def config(
103108 instances .append (config_from_dict (* config_ [1 :], ** default_kwargs ))
104109 elif type_ in ("env" , "environment" ):
105110 params = list (config_ [1 :]) + default_args [(len (config_ ) - 1 ) :]
106- instances .append (config_from_env (* params , ** default_kwargs ))
111+ instances .append (
112+ config_from_env (
113+ * params ,
114+ ** default_kwargs ,
115+ strip_prefix = strip_prefix ,
116+ ),
117+ )
107118 elif type_ == "python" :
108119 if len (config_ ) < 2 :
109120 raise ValueError ("No path specified for python module" )
@@ -113,6 +124,7 @@ def config(
113124 * params ,
114125 ** default_kwargs ,
115126 ignore_missing_paths = ignore_missing_paths ,
127+ strip_prefix = strip_prefix ,
116128 ),
117129 )
118130 elif type_ == "json" :
@@ -137,6 +149,7 @@ def config(
137149 * config_ [1 :],
138150 ** default_kwargs ,
139151 ignore_missing_paths = ignore_missing_paths ,
152+ strip_prefix = strip_prefix ,
140153 ),
141154 )
142155 elif type_ == "ini" :
@@ -145,6 +158,7 @@ def config(
145158 * config_ [1 :],
146159 ** default_kwargs ,
147160 ignore_missing_paths = ignore_missing_paths ,
161+ strip_prefix = strip_prefix ,
148162 ),
149163 )
150164 elif type_ == "dotenv" :
@@ -153,6 +167,7 @@ def config(
153167 * config_ [1 :],
154168 ** default_kwargs ,
155169 ignore_missing_paths = ignore_missing_paths ,
170+ strip_prefix = strip_prefix ,
156171 ),
157172 )
158173 elif type_ == "path" :
@@ -178,9 +193,10 @@ class EnvConfiguration(Configuration):
178193
179194 def __init__ (
180195 self ,
181- prefix : str ,
196+ prefix : str = "" ,
182197 separator : str = "__" ,
183198 * ,
199+ strip_prefix : bool = True ,
184200 lowercase_keys : bool = False ,
185201 interpolate : InterpolateType = False ,
186202 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
@@ -189,9 +205,11 @@ def __init__(
189205
190206 prefix: prefix to filter environment variables with
191207 separator: separator to replace by dots
208+ strip_prefix: whether to include the prefix
192209 lowercase_keys: whether to convert every key to lower case.
193210 """
194211 self ._prefix = prefix
212+ self ._strip_prefix = strip_prefix
195213 self ._separator = separator
196214 super ().__init__ (
197215 {},
@@ -207,9 +225,12 @@ def reload(self) -> None:
207225 for key , value in os .environ .items ():
208226 if not key .startswith (self ._prefix + self ._separator ):
209227 continue
210- result [
211- key [len (self ._prefix ) :].replace (self ._separator , "." ).strip ("." )
212- ] = value
228+ if self ._strip_prefix :
229+ result [
230+ key [len (self ._prefix ) :].replace (self ._separator , "." ).strip ("." )
231+ ] = value
232+ else :
233+ result [key .replace (self ._separator , "." ).strip ("." )] = value
213234 super ().__init__ (
214235 result ,
215236 lowercase_keys = self ._lowercase ,
@@ -222,6 +243,7 @@ def config_from_env(
222243 prefix : str ,
223244 separator : str = "__" ,
224245 * ,
246+ strip_prefix : bool = True ,
225247 lowercase_keys : bool = False ,
226248 interpolate : InterpolateType = False ,
227249 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
@@ -231,6 +253,7 @@ def config_from_env(
231253 Params:
232254 prefix: prefix to filter environment variables with.
233255 separator: separator to replace by dots.
256+ strip_prefix: whether to include the prefix
234257 lowercase_keys: whether to convert every key to lower case.
235258 interpolate: whether to apply string interpolation when looking for items.
236259
@@ -240,6 +263,7 @@ def config_from_env(
240263 return EnvConfiguration (
241264 prefix ,
242265 separator ,
266+ strip_prefix = strip_prefix ,
243267 lowercase_keys = lowercase_keys ,
244268 interpolate = interpolate ,
245269 interpolate_type = interpolate_type ,
@@ -463,13 +487,15 @@ def __init__(
463487 read_from_file : bool = False ,
464488 * ,
465489 section_prefix : str = "" ,
490+ strip_prefix : bool = True ,
466491 lowercase_keys : bool = False ,
467492 interpolate : InterpolateType = False ,
468493 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
469494 ignore_missing_paths : bool = False ,
470495 ):
471496 """Class Constructor."""
472497 self ._section_prefix = section_prefix
498+ self ._strip_prefix = strip_prefix
473499 super ().__init__ (
474500 data = data ,
475501 read_from_file = read_from_file ,
@@ -502,8 +528,9 @@ def optionxform(self, optionstr: str) -> str:
502528 data = cast (str , data )
503529 cfg = ConfigParser ()
504530 cfg .read_string (data )
531+ n = len (self ._section_prefix ) if self ._strip_prefix else 0
505532 result = {
506- section [len ( self . _section_prefix ) :] + "." + k : v
533+ section [n :] + "." + k : v
507534 for section , values in cfg .items ()
508535 for k , v in values .items ()
509536 if section .startswith (self ._section_prefix )
@@ -516,6 +543,7 @@ def config_from_ini(
516543 read_from_file : bool = False ,
517544 * ,
518545 section_prefix : str = "" ,
546+ strip_prefix : bool = True ,
519547 lowercase_keys : bool = False ,
520548 interpolate : InterpolateType = False ,
521549 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
@@ -538,6 +566,7 @@ def config_from_ini(
538566 data ,
539567 read_from_file ,
540568 section_prefix = section_prefix ,
569+ strip_prefix = strip_prefix ,
541570 lowercase_keys = lowercase_keys ,
542571 interpolate = interpolate ,
543572 interpolate_type = interpolate_type ,
@@ -555,14 +584,17 @@ def __init__(
555584 prefix : str = "" ,
556585 separator : str = "__" ,
557586 * ,
587+ strip_prefix : bool = True ,
558588 lowercase_keys : bool = False ,
559589 interpolate : InterpolateType = False ,
560590 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
561591 ignore_missing_paths : bool = False ,
562592 ):
563593 """Class Constructor."""
564594 self ._prefix = prefix
595+ self ._strip_prefix = strip_prefix
565596 self ._separator = separator
597+
566598 super ().__init__ (
567599 data = data ,
568600 read_from_file = read_from_file ,
@@ -589,8 +621,9 @@ def _reload(
589621 parse_env_line (x ) for x in data .splitlines () if x and not x .startswith ("#" )
590622 )
591623
624+ n = len (self ._prefix ) if self ._strip_prefix else 0
592625 result = {
593- k [len ( self . _prefix ) :].replace (self ._separator , "." ).strip ("." ): v
626+ k [n :].replace (self ._separator , "." ).strip ("." ): v
594627 for k , v in result .items ()
595628 if k .startswith (self ._prefix )
596629 }
@@ -604,6 +637,7 @@ def config_from_dotenv(
604637 prefix : str = "" ,
605638 separator : str = "__" ,
606639 * ,
640+ strip_prefix : bool = True ,
607641 lowercase_keys : bool = False ,
608642 interpolate : InterpolateType = False ,
609643 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
@@ -629,6 +663,7 @@ def config_from_dotenv(
629663 read_from_file ,
630664 prefix = prefix ,
631665 separator = separator ,
666+ strip_prefix = strip_prefix ,
632667 lowercase_keys = lowercase_keys ,
633668 interpolate = interpolate ,
634669 interpolate_type = interpolate_type ,
@@ -645,6 +680,7 @@ def __init__(
645680 prefix : str = "" ,
646681 separator : str = "_" ,
647682 * ,
683+ strip_prefix : bool = True ,
648684 lowercase_keys : bool = False ,
649685 interpolate : InterpolateType = False ,
650686 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
@@ -677,6 +713,7 @@ def __init__(
677713 module = importlib .import_module (module )
678714 self ._module : Optional [ModuleType ] = module
679715 self ._prefix = prefix
716+ self ._strip_prefix = strip_prefix
680717 self ._separator = separator
681718 except (FileNotFoundError , ModuleNotFoundError ):
682719 if not ignore_missing_paths :
@@ -699,10 +736,9 @@ def reload(self) -> None:
699736 for x in dir (self ._module )
700737 if not x .startswith ("__" ) and x .startswith (self ._prefix )
701738 ]
739+ n = len (self ._prefix ) if self ._strip_prefix else 0
702740 result = {
703- k [len (self ._prefix ) :]
704- .replace (self ._separator , "." )
705- .strip ("." ): getattr (self ._module , k )
741+ k [n :].replace (self ._separator , "." ).strip ("." ): getattr (self ._module , k )
706742 for k in variables
707743 }
708744 else :
@@ -720,6 +756,7 @@ def config_from_python(
720756 prefix : str = "" ,
721757 separator : str = "_" ,
722758 * ,
759+ strip_prefix : bool = True ,
723760 lowercase_keys : bool = False ,
724761 interpolate : InterpolateType = False ,
725762 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
@@ -741,6 +778,7 @@ def config_from_python(
741778 module ,
742779 prefix ,
743780 separator ,
781+ strip_prefix = strip_prefix ,
744782 lowercase_keys = lowercase_keys ,
745783 interpolate = interpolate ,
746784 interpolate_type = interpolate_type ,
@@ -882,6 +920,7 @@ def __init__(
882920 read_from_file : bool = False ,
883921 * ,
884922 section_prefix : str = "" ,
923+ strip_prefix : bool = True ,
885924 lowercase_keys : bool = False ,
886925 interpolate : InterpolateType = False ,
887926 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
@@ -894,6 +933,7 @@ def __init__(
894933 )
895934
896935 self ._section_prefix = section_prefix
936+ self ._strip_prefix = strip_prefix
897937 super ().__init__ (
898938 data = data ,
899939 read_from_file = read_from_file ,
@@ -920,8 +960,9 @@ def _reload(
920960 loaded = toml .loads (data )
921961 loaded = cast (dict , loaded )
922962
963+ n = len (self ._section_prefix ) if self ._section_prefix else 0
923964 result = {
924- k [len ( self . _section_prefix ) :]: v
965+ k [n :]: v
925966 for k , v in self ._flatten_dict (loaded ).items ()
926967 if k .startswith (self ._section_prefix )
927968 }
@@ -934,6 +975,7 @@ def config_from_toml(
934975 read_from_file : bool = False ,
935976 * ,
936977 section_prefix : str = "" ,
978+ strip_prefix : bool = True ,
937979 lowercase_keys : bool = False ,
938980 interpolate : InterpolateType = False ,
939981 interpolate_type : InterpolateEnumType = InterpolateEnumType .STANDARD ,
@@ -955,6 +997,7 @@ def config_from_toml(
955997 data ,
956998 read_from_file ,
957999 section_prefix = section_prefix ,
1000+ strip_prefix = strip_prefix ,
9581001 lowercase_keys = lowercase_keys ,
9591002 interpolate = interpolate ,
9601003 interpolate_type = interpolate_type ,
0 commit comments