diff --git a/.spellcheck_exceptions_dictionary.txt b/.spellcheck_exceptions_dictionary.txt index ceeceab..d82e23c 100644 --- a/.spellcheck_exceptions_dictionary.txt +++ b/.spellcheck_exceptions_dictionary.txt @@ -52,7 +52,11 @@ userspace userguide sdist exe - +hashable +checksubclass +issubclasshook +issubclass +metaclass # python keywords pprint diff --git a/2_standard_library/29_python_runtime_services/0_def.txt b/2_standard_library/29_python_runtime_services/0_python_runtime_services.txt similarity index 69% rename from 2_standard_library/29_python_runtime_services/0_def.txt rename to 2_standard_library/29_python_runtime_services/0_python_runtime_services.txt index 23cb54f..236899b 100644 --- a/2_standard_library/29_python_runtime_services/0_def.txt +++ b/2_standard_library/29_python_runtime_services/0_python_runtime_services.txt @@ -15,4 +15,5 @@ def python_runtime_services: - proof: ??? -References: ??? +References: + The Python Standard Library. Python Runtime Services. 2025. https://docs.python.org/3/library/python.html diff --git a/2_standard_library/29_python_runtime_services/9_abcs.txt b/2_standard_library/29_python_runtime_services/9_abcs.txt new file mode 100755 index 0000000..d840d9d --- /dev/null +++ b/2_standard_library/29_python_runtime_services/9_abcs.txt @@ -0,0 +1,27 @@ +def abcs: + - formal: ??? + + - in words: ??? + + - plain english: ??? + + - intuition: ??? + + - properties: + - specification: + - https://peps.python.org/pep-3119/ + - https://docs.python.org/3/library/abc.html#module-abc + + - implementation: https://github.com/python/cpython/blob/3.13/Lib/abc.py + + + - examples: ??? + + - use cases: + - register a third-party class as a subclass of our own abstract class(i.e. metaclass) + this enables using the third-party class in polymorphic code as a subclass. + + - proof: ??? + +References: + The Python Standard Library. Python Runtime Services. 2025. https://docs.python.org/3/library/python.html diff --git a/2_standard_library/4_built_in_types/5_iterator_types/1_iterator.txt b/2_standard_library/4_built_in_types/5_iterator_types/1_iterator.txt index 8c068f6..9ade1af 100644 --- a/2_standard_library/4_built_in_types/5_iterator_types/1_iterator.txt +++ b/2_standard_library/4_built_in_types/5_iterator_types/1_iterator.txt @@ -26,5 +26,5 @@ def iterator: - proof: None. It is a definition. References: - https://docs.python.org/3.11/glossary.html#term-iterator + The Python Standard Library. 2025. https://docs.python.org/3/glossary.html#term-iterator diff --git a/2_standard_library/4_built_in_types/5_iterator_types/2_generator.txt b/2_standard_library/4_built_in_types/5_iterator_types/2_generator.txt index 85b359f..678ae1f 100644 --- a/2_standard_library/4_built_in_types/5_iterator_types/2_generator.txt +++ b/2_standard_library/4_built_in_types/5_iterator_types/2_generator.txt @@ -21,6 +21,6 @@ def generator | generator function: - proof: None. It is a definition. References: - https://docs.python.org/3.11/glossary.html#term-generator + The Python Standard Library. 2025. https://docs.python.org/3/glossary.html#term-generator diff --git a/2_standard_library/4_built_in_types/5_iterator_types/3_generator_expression.txt b/2_standard_library/4_built_in_types/5_iterator_types/3_generator_expression.txt index 7b7a2dd..9957600 100644 --- a/2_standard_library/4_built_in_types/5_iterator_types/3_generator_expression.txt +++ b/2_standard_library/4_built_in_types/5_iterator_types/3_generator_expression.txt @@ -19,5 +19,5 @@ - proof: None. It is a definition. References: - https://docs.python.org/3.11/glossary.html#term-generator-iterator + The Python Standard Library. 2025. https://docs.python.org/3/glossary.html#term-generator-iterator diff --git a/2_standard_library/8_data_types/5_collections_abstract_base_classes/0_collections_abcs.txt b/2_standard_library/8_data_types/5_collections_abstract_base_classes/0_collections_abcs.txt new file mode 100644 index 0000000..dc828fc --- /dev/null +++ b/2_standard_library/8_data_types/5_collections_abstract_base_classes/0_collections_abcs.txt @@ -0,0 +1,27 @@ +def collections_abcs: + - formal: ??? + + - in words: ??? + + - plain english: ??? + + - intuition: ??? + + - properties: + - implementation: https://github.com/python/cpython/tree/3.11/Lib/_collections_abc.py + - specification: https://docs.python.org/3/library/collections.abc.html + - examples: + - test interface compliance: + - hashable + - iterable + - mapping + - ... + + - use cases: + - implement custom classes that satisfy the container API. + - test compliance to a collections' interface using `issubclass` or `isinstance`. + + - proof: ??? + +References: + The Python Standard Library. 2025. collections.abc — Abstract Base Classes for Containers, Data Types. https://docs.python.org/3/library/collections.abc.html diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/app.py b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/app.py new file mode 100644 index 0000000..cd4188d --- /dev/null +++ b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/app.py @@ -0,0 +1,20 @@ +from workers.worker import Worker +from thirdparty.third_party_class import ThirdPartyWorker +from interfaces.s_one import SOneContract +from interfaces.s_two import STwoContract + +if __name__ == "__main__": + + """ + This is the registration of the third party to enable our system to treat it as a subclass of SOneContract". + This makes ThirdPartyWorker a virtual subclass of SOneContract + """ + SOneContract.register(ThirdPartyWorker) + + workers = [Worker(), ThirdPartyWorker()] + + for worker in workers: + if(isinstance(worker, SOneContract)): + worker.do_work() + if(isinstance(worker, STwoContract)): + worker.s_two_work() \ No newline at end of file diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/interfaces/__init__.py b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/interfaces/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/interfaces/s_one.py b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/interfaces/s_one.py new file mode 100644 index 0000000..e192f0d --- /dev/null +++ b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/interfaces/s_one.py @@ -0,0 +1,22 @@ +from abc import ABCMeta, abstractmethod + +class SOneContract(metaclass = ABCMeta): + + @abstractmethod + def do_work(self): + raise NotImplemented + + """ + # NB: @abstractmethod only applies to subclasses created using regular inheritance. + virtual sub classes can be instantiated without implementing it, while regular subclasses cannot. + @abstractmethod + def s_one_specialty(self): + raise NotImplemented + """ + + def __issubclasshook__(cls): + """ + NB: Alternativeltm we overload the behvaiour of `issubclass` function for SOneContract + and define what it means to be a SOneContract. + """ + pass \ No newline at end of file diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/interfaces/s_two.py b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/interfaces/s_two.py new file mode 100644 index 0000000..6273a12 --- /dev/null +++ b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/interfaces/s_two.py @@ -0,0 +1,9 @@ +from abc import ABC + +class STwoContract(ABC): + """ + NB: This is an alternative to explicitly setting the metaclass to ABCMeta. + The ABC class is syntactic sugar. + """ + def s_two_work(self): + pass \ No newline at end of file diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/scenario.txt b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/scenario.txt new file mode 100644 index 0000000..d8c401d --- /dev/null +++ b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/scenario.txt @@ -0,0 +1,12 @@ +two teams: + - internal classes that implement some contract + - immutable third party provided classes that implement some contract + +issues: + - we have polymorphic code that delegates to work workers, based on the contract they implement, that cannot be checked with duck typing. + - solution: + - register the third party classes as a subclass using Python's ABCs. + - implement custom behaviour for `issubclass` for a specific ABC, using `__issubclasshook__()`. + - __issubclasshook__() is used by __checksubclass__() + + diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/thirdparty/__init__.py b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/thirdparty/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/thirdparty/third_party_class.py b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/thirdparty/third_party_class.py new file mode 100644 index 0000000..b92ce1d --- /dev/null +++ b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/thirdparty/third_party_class.py @@ -0,0 +1,3 @@ +class ThirdPartyWorker: + def do_work(self): + print("I am a third party class doing work") \ No newline at end of file diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/workers/__init__.py b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/workers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/workers/worker.py b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/workers/worker.py new file mode 100644 index 0000000..750c1da --- /dev/null +++ b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/1_abc_meta/workers/worker.py @@ -0,0 +1,5 @@ +from interfaces.s_one import SOneContract + +class Worker(SOneContract): + def do_work(self): + print("I am an internal worker doing work") \ No newline at end of file diff --git a/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/2_decorators/TestClassMethodDecorator.py b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/2_decorators/TestClassMethodDecorator.py new file mode 100644 index 0000000..d686564 --- /dev/null +++ b/4_experiments/2_standard_library/29_python_runtime_services/9_abcs/2_decorators/TestClassMethodDecorator.py @@ -0,0 +1,44 @@ +import abc +from abc import abstractmethod + +class TestClassMethodDecorator(): + @staticmethod + def method_static_method(): + print("In static method") + + @classmethod + def method_class_method(cls): + print("In class method") + + @abstractmethod + def method_abstract(self): + print("In abstract method") + + @staticmethod + @abstractmethod + def method_abstract_static(): + print("In abstract static method") + + def invoke_method_static_method_in_class(self): + """ + Q: why can't we do this? + """ + method_static_method() + + +if __name__ == "__main__": + print(f"Test: {TestClassMethodDecorator.__name__}") + a = TestClassMethodDecorator() + a.method_static_method() + TestClassMethodDecorator.method_static_method() + # a.invoke_method_static_method_in_class() + + a.method_abstract() + # TestClassMethodDecorator.method_abstract() + TestClassMethodDecorator.method_abstract_static() + + a.method_class_method() + TestClassMethodDecorator.method_class_method() + + print(abc.get_cache_token()) + print(type(abc.get_cache_token())) \ No newline at end of file