cntxt
adds a dynamic namespace that is managed with a context manager and extends down
through the call stack, to be accessible where needed.
Scopes:
- Local scope - variables in the current function or class definition
- Enclosing scope - variables available through lexical closure
- Global scope - module namespace created when module is loaded, usually never deleted
- Built-in scope - created when interpreter starts, never deleted
Namespaces: 5. Object namespace - attributes, inherited or not 6. Class namespace - same, but for classes 7. Thread-local - data specific to a thread 8. Environment variables - values defined outside the Python program 9. File, database or similar - containing key-value pairs or more complex data
What's wrong with these namespaces?
- Local scope is too local, not available elsewhere.
- Enclosing scope is a little bit less local, but still very local in terms of a codebase.
- Global scope is too global - we try to avoid "polluting the global namespace" as the values can be overwritten anywhere and conflicts can be hard to debug.
- Built-in scope is too static.
- Instances are ok, but accessing them requires a reference, which you have to manually pass down the stack to any users.
- Classes are often used as importable singletons for configuration type information, but as such they can be "too global" and modified in surprising places.
- Thread-local data is "too global" within the thread stack.
- Environment variables are essentially global values, and where they are defined is not visible in the Python code.
- Files or more powerful require configuration information to be accessible. They are also not in memory, which may be relevant in some cases.