Pendulum's "+" Operator Reads the Call Stack to Guess What You Mean
Why Pendulum had to write the most cursed "+" operator in all of Python
Pendulum, the popular Python datetime library, made two promises: DST-aware arithmetic and drop-in compatibility with the standard library. Those promises collide inside datetime.astimezone(), where the standard library calls + expecting wall-clock semantics. Pendulum's fix: inspect the call stack in __add__ and, if the caller is named astimezone, fall back to the standard library's behavior. The hack is fragile, breaks on PyPy and dateutil time zones, and makes + roughly 600 times slower. A merged pull request removes the guess.
So you can change the result of + by renaming your own function.
- shoo
Mmm. Changing control flow based on introspection of the call stack is reasonably nasty.
I recall we found a neat use for call stack introspection in one project - not to change control flow but to improve logging. Inside an open_db_connection utility function, to auto-generate an informational name describing which part of the codebase had opened the connection:
E.g. some_backend_process: main -> ... > grandparent -> parent -> open_db_connection
We'd use information from the call stack generate a string "some_backend_process grandparent.parent" describing the call site which could be passed to postgres as the application_name [1] when establishing a connection. Then from the database side, if we had problematic queries at runtime, we had a lot more clues to figure out which part of the backend codebase was responsible [2].
There'd be a way to do something equivalent without peeking at the call stack, by requiring the caller to explicitly pass a descriptive & unique name, but that makes things a bit more error-prone, especially since some devs would be prone to copy-pasting chunks of existing code & reusing the same name everywhere.
[1] https://www.postgresql.org/docs/current/libpq-connect.html#L...
[2] https://www.postgresql.org/docs/current/monitoring-stats.htm...
- jvolkman
I'll one up this with my hack that changes the value of `sys.platform` based on the caller: https://github.com/jvolkman/rules_pycross/blob/main/pycross/...
This is used when cross compiling binary wheels (e.g., building a macos wheel on a linux build host or vice versa).
- ariebovenberg
Author here. I ran into this while comparing Pendulum with `whenever`, the datetime library I maintain. I sent a patch that removes the hack, but the post is about why the underlying design can't be patched the same way. Happy to answer questions.