Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cached Value #820

Open
str-it opened this issue Sep 26, 2024 · 1 comment
Open

Cached Value #820

str-it opened this issue Sep 26, 2024 · 1 comment

Comments

@str-it
Copy link

str-it commented Sep 26, 2024

I want to have a Singleton which functions as a cache for a method call.

I want the field file_content in my container be initialized one time by calling a given method (reader.read). From then on always that result should be returned instead of calling the method again.

I have added a working code example below.
Is there any better way?
Maybe it might be useful if it was rewritten as a new Provider?

from pathlib import Path
from dependency_injector import containers, providers


class Reader:
    def read(self, filepath: Path, *args, **kwargs) -> str:
        print('read file')
        print('args:', args)
        print('kwargs:', kwargs)
        print()
        return filepath.read_text('utf-8')


SingletonAsCache = lambda bound_method, *args, **kwargs: bound_method(*args, **kwargs)


class MyContainer(containers.DeclarativeContainer):
    reader = providers.Factory(Reader)

    file_content = providers.Singleton(SingletonAsCache, reader.provided.read)


container = MyContainer()


def print_first_line():
    c: str = container.file_content(Path(__file__), 'any arg', any_kwarg='any_kwarg_value')
    print('first line:', c.splitlines()[0])


print_first_line()
print_first_line()
print_first_line()

Output:

read file
args: ('any arg',)
kwargs: {'any_kwarg': 'any_kwarg_value'}

first line: from pathlib import Path
first line: from pathlib import Path
first line: from pathlib import Path
@nightblure
Copy link

@str-it hi!

I simplified your code which you provided above and demonstrate new version of the code, as well as the output from the console, which shows that the instance of the Reader class is indeed a singleton.

code:

from pathlib import Path
from dependency_injector import containers, providers


class Reader:
    def read(self, filepath: Path, *args, **kwargs) -> str:
        print('read file')
        print('args:', args)
        print('kwargs:', kwargs)
        print()
        return filepath.read_text('utf-8')


class MyContainer(containers.DeclarativeContainer):
    reader = providers.Singleton(Reader)


def print_first_line(reader: Reader):
    print(f'reader instance id: {id(reader)}')
    c: str = reader.read(Path(__file__), 'any arg', any_kwarg='any_kwarg_value')
    print('first line:', c.splitlines()[0])


def main():
    container = MyContainer()

    for _ in range(3):
        reader = container.reader()
        print_first_line(reader)


if __name__ == '__main__':
    main()

output:

reader instance id: 4418761872
read file
args: ('any arg',)
kwargs: {'any_kwarg': 'any_kwarg_value'}

first line: from pathlib import Path
reader instance id: 4418761872
read file
args: ('any arg',)
kwargs: {'any_kwarg': 'any_kwarg_value'}

first line: from pathlib import Path
reader instance id: 4418761872
read file
args: ('any arg',)
kwargs: {'any_kwarg': 'any_kwarg_value'}

first line: from pathlib import Path

Process finished with exit code 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants