record the configuration uri and a hash of it's contents to settings when parsed
Feature Request
When Pyramid is started with a configuration file - such as pserve example.ini or registered_script example.ini - the configuration file and an md5 of it's raw contents should be put into the global_config and/or settings. The global config currently has the filepath as a __file__ key, but I think this is an implementation detail of pserve with .ini's (I am not sure on this).
Having this information easily accessible has become important for both troubleshooting and ensuring an invoked utility script is compatible with a live Pyramid application if they interact.
For example, it allows this usage to be easily detected and fail:
pserve production.ini
cleanup_stale_data development.ini
Describe the solution you'd like I think this should be consistently available, however my understanding of Pyramid suggests it could happen in one or more of the functions in pyramid.paster (https://github.com/Pylons/pyramid/blob/main/src/pyramid/paster.py)
I would be happy to generate a PR for this, I just know that I am likely to miss multiple contexts of where these files are parsed. If the maintainers like this idea- if given an overview, I will generate a PR.
Describe alternatives you've considered I calculate this myself, but this seems to be possible based on my contexts - and things may change if other file formats/parsers are used.
Additional context This is somewhat inspired by poetry lockfiles.
Initially I thought of this to ensure I can coordinate a Server with a Script. The exact use case is that a live Pyramid Application responds to ACME challenges, but a Pyramid Script invoked by cron is used to check for expiring Certificates and will order renewals. In this usage, I need to ensure the script and application are both using the same configuration file - so they both calculate the hash, and the Pyramid application publishes it on a private url.
This was quick to implement on an application in developer-space, and then I realized I could easily integrate the hash into error logging to aid in post-deployment troubleshooting.
In case anyone needs something similar, here is a version of the code I used:
import hashlib
import os
from typing import Dict
from typing import Optional
import uuid
def normalize_filepath(fpath: str) -> str:
fpath = os.path.normpath(fpath)
if fpath[-1] == "/":
fpath = fpath[:-1]
return fpath
def upgrade_settings(
settings: Dict,
config_uri: Optional[str] = None,
) -> Dict:
"""
upgrades Pyramid Application settings to help identify the configuration.
While `config_uri` is stashed into the settings dict for convenience,
it should not be exposed.
Instead, the following two items are safe to expose to clients:
* `config_uri-path` - a hashed value of the filepath
* `config_uri-contents` - a hashed value of the file contents
Additionally, `mac_uuid` will contain a uuid identifying the machine, based
on the network mac address. There are more robust approaches to this, but
it suffices for these needs. see
https://stackoverflow.com/questions/36235807/fixed-identifier-for-a-machine-uuid-getnode
"""
if config_uri:
settings["config_uri"] = config_uri
_hash = hashlib.md5(config_uri.encode()).hexdigest()
settings["config_uri-path"] = _hash
with open(config_uri, "rb") as f:
_contents = f.read()
_hash = hashlib.md5(_contents).hexdigest()
settings["config_uri-contents"] = _hash
mac = uuid.getnode()
settings["mac_uuid"] = str(uuid.UUID(int=mac))
return settings