3 ms·
Previous discussion: https://news.ycombinator.com/item?id=31849787 https://news.ycombinator.com/item?id=31849787 Repeating my comment from that thread: from
by j4mie 2y ago
Previous discussion: https://news.ycombinator.com/item?id=31849787 https://news.ycombinator.com/item?id=31849787
Repeating my comment from that thread:
from diagrams import Diagram
from diagrams.aws.compute import EC2
with Diagram("Simple Diagram"):
EC2("web")
This has a very odd API. It's using (abusing?) context managers and contextvars to do weird spooky things that you could just as easily do with ordinary objects or functions.
- flakes 2y agoDepends how it's implemented. It seems very similar to Apache Airflow in API, and similar to the many Argo Workflows Python wrappers. This pattern when implemented with context vars in the context managers is a pretty nice way to reduce the boilerplate, without the downsides of traditional globals. The state can be safely contained to just the with block. Usually these types of APIs also allow usage without it, using the context vars only to populate arguments not explicitly provided.
- baq 2y agoit's using context managers to manage context i.e. state that is there but isn't needed to be referenced by code directly. it's the whole point. you can do it all with just functions or objects (doesn't matter, functions are objects in Python anyway) by design, context managers are there for DRY purposes.
- wdfx 2y agoWhat's jarring me with the parent's example is the fact that the context managers must be holding global state. It would feel a lot better if it was this, for example, where you use each context explicitly: from diagrams import Diagram from diagrams.aws.compute import EC2 with Diagram("Simple Diagram") as d: d.add(EC2("web")) As as the parent also suggests, this then doesn't really need the context management at all from diagrams import Diagram from diagrams.aws.compute import EC2 d = Diagram("Simple Diagram") d.add(EC2("web"))
- baq 2y agoyeah but then you have to repeat yourself a lot: d.add(first) d.add(second) d.add(...) you see redundancy and a misused language capability, I see a feature and a nice DSL.