diff --git a/tests/timeit/21.weakref.01.py b/tests/timeit/21.weakref.01.py new file mode 100755 index 00000000..4eb4b1e5 --- /dev/null +++ b/tests/timeit/21.weakref.01.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys, os, weakref + +import timeit +from threading import Lock + +class Foo(): + def a(self,v): + return v+v*v + +f1 = Foo() +f21 = Foo() +f22 = Foo() + +a1 = f1.a +a21 = weakref.WeakMethod(f21.a) +a22 = weakref.WeakMethod(f22.a) +a31 = weakref.ref(_a31:=f21.a) +a32 = weakref.ref(_a32:=f22.a) + +del f22,_a32 + +def test1(v=a1,ff=f1): return sum([ v(x) for x in range(100)]) + +def test2(v=a21,ff=f21): return sum([v()(x) if v() else 0 for x in range(100)]) +def test3(v=a22,ff=f21): return sum([v()(x) if v() else 0 for x in range(100)]) +def test4(v=a21,ff=f21): return sum([ _v(x) if (_v:=v()) else 0 for x in range(100)]) +def test5(v=a22,ff=f21): return sum([ _v(x) if (_v:=v()) else 0 for x in range(100)]) + +def test6(v=a31,ff=f21): return sum([v()(x) if v() else 0 for x in range(100)]) +def test7(v=a32,ff=f21): return sum([v()(x) if v() else 0 for x in range(100)]) +def test8(v=a31,ff=f21): return sum([ _v(x) if (_v:=v()) else 0 for x in range(100)]) +def test9(v=a32,ff=f21): return sum([ _v(x) if (_v:=v()) else 0 for x in range(100)]) + +loop = 10000 + +a = {} + +iii = 1 +while (testName := f'test{iii}') and (testName in globals()): + result = timeit.timeit(f'{testName}(*a)', globals=globals(), number=loop) + # print(f"test{iii}) fps {loop / result :.3f} - s {result / loop:.10f} - {result / loop} {globals()[testName](*a)}") + print(f"test{iii:02}) | {result / loop:.10f} sec. | {loop / result : 15.3f} Fps ╞╡-> {globals()[testName](*a)}") + iii+=1 + diff --git a/tests/timeit/22.queue.01.py b/tests/timeit/22.queue.01.py new file mode 100755 index 00000000..0406005c --- /dev/null +++ b/tests/timeit/22.queue.01.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys, os, weakref + +import timeit +from queue import Queue + +qu = Queue() +r = 100 + +def test1(q=qu): + ret = 0 + for i in range(r): + ret += i + return ret + +def test2(q=qu): + ret = 0 + for i in range(r): + qu.put(i) + while x := q.get(): + ret += x + return ret + +def test3(q=qu): + ret = 0 + ar = [] + for i in range(r): + ar.append(i) + for x in ar: + ret += x + return ret + +def test4(q=qu): + return sum(i for i in range(r)) + +def test5(q=qu): + ar = [] + for i in range(r): + ar.append(i) + return sum(ar) + +def test6(q=qu): + ret = 0 + ar = [] + for i in range(r): + ar.append(i) + while ar: + ret += ar.pop() + return ret + +loop = 1000 + +a = {} + +iii = 1 +while (testName := f'test{iii}') and (testName in globals()): + result = timeit.timeit(f'{testName}(*a)', globals=globals(), number=loop) + # print(f"test{iii}) fps {loop / result :.3f} - s {result / loop:.10f} - {result / loop} {globals()[testName](*a)}") + print(f"test{iii:02}) | {result / loop:.10f} sec. | {loop / result : 15.3f} Fps ╞╡-> {globals()[testName](*a)}") + iii+=1 + diff --git a/tests/test.generic.006.weakref.01.py b/tests/weakref/test.01.py similarity index 100% rename from tests/test.generic.006.weakref.01.py rename to tests/weakref/test.01.py diff --git a/tests/test.generic.006.weakref.02.py b/tests/weakref/test.02.py similarity index 100% rename from tests/test.generic.006.weakref.02.py rename to tests/weakref/test.02.py diff --git a/tests/test.generic.006.weakref.03.py b/tests/weakref/test.03.py similarity index 100% rename from tests/test.generic.006.weakref.03.py rename to tests/weakref/test.03.py diff --git a/tests/weakref/test.04.gc.01.py b/tests/weakref/test.04.gc.01.py new file mode 100755 index 00000000..d41e6883 --- /dev/null +++ b/tests/weakref/test.04.gc.01.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Example inspired by +# https://stackoverflow.com/questions/39838793/python-object-is-being-referenced-by-an-object-i-cannot-find + +import gc, weakref + +class Foo(object): + __slots__ = ('a','b') + def __init__(self, a=1234) -> None: + self.a = a + self.b = lambda : self.a + + def f(self): + return self.a + + # def __del__(self): + # print(f"Deleted {self}") + +def pobjs(): + for i,o in enumerate(gc.get_objects()[-100:]): + ss = str(o) + if "Foo" in ss: + print(f" * {i} - {ss}") + +v1 = {'b':2345} + +print(f"\nStart {gc.isenabled()=}") +# print(f"{gc.set_debug(gc.DEBUG_LEAK)=}") + +print("\n############# Phase 1 ##################") +foo = Foo(v1) +print(f"{gc.get_referents(foo)=}") +print(f"{gc.get_count()=}") +print(f"{foo.a=} - {foo.b=} - {foo.f()=}") +del foo +print(f"{gc.collect()=}") + +print("\n############# Phase 2 ##################") +foo = Foo(v1) +bar = foo.a +print(f"{gc.get_referents(foo)=}") +print(f"{gc.get_count()=}") +print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar=}") +del foo +print(f"{gc.collect()=}") +print(f"{bar=}") + +print("\n############# Phase 3 ##################") +foo = Foo(v1) +bar = foo.b +print(f"{gc.get_referents(foo)=}") +print(f"{gc.get_count()=}") +print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()=}") +del foo +print(f"{gc.collect()=}") +print(f"{bar()=}") + +print("\n############# Phase 4 ##################") +foo = Foo(v1) +bar = foo.b +print(f"{gc.get_referents(foo)=}") +print(f"{gc.get_referents(v1)=}") +print(f"{gc.get_count()=}") +print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()=}") +del foo +pobjs() +print(f"{gc.collect()=}") +print(f"{bar()=}") +del bar +pobjs() +print(f"{gc.collect()=}") +pobjs() + +print("\n############# Phase 5 ##################") +foo = Foo(v1) +bar = weakref.ref(foo.b) +xx = foo.f +baz = weakref.ref(xx) +print(f"{gc.get_referents(foo)=}") +print(f"{gc.get_referents(v1)=}") +print(f"{gc.get_count()=}") +print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()()=}") +del foo +pobjs() +print(f"{gc.collect()=}") +print(f"{bar()() if bar() else None=}") +del bar +pobjs() +print(f"{gc.collect()=}") +pobjs() + +print(f"{gc.garbage=}") +print(f"End {gc.get_count()=}") diff --git a/tests/weakref/test.04.gc.02.py b/tests/weakref/test.04.gc.02.py new file mode 100755 index 00000000..9131f429 --- /dev/null +++ b/tests/weakref/test.04.gc.02.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Example inspired by +# https://stackoverflow.com/questions/39838793/python-object-is-being-referenced-by-an-object-i-cannot-find + +import gc, weakref, time + +class Foo(): + __slots__ = ('__weakref__','a','b') + def __init__(self, a=1234) -> None: + self.a = a + self.b = lambda : self.a + + def f(self): + return self.a + + # def __del__(self): + # print(f"Deleted {self}") + +def pobjs(): + for i,o in enumerate(gc.get_objects()[-100:]): + ss = str(o) + if "Foo" in ss: + print(f" * {i} - {ss}") + +v1 = {'b':2345} + +print(f"\nStart {gc.isenabled()=}") +# print(f"{gc.set_debug(gc.DEBUG_LEAK)=}") + +def _gccb(phase,info): + print(f" ---> {gc.garbage=}") + print(f" ---> {phase=} {info=}") + +# gc.callbacks.append(_gccb) + +print("\n############# Phase 1 ##################") +foo = Foo(v1) +bar =foo.b + +wrfoo = weakref.ref(foo) +wrbar = weakref.ref(bar) +wrf = weakref.WeakMethod(foo.f) + +# print(f"{gc.get_referents(foo)=}") +# print(f"{gc.get_referrers(foo)=}") +# print(f"{gc.get_referents(v1)=}") +# print(f"{gc.get_referrers(v1)=}") +# print(f"{gc.get_count()=}") +print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()=}") +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") +del foo +print(f"{gc.collect()=}") +print(f"{bar()}") +# print(f"{gc.get_referents(v1)=}") +# print(f"{gc.get_referrers(v1)=}") +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") +bar = None +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") +time.sleep(4) +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") +print(f"{gc.collect()=}") +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") + +print(f"{gc.garbage=}") +print(f"End {gc.get_count()=}") diff --git a/tests/weakref/test.04.gc.03.py b/tests/weakref/test.04.gc.03.py new file mode 100755 index 00000000..e678cb66 --- /dev/null +++ b/tests/weakref/test.04.gc.03.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Example inspired by +# https://stackoverflow.com/questions/39838793/python-object-is-being-referenced-by-an-object-i-cannot-find + +import gc, weakref, time + +class Bar(): + __slots__ = ('_foo') + def __init__(self, foo) -> None: + self._foo = foo + +class Foo(): + __slots__ = ('__weakref__','a','b','_bar') + def __init__(self, a=1234) -> None: + self._bar = Bar(self) + self.a = a + self.b = lambda : self.a + + def f(self): + return self.a + + # def __del__(self): + # print(f"Deleted {self}") + +def pobjs(): + for i,o in enumerate(gc.get_objects()[-100:]): + ss = str(o) + if "Foo" in ss: + print(f" * {i} - {ss}") + +def _ref(o): + print(f"\n### -> Referents - {o}") + for i,r in enumerate(gc.get_referents(o)): + print(f" - {i} ) {r}") + print(f"\n### -> Referrers - {o}") + for i,r in enumerate(gc.get_referrers(o)): + print(f" - {i} ) {r}") + print("") + +v1 = {'b':2345} + +print(f"\nStart {gc.isenabled()=}") +# print(f"{gc.set_debug(gc.DEBUG_LEAK)=}") + +def _gccb(phase,info): + print(f" ---> {gc.garbage=}") + print(f" ---> {phase=} {info=}") + +# gc.callbacks.append(_gccb) + +print("\n############# Phase 1 ##################") +foo = Foo(v1) +bar =foo.b + +wrfoo = weakref.ref(foo) +wrbar = weakref.ref(bar) +wrf = weakref.WeakMethod(foo.f) + +# print(f"{gc.get_referents(foo)=}") +# print(f"{gc.get_referrers(foo)=}") +# print(f"{gc.get_referents(v1)=}") +# print(f"{gc.get_referrers(v1)=}") +# print(f"{gc.get_count()=}") +_ref(foo) + +print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()=}") +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") +del foo +print(f"{gc.collect()=}") +print(f"{bar()}") +# print(f"{gc.get_referents(v1)=}") +# print(f"{gc.get_referrers(v1)=}") +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") +bar = None +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") +time.sleep(4) +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") +print(f"{gc.collect()=}") +print(f"{wrfoo()=} {wrbar()=} {wrf()=}") + +print(f"{gc.garbage=}") +print(f"End {gc.get_count()=}") diff --git a/tests/weakref/test.05.TermTk.01.py b/tests/weakref/test.05.TermTk.01.py new file mode 100755 index 00000000..775c20ae --- /dev/null +++ b/tests/weakref/test.05.TermTk.01.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys, os +import gc, weakref, time + +sys.path.append(os.path.join(sys.path[0],'../..')) +sys.path.append(os.path.join(sys.path[0],'.')) +import TermTk as ttk + +def pobjs(): + for i,o in enumerate(gc.get_objects()[-100:]): + ss = str(o) + if "Foo" in ss: + print(f" * {i} - {ss}") + +print(f"\nStart {gc.isenabled()=}") + +def _gccb(phase,info): + print(f" ---> {gc.garbage=}") + print(f" ---> {phase=} {info=}") +# gc.callbacks.append(_gccb) + +def _ref(o): + print(f"\n### -> Referents - {o}") + for i,r in enumerate(gc.get_referents(o)): + print(f" - {i} ) {r}") + print(f"\n### -> Referrers - {o}") + for i,r in enumerate(gc.get_referrers(o)): + print(f" - {i} ) {r}") + for ii,rr in enumerate(gc.get_referrers(r)): + print(f" | {ii} ) {rr}") + print("") + print("") + +print("\n############# Phase 1 ##################") +# wid = ttk.TTkWidget() +# wid = ttk.TTkButton() +# wid = ttk.TTkLabel() +# wid = ttk.TTkGraph() +# wid = ttk.TTkSpacer() +# wid = ttk.TTkSplitter() +# wid = ttk.TTkCanvas() +# sizef = wid.size +sizef = [] + +ttk.TTkHelper._updateWidget = set() +ttk.TTkHelper._updateBuffer = set() + +wrwid = weakref.ref(wid) +# wrsizef = weakref.ref(sizef) +wrsizef = wrwid +# wrsizef2 = weakref.WeakMethod(wid.size) +wrsizef2 = wrwid + +_ref(wid) + +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +del wid +print(f"{gc.collect()=}") +# print(f"{sizef()}") +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +sizef = None +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +# time.sleep(4) +# print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +print(f"{gc.collect()=}") +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") + +print(f"{gc.garbage=}") +print(f"End {gc.get_count()=}") diff --git a/tests/weakref/test.05.TermTk.02.py b/tests/weakref/test.05.TermTk.02.py new file mode 100755 index 00000000..e12812ad --- /dev/null +++ b/tests/weakref/test.05.TermTk.02.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys, os +import gc, weakref, time + +sys.path.append(os.path.join(sys.path[0],'../..')) +sys.path.append(os.path.join(sys.path[0],'.')) +import TermTk as ttk + +def pobjs(): + for i,o in enumerate(gc.get_objects()[-100:]): + ss = str(o) + if "Foo" in ss: + print(f" * {i} - {ss}") + +print(f"\nStart {gc.isenabled()=}") + +def _gccb(phase,info): + print(f" ---> {gc.garbage=}") + print(f" ---> {phase=} {info=}") +# gc.callbacks.append(_gccb) + +def _ref(o): + print(f"\n### -> Referents - {o}") + for i,r in enumerate(gc.get_referents(o)): + print(f" - {i} ) {r}") + print(f"\n### -> Referrers - {o}") + for i,r in enumerate(gc.get_referrers(o)): + print(f" - {i} ) {r}") + for ii,rr in enumerate(gc.get_referrers(r)): + print(f" | {ii} ) {rr}") + print("") + print("") + + +class TestWid(ttk.TTkWidget): + __slots__ = ('_a','_b') + def __init__(self, *args, **kwargs): + self.setDefaultSize(kwargs, 10, 10) + super().__init__(*args, **kwargs) + self._b = ttk.pyTTkSignal(bool) + self.setFocusPolicy(ttk.TTkK.ClickFocus + ttk.TTkK.TabFocus) + + def mousePressEvent(self, evt): + # TTkLog.debug(f"{self._text} Test Mouse {evt}") + self.update() + return True + + def paintEvent(self, canvas): + canvas.fill(pos=(0,0), size=(2,2)) + +print("\n############# Phase 1 ##################") +# wid = ttk.TTkWidget() +wid = ttk.TTkButton() +# wid = ttk.TTkGraph() +# wid = ttk.TTkSpacer() +# wid = ttk.TTkSplitter() +# wid = TestWid() +# sizef = wid.size +sizef = [] + +wrwid = weakref.ref(wid) +# wrsizef = weakref.ref(sizef) +wrsizef = wrwid +# wrsizef2 = weakref.WeakMethod(wid.size) +wrsizef2 = wrwid + +_ref(wid) + +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +del wid +print(f"{gc.collect()=}") +# print(f"{sizef()}") +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +sizef = None +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +# time.sleep(4) +# print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +print(f"{gc.collect()=}") +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") + +print(f"{gc.garbage=}") +print(f"End {gc.get_count()=}") diff --git a/tests/weakref/test.05.TermTk.03.signals.py b/tests/weakref/test.05.TermTk.03.signals.py new file mode 100755 index 00000000..8446847a --- /dev/null +++ b/tests/weakref/test.05.TermTk.03.signals.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys, os +import gc, weakref, time + +sys.path.append(os.path.join(sys.path[0],'../..')) +sys.path.append(os.path.join(sys.path[0],'.')) +import TermTk as ttk + +def pobjs(): + for i,o in enumerate(gc.get_objects()[-100:]): + ss = str(o) + if "Foo" in ss: + print(f" * {i} - {ss}") + +print(f"\nStart {gc.isenabled()=}") + +def _gccb(phase,info): + print(f" ---> {gc.garbage=}") + print(f" ---> {phase=} {info=}") +# gc.callbacks.append(_gccb) + +def _ref(o): + print(f"\n### -> Referents - {o}") + for i,r in enumerate(gc.get_referents(o)): + print(f" - {i} ) {r}") + print(f"\n### -> Referrers - {o}") + for i,r in enumerate(gc.get_referrers(o)): + print(f" - {i} ) {r}") + for ii,rr in enumerate(gc.get_referrers(r)): + print(f" | {ii} ) {rr}") + print("") + print("") + +print("\n############# Phase 1 ##################") + +root = ttk.TTkWidget() +# wid = ttk.TTkWidget() +wid = ttk.TTkButton() +# wid = ttk.TTkLabel() +# wid = ttk.TTkGraph() +# wid = ttk.TTkSpacer() +# wid = ttk.TTkSplitter() +# sizef = wid.size +sizef = [] + +root.closed.connect(wid.close) + +ttk.TTkHelper._updateWidget = set() +ttk.TTkHelper._updateBuffer = set() + +wrwid = weakref.ref(wid) +# wrsizef = weakref.ref(sizef) +wrsizef = wrwid +# wrsizef2 = weakref.WeakMethod(wid.size) +wrsizef2 = wrwid + +_ref(wid) + +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +del wid +print(f"{gc.collect()=}") +# print(f"{sizef()}") +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +sizef = None +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +# time.sleep(4) +# print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") +print(f"{gc.collect()=}") +print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") + +print(f"{gc.garbage=}") +print(f"End {gc.get_count()=}")