Skip to content
/ nodnod Public

Programming in Python empowered with Nodes DI, implements efficient nodes computation agents and dependency scoping

Notifications You must be signed in to change notification settings

timoniq/nodnod

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

72 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NodNod

🧑‍🧑‍🧒‍🧒

codecov pypi

about

nodnod is a dependency injection tool

nodnod strives to be effective and simple: it has many agents, but, for example, asyncio agent turns each dependency into a coroutine and yields decomposed dependency net to your loop to solve it the best way possible

nodnod is easy to integrate, be it a framework or a small project

interfaces

composing a set of dependencies is as simple as:

async def main():
    agent = EventLoopAgent.build({Username})

    async with Scope() as scope:
        scope.inject(User, User(id=1, username=Some("arseni")))
        await agent.run(scope, {})

    print(scope[Username])

two objects that define compile-time and runtime are agent and Scope.

  • agent precompiles the dependency graph
  • scope contains dependency roots and defines dependency visibility within one scope. many scopes can be linked in the manner of parent-child or global-local relation. dependencies are made accessible within different scopes

nodnod provides many interfaces to build different kinds of dependencies:

  • polymorphic - node whose resolution may vary

    @polymorphic[float]
    class Ratio:
        @case
        def from_video(cls, video: Video) -> float:
            frame = video.frames[0]
            return frame.width / frame.length
    
        @case
        def from_photo(cls, photo: Photo) -> float:
            return photo.width / photo.length
  • scalar node disguises as its result for type checkers

    @scalar_node
    class Username:
        @classmethod
        def __compose__(cls, user: User) -> str:
            return user.username.map_error(lambda _: f"#{user.id}")
  • logical or

    @classmethod
    def __compose__(cls, dep: One | Another) -> ...: ...
    • can be concurrent: two nodes are racing to deliver their resolution
    • or sequential: if first resolution fails, next one is triggered
  • kungfu funtional types are supported:

    Exceptions can be intercepted:

    @classmethod
    def __compose__(cls, weather: Result[Weather, ConnectionError)): ...

    Dependencies can be optional:

    @classmethod
    def __compose__(cls, ratio: Option[Ratio]): ...

your contributions are welcome!

🌺

About

Programming in Python empowered with Nodes DI, implements efficient nodes computation agents and dependency scoping

Resources

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •  

Languages