summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--python-lazy-load.spec565
-rw-r--r--sources1
3 files changed, 567 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..a57a7e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/lazy_load-0.8.3.tar.gz
diff --git a/python-lazy-load.spec b/python-lazy-load.spec
new file mode 100644
index 0000000..97ee4ec
--- /dev/null
+++ b/python-lazy-load.spec
@@ -0,0 +1,565 @@
+%global _empty_manifest_terminate_build 0
+Name: python-lazy-load
+Version: 0.8.3
+Release: 1
+Summary: ℒazy-ℒoad - A minimalistic interface that allows the lazy evaluation of expressions. Additional functions and wrappers allow it to easily use the lazy evaluation for functions and classes.
+License: MIT
+URL: https://github.com/kutoga/lazy-load
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/80/0c/36859ba71fb3e47505afeb61b21fef848c5afb54e119537a685b4e1adc0e/lazy_load-0.8.3.tar.gz
+BuildArch: noarch
+
+Requires: python3-lazy-object-proxy
+
+%description
+A minimalistic interface that allows lazy evaluation of expressions and function calls.
+Note: This small library is heavily based on `python-lazy-object-proxy`.
+Why using ℒazy-ℒoad? Lazy loading in general may make some software implementations much more efficient.
+Especially if it is not known if some data has to be loaded or not. Often the resulting code is less efficient,
+because eager loading is used or the code is not elegant, because one has to program (somehow) lazy loading.
+Advantages of this library are that lazy-loading may be used quite elegant and effective.
+Examples
+^^^^^^^^
+In a loop it might happen that a special condition appears once or even more often. If this is the case,
+an expensive function `expensive_function` is called and on the resulting object an operation has
+to be done. If the expensive function had to called more than once, than the result object may be reused.
+Possible implementation:
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = None
+ for x, y, p in get_coordinates():
+ if test_for_something(x, y, p):
+ if obj is None:
+ obj = expensive_function()
+ obj.do_something(x, y)
+Given this library, it might be done like this:
+ from lazy_load import lazy
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = lazy(expensive_function)
+ for x, y, p in get_coordinates():
+ if test_for_something(x, y, p):
+ obj.do_something(x, y)
+There are similar situations outside of loops. The implementation without `lazy-load` might look like this:
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = None
+ def get_obj():
+ global obj
+ if obj is None:
+ obj = expensive_function()
+ return obj
+ if condition_a:
+ get_obj().xyz()
+ if condition_b:
+ do_something()
+ if condition_c:
+ get_obj().abc()
+This code can be realized much easier with `lazy-load`. Not only is the code shorter, but it is also more readable:
+ from lazy_load import lazy
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = lazy(expensive_function)
+ if condition_a:
+ obj.xyz()
+ if condition_b:
+ do_something()
+ if condition_c:
+ obj.abc()
+It might be the case that the expensive function is used more often and always a lazy evaluation is done.
+In this case, a decorator might be used to indicate that all function calls to this function shall be lazily
+evaluated. This makes it possible to normally use the function. The behaviour is still the same like in the first example:
+ from lazy_load import lazy_func
+ @lazy_func
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = expensive_function()
+ for x, y, p in get_coordinates():
+ if test_for_something(x, y, p):
+ obj.do_something(x, y)
+A lazy evaluation of functions / methods calls might be done with the `@lazy_func` decorator of with the `lazy`-call. This was already
+shown, therefore the following examples show how to do a one-shot lazy evaluation of a function call:
+ from lazy_load import lazy, lz
+ def expensive_func(x, y):
+ print(f"function evaluation with arguments x={x}, y={y}")
+ return result
+ # Possibility 1: Use `lazy` with a callable
+ obj = lazy(lambda: expensive_func(a, b))
+ # Possibility 2: If it doesn't matter if the argument expressions for the expensive-function are eager evaluated, the call may be simplified:
+ obj = lazy(expensive_func, a, b)
+ # Possibility 3: `lazy` has a short version / alias: `lz`
+ obj = lz(expensive_func, a, b)
+Python allows it to pass functions around: This is often used for callbacks, but also for other use cases.
+Assuming an expensive function is passed to an object which calls this function and stores the result of
+the function call in an attribute. Later it might happen that this attribute is used. Depending on the
+program flow it also might happen that this attribute is not used. With a lazily evaluated function the
+expensive function call is only executed if the result is really used. The lazily evaluated version of
+a function has the exact same signature as the original function.
+One might now like to have the possibility to on-the-fly convert a callable to a lazily evaluated callable.
+This might be done in the following way:
+ from lazy_load import lazy_func, lf
+ def expensive_func(x):
+ print(f"function evaluation with argument x={x}")
+ return result
+ # Possibility 1: Use `lazy_func`.
+ my_obj.do_something(f=lazy_func(expensive_func))
+ # Possibility 2: Use `lf` which is an alias of `lazy_func`
+ my_obj.do_something(f=lf(expensive_func))
+ # Possibility 3: Use the `ℒ`-"operator"
+ my_obj.do_something(f=ℒ[expensive_func])
+Actually, I want to go deeper into the `ℒ`azy- or `ℒ`-"operator". This operator converts on-the-fly a function
+to a lazily evaluated function. Another example:
+ from lazy_load import ℒ
+ def test(name):
+ print(f"hey {name}")
+ return True
+ res = test("peter")
+ # prints "hey peter"
+ test_l = ℒ[test]
+ res = test_l("hans")
+ # prints nothing
+ if res:
+ print("res is True")
+ # prints "hey hans\nres is True"
+It is also possible to convert multiple functions to lazily evaluated functions using `ℒ`:
+ from lazy_load import ℒ
+ def f1(x):
+ print(f"f1 {x}")
+ return True
+ def f2(x):
+ print(f"f1 {x}")
+ return True
+ f1_l, f2_l, f3_l = ℒ[f1, f2, lambda x: x == 1]
+ # This is equal to:
+ f1_l = ℒ[f1]
+ f2_l = ℒ[f2]
+ f3_l = ℒ[lambda x: x == 1]
+Finally, one might like to decorate a class in a way that all its public methods which have a return
+value are lazily evaluated. Public methods are all methods that have a name not starting with `_`.
+Methods with a return value are identificated by the given return type hint which must not be `None`.
+This behaviour might be done with the `@lazy_class`-decorator (alias: `lc`):
+ from lazy_load import lazy_class
+ @lazy_class
+ class MyClass:
+ def __init__(self):
+ # Method name starts with "_" => is not public; therefore it is eager evaluated
+ pass
+ def setX(x) -> None:
+ # Method does not return a value => therefore it is eager evaluated
+ def do():
+ # Method does not hav a return value type hint => therefore it is eager evaluated
+ def compute() -> int:
+ # Method will always be lazily evaluated
+ return result
+Finally, it is also possible to force the evaluation of a lazy loading object by using `force_eval` (alias `fe`).
+This function can safely to used to non-lazy loading objects: It is then just equal to the identity function.
+ from lazy_load import lazy, force_eval
+ def f1(x):
+ print(f"f1 {x}")
+ return True
+ lazy_obj = lazy(f1, 1)
+ # The following expression prints "f1 1" and returns "True"
+ force_eval(lazy_obj)
+The `force_eval` function may also be applied to lazy-functions (which are created with `lazy_func(x)`, `@lazy_func`
+or with `ℒ`). This restores the original non-lazy / eager function. For non-lazy functions this call has no effect:
+ from lazy_load import lazy_func, force_eval
+ @lazy_func
+ def f(x):
+ print("hey")
+ return x**2
+ # The following line prints nothing
+ obj = f(2)
+ f_eager = force_eval(f)
+ # The following line prints "hey" and "obj" has immediatly the value "4"
+ obj = f_eager(2)
+
+%package -n python3-lazy-load
+Summary: ℒazy-ℒoad - A minimalistic interface that allows the lazy evaluation of expressions. Additional functions and wrappers allow it to easily use the lazy evaluation for functions and classes.
+Provides: python-lazy-load
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-lazy-load
+A minimalistic interface that allows lazy evaluation of expressions and function calls.
+Note: This small library is heavily based on `python-lazy-object-proxy`.
+Why using ℒazy-ℒoad? Lazy loading in general may make some software implementations much more efficient.
+Especially if it is not known if some data has to be loaded or not. Often the resulting code is less efficient,
+because eager loading is used or the code is not elegant, because one has to program (somehow) lazy loading.
+Advantages of this library are that lazy-loading may be used quite elegant and effective.
+Examples
+^^^^^^^^
+In a loop it might happen that a special condition appears once or even more often. If this is the case,
+an expensive function `expensive_function` is called and on the resulting object an operation has
+to be done. If the expensive function had to called more than once, than the result object may be reused.
+Possible implementation:
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = None
+ for x, y, p in get_coordinates():
+ if test_for_something(x, y, p):
+ if obj is None:
+ obj = expensive_function()
+ obj.do_something(x, y)
+Given this library, it might be done like this:
+ from lazy_load import lazy
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = lazy(expensive_function)
+ for x, y, p in get_coordinates():
+ if test_for_something(x, y, p):
+ obj.do_something(x, y)
+There are similar situations outside of loops. The implementation without `lazy-load` might look like this:
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = None
+ def get_obj():
+ global obj
+ if obj is None:
+ obj = expensive_function()
+ return obj
+ if condition_a:
+ get_obj().xyz()
+ if condition_b:
+ do_something()
+ if condition_c:
+ get_obj().abc()
+This code can be realized much easier with `lazy-load`. Not only is the code shorter, but it is also more readable:
+ from lazy_load import lazy
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = lazy(expensive_function)
+ if condition_a:
+ obj.xyz()
+ if condition_b:
+ do_something()
+ if condition_c:
+ obj.abc()
+It might be the case that the expensive function is used more often and always a lazy evaluation is done.
+In this case, a decorator might be used to indicate that all function calls to this function shall be lazily
+evaluated. This makes it possible to normally use the function. The behaviour is still the same like in the first example:
+ from lazy_load import lazy_func
+ @lazy_func
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = expensive_function()
+ for x, y, p in get_coordinates():
+ if test_for_something(x, y, p):
+ obj.do_something(x, y)
+A lazy evaluation of functions / methods calls might be done with the `@lazy_func` decorator of with the `lazy`-call. This was already
+shown, therefore the following examples show how to do a one-shot lazy evaluation of a function call:
+ from lazy_load import lazy, lz
+ def expensive_func(x, y):
+ print(f"function evaluation with arguments x={x}, y={y}")
+ return result
+ # Possibility 1: Use `lazy` with a callable
+ obj = lazy(lambda: expensive_func(a, b))
+ # Possibility 2: If it doesn't matter if the argument expressions for the expensive-function are eager evaluated, the call may be simplified:
+ obj = lazy(expensive_func, a, b)
+ # Possibility 3: `lazy` has a short version / alias: `lz`
+ obj = lz(expensive_func, a, b)
+Python allows it to pass functions around: This is often used for callbacks, but also for other use cases.
+Assuming an expensive function is passed to an object which calls this function and stores the result of
+the function call in an attribute. Later it might happen that this attribute is used. Depending on the
+program flow it also might happen that this attribute is not used. With a lazily evaluated function the
+expensive function call is only executed if the result is really used. The lazily evaluated version of
+a function has the exact same signature as the original function.
+One might now like to have the possibility to on-the-fly convert a callable to a lazily evaluated callable.
+This might be done in the following way:
+ from lazy_load import lazy_func, lf
+ def expensive_func(x):
+ print(f"function evaluation with argument x={x}")
+ return result
+ # Possibility 1: Use `lazy_func`.
+ my_obj.do_something(f=lazy_func(expensive_func))
+ # Possibility 2: Use `lf` which is an alias of `lazy_func`
+ my_obj.do_something(f=lf(expensive_func))
+ # Possibility 3: Use the `ℒ`-"operator"
+ my_obj.do_something(f=ℒ[expensive_func])
+Actually, I want to go deeper into the `ℒ`azy- or `ℒ`-"operator". This operator converts on-the-fly a function
+to a lazily evaluated function. Another example:
+ from lazy_load import ℒ
+ def test(name):
+ print(f"hey {name}")
+ return True
+ res = test("peter")
+ # prints "hey peter"
+ test_l = ℒ[test]
+ res = test_l("hans")
+ # prints nothing
+ if res:
+ print("res is True")
+ # prints "hey hans\nres is True"
+It is also possible to convert multiple functions to lazily evaluated functions using `ℒ`:
+ from lazy_load import ℒ
+ def f1(x):
+ print(f"f1 {x}")
+ return True
+ def f2(x):
+ print(f"f1 {x}")
+ return True
+ f1_l, f2_l, f3_l = ℒ[f1, f2, lambda x: x == 1]
+ # This is equal to:
+ f1_l = ℒ[f1]
+ f2_l = ℒ[f2]
+ f3_l = ℒ[lambda x: x == 1]
+Finally, one might like to decorate a class in a way that all its public methods which have a return
+value are lazily evaluated. Public methods are all methods that have a name not starting with `_`.
+Methods with a return value are identificated by the given return type hint which must not be `None`.
+This behaviour might be done with the `@lazy_class`-decorator (alias: `lc`):
+ from lazy_load import lazy_class
+ @lazy_class
+ class MyClass:
+ def __init__(self):
+ # Method name starts with "_" => is not public; therefore it is eager evaluated
+ pass
+ def setX(x) -> None:
+ # Method does not return a value => therefore it is eager evaluated
+ def do():
+ # Method does not hav a return value type hint => therefore it is eager evaluated
+ def compute() -> int:
+ # Method will always be lazily evaluated
+ return result
+Finally, it is also possible to force the evaluation of a lazy loading object by using `force_eval` (alias `fe`).
+This function can safely to used to non-lazy loading objects: It is then just equal to the identity function.
+ from lazy_load import lazy, force_eval
+ def f1(x):
+ print(f"f1 {x}")
+ return True
+ lazy_obj = lazy(f1, 1)
+ # The following expression prints "f1 1" and returns "True"
+ force_eval(lazy_obj)
+The `force_eval` function may also be applied to lazy-functions (which are created with `lazy_func(x)`, `@lazy_func`
+or with `ℒ`). This restores the original non-lazy / eager function. For non-lazy functions this call has no effect:
+ from lazy_load import lazy_func, force_eval
+ @lazy_func
+ def f(x):
+ print("hey")
+ return x**2
+ # The following line prints nothing
+ obj = f(2)
+ f_eager = force_eval(f)
+ # The following line prints "hey" and "obj" has immediatly the value "4"
+ obj = f_eager(2)
+
+%package help
+Summary: Development documents and examples for lazy-load
+Provides: python3-lazy-load-doc
+%description help
+A minimalistic interface that allows lazy evaluation of expressions and function calls.
+Note: This small library is heavily based on `python-lazy-object-proxy`.
+Why using ℒazy-ℒoad? Lazy loading in general may make some software implementations much more efficient.
+Especially if it is not known if some data has to be loaded or not. Often the resulting code is less efficient,
+because eager loading is used or the code is not elegant, because one has to program (somehow) lazy loading.
+Advantages of this library are that lazy-loading may be used quite elegant and effective.
+Examples
+^^^^^^^^
+In a loop it might happen that a special condition appears once or even more often. If this is the case,
+an expensive function `expensive_function` is called and on the resulting object an operation has
+to be done. If the expensive function had to called more than once, than the result object may be reused.
+Possible implementation:
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = None
+ for x, y, p in get_coordinates():
+ if test_for_something(x, y, p):
+ if obj is None:
+ obj = expensive_function()
+ obj.do_something(x, y)
+Given this library, it might be done like this:
+ from lazy_load import lazy
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = lazy(expensive_function)
+ for x, y, p in get_coordinates():
+ if test_for_something(x, y, p):
+ obj.do_something(x, y)
+There are similar situations outside of loops. The implementation without `lazy-load` might look like this:
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = None
+ def get_obj():
+ global obj
+ if obj is None:
+ obj = expensive_function()
+ return obj
+ if condition_a:
+ get_obj().xyz()
+ if condition_b:
+ do_something()
+ if condition_c:
+ get_obj().abc()
+This code can be realized much easier with `lazy-load`. Not only is the code shorter, but it is also more readable:
+ from lazy_load import lazy
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = lazy(expensive_function)
+ if condition_a:
+ obj.xyz()
+ if condition_b:
+ do_something()
+ if condition_c:
+ obj.abc()
+It might be the case that the expensive function is used more often and always a lazy evaluation is done.
+In this case, a decorator might be used to indicate that all function calls to this function shall be lazily
+evaluated. This makes it possible to normally use the function. The behaviour is still the same like in the first example:
+ from lazy_load import lazy_func
+ @lazy_func
+ def expensive_function():
+ print("function evaluation")
+ return result
+ obj = expensive_function()
+ for x, y, p in get_coordinates():
+ if test_for_something(x, y, p):
+ obj.do_something(x, y)
+A lazy evaluation of functions / methods calls might be done with the `@lazy_func` decorator of with the `lazy`-call. This was already
+shown, therefore the following examples show how to do a one-shot lazy evaluation of a function call:
+ from lazy_load import lazy, lz
+ def expensive_func(x, y):
+ print(f"function evaluation with arguments x={x}, y={y}")
+ return result
+ # Possibility 1: Use `lazy` with a callable
+ obj = lazy(lambda: expensive_func(a, b))
+ # Possibility 2: If it doesn't matter if the argument expressions for the expensive-function are eager evaluated, the call may be simplified:
+ obj = lazy(expensive_func, a, b)
+ # Possibility 3: `lazy` has a short version / alias: `lz`
+ obj = lz(expensive_func, a, b)
+Python allows it to pass functions around: This is often used for callbacks, but also for other use cases.
+Assuming an expensive function is passed to an object which calls this function and stores the result of
+the function call in an attribute. Later it might happen that this attribute is used. Depending on the
+program flow it also might happen that this attribute is not used. With a lazily evaluated function the
+expensive function call is only executed if the result is really used. The lazily evaluated version of
+a function has the exact same signature as the original function.
+One might now like to have the possibility to on-the-fly convert a callable to a lazily evaluated callable.
+This might be done in the following way:
+ from lazy_load import lazy_func, lf
+ def expensive_func(x):
+ print(f"function evaluation with argument x={x}")
+ return result
+ # Possibility 1: Use `lazy_func`.
+ my_obj.do_something(f=lazy_func(expensive_func))
+ # Possibility 2: Use `lf` which is an alias of `lazy_func`
+ my_obj.do_something(f=lf(expensive_func))
+ # Possibility 3: Use the `ℒ`-"operator"
+ my_obj.do_something(f=ℒ[expensive_func])
+Actually, I want to go deeper into the `ℒ`azy- or `ℒ`-"operator". This operator converts on-the-fly a function
+to a lazily evaluated function. Another example:
+ from lazy_load import ℒ
+ def test(name):
+ print(f"hey {name}")
+ return True
+ res = test("peter")
+ # prints "hey peter"
+ test_l = ℒ[test]
+ res = test_l("hans")
+ # prints nothing
+ if res:
+ print("res is True")
+ # prints "hey hans\nres is True"
+It is also possible to convert multiple functions to lazily evaluated functions using `ℒ`:
+ from lazy_load import ℒ
+ def f1(x):
+ print(f"f1 {x}")
+ return True
+ def f2(x):
+ print(f"f1 {x}")
+ return True
+ f1_l, f2_l, f3_l = ℒ[f1, f2, lambda x: x == 1]
+ # This is equal to:
+ f1_l = ℒ[f1]
+ f2_l = ℒ[f2]
+ f3_l = ℒ[lambda x: x == 1]
+Finally, one might like to decorate a class in a way that all its public methods which have a return
+value are lazily evaluated. Public methods are all methods that have a name not starting with `_`.
+Methods with a return value are identificated by the given return type hint which must not be `None`.
+This behaviour might be done with the `@lazy_class`-decorator (alias: `lc`):
+ from lazy_load import lazy_class
+ @lazy_class
+ class MyClass:
+ def __init__(self):
+ # Method name starts with "_" => is not public; therefore it is eager evaluated
+ pass
+ def setX(x) -> None:
+ # Method does not return a value => therefore it is eager evaluated
+ def do():
+ # Method does not hav a return value type hint => therefore it is eager evaluated
+ def compute() -> int:
+ # Method will always be lazily evaluated
+ return result
+Finally, it is also possible to force the evaluation of a lazy loading object by using `force_eval` (alias `fe`).
+This function can safely to used to non-lazy loading objects: It is then just equal to the identity function.
+ from lazy_load import lazy, force_eval
+ def f1(x):
+ print(f"f1 {x}")
+ return True
+ lazy_obj = lazy(f1, 1)
+ # The following expression prints "f1 1" and returns "True"
+ force_eval(lazy_obj)
+The `force_eval` function may also be applied to lazy-functions (which are created with `lazy_func(x)`, `@lazy_func`
+or with `ℒ`). This restores the original non-lazy / eager function. For non-lazy functions this call has no effect:
+ from lazy_load import lazy_func, force_eval
+ @lazy_func
+ def f(x):
+ print("hey")
+ return x**2
+ # The following line prints nothing
+ obj = f(2)
+ f_eager = force_eval(f)
+ # The following line prints "hey" and "obj" has immediatly the value "4"
+ obj = f_eager(2)
+
+%prep
+%autosetup -n lazy-load-0.8.3
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-lazy-load -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Wed May 10 2023 Python_Bot <Python_Bot@openeuler.org> - 0.8.3-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..c134326
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+1fcfeaba2d746dd00435477fc81d075f lazy_load-0.8.3.tar.gz