python-dotenv
python-dotenv copied to clipboard
feat: option to change POSIX variable name regex - facilitate passthrough
Background
There are certain situations where a string ${xxxxxxxx} should not be a candidate for variable substitution. This is very common in Spring Boot applications where ${a.b.c.d} is property placeholder syntax
This PR allows the user to narrow the scope of dotenv.variables._posix_variable so that some strings that resemble POSIX variable substitution can be treated literally.
Before this PR:
# I'm looking at you Spring Boot
APP_SOME_VAR=${app.some.other.var}
# after load_dotenv
# dotenv.variables._posix_variable is quite greedy
APP_SOME_VAR=
After this PR:
# somewhere in code:
# typical Spring Boot naming convention consists of
# caps, numerals, and underscores
dotenv.set_variable_name_pattern(r"""[A-Z0-9_]+""")
# Spring Boot property placeholder syntax
APP_SOME_VAR=${app.some.other.var}
# after load_dotenv
# literal passthrough
APP_SOME_VAR=${app.some.other.var}
Real-world use case: 12-factor'ing Spring Boot applications where some properties refer to other properties ${a.b.c.d} in their values
Feature Implementation
- opt-in package level function
dotenv.set_variable_name_pattern(....)to set the regex for the naming convention. This is a substring that will be used inside the${xxxxxx:-yyyyyy}matcher. IOW, this pattern is only used to match the variable name, not the enclosing${...} - revert to default:
dotenv.set_variable_name_pattern() - added a test for literal passthrough
- existing tests all passed
This feature does not affect any existing code as it is purely opt-in
Thread Safety
- this feature sets a module level variable in
dotenv.variablesso is not thread safe
Deferred Ideas
- per instance
_posix_variable- this would be very intrusive so not in the scope of this feature - thread-local
_posix_variable- this is a low risk thread-safety enhancement where each thread can set its own_posix_variable
Usage
# before calling load_dotenv or dotenv_values
dotenv.set_variable_name_pattern(r'''[A-Z0-9_]+''') # Spring Boot preset
load_dotenv()
# or
load_dotenv(varname_pattern=r'''[A-Z0-9_]+''')
dotenv_values(varname_pattern=r'''[A-Z0-9_]+''')
# epilogue: reset to package default regex
dotenv.set_variable_name_pattern()
Benefits
- allow literal passthrough of string segments that look like POSIX substitution
Workaround
Current workaround
## this is horrible
__='${'
APP_SOME_VAR=${__}app.some.other.var}