Open jriddy opened 7 months ago
Howdy,
sure, let's brainstorm! Can you describe a scenario to try to cover?
One solution that comes to mind would be using multiple incanter objects, one for each dependency scope. But maybe it can be simpler.
Well for now, there is no notion of caching the results of factory functions in Incant at all. So there's no notion of scope anad no obvious place to put it.
An example use case might have something like:
def dsn():
return DEFAULT_DSN
def db_conn(dsn):
with dbapi.connect(dsn) as conn: yield conn
def user_types(db_conn):
return list(map(UserType.from_db_row, db_conn.execute("select * from user_types"))
def print_user_types(user_types):
for ut in user_types: print(ut)
def main():
ic = incant.Incanter()
ic.register_by_name(dsn)
ic.register_by_name(db_conn)
ic.register_by_name(user_types)
# At this point I want to call funtions with db_conn cached between those calls
composed = ic.compose(print_user_types)
# Should connect to db and run query
composed()
# Should just used cached values
composed()
# Should invalidate cache and recalculate all
composed.reinject(dsn='someother:dsnvalue')
I took a deeper look at the source code that does the generation. Since you just generate calls to functions here, it might be easiest to add some wrapper that can cache, but that wrapper needs to be able to invalidate, based on inputs to the dependency graph, so it's a big thing to put in.
It also seems like the API is geared to treat compose
as the heavy-lifting part, but if the actual dependency function invocations are themselves resource intensive, it's like we're missing a bit that lets you pre-calculate them and use their cached values.
I'm sorry that I'm not defining my use cases, well. I guess I'm more just thinking through these problems as I type them. I think doing this kinda work may be well outside the scope of what you were trying to achieve with Incant.
I was just typing up a reply when I found a bug in incant running your example ;)
I'll get back to you in a day or two with my thoughts.
I'm looking at this project and I like the relative simplicity of it compared to a lot of DI libs for python. But I'm wracking my head trying to figure out how I'd introduce dependency scope. That is...caching what was returned for a factory through multiple invocations on the same incantor object.
To me, this would be necessary to use incantor to inject longer-lived things like a database connection or a requests session or something like that.
Any plans or ideas on this? I'd be interested in helping if I could get an angle on how this might work.