From efaf64d6458295d3700b44632eb27730eac2cd4e Mon Sep 17 00:00:00 2001 From: Iwan Aucamp Date: Sun, 10 Oct 2021 22:14:09 +0200 Subject: [PATCH] Make namespaces a generator by default 90f6fe5 changed ```python class Store: def namespaces(self): """ """ if False: yield None ``` to ```python class Store: def namespaces(self): """ """ ``` This resulted in `Store.namespaces` no longer being an emtpy generator by default (see https://stackoverflow.com/q/13243766). The reason it was removed is because it is unreachable code, however I did not consider that it would make the function an empty generator. The reason why `if False: yield None` made it an empty generator is because the presence of the yield keyword informs CPython that a function is a generator: https://www.python.org/dev/peps/pep-0255/#why-a-new-keyword-for-yield-why-not-a-builtin-function-instead There are several ways of making an empty generator: - `if False: yield` - `return` and `yield` - `yield from ()` - ... more Both `if False: yield` and `return`; `yield` results in same bytecode however, which is that of an empty function, and they are both equally confusing I would say. `yield from ()` is somewhat clearer, but the bytecode of the funciton looks very different from an empty function (see https://stackoverflow.com/a/61496399) So the best option I see is to just put back what was there and add a comment and a test to prevent the issue from re-occuring. --- rdflib/store.py | 5 +++++ test/test_store.py | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 test/test_store.py diff --git a/rdflib/store.py b/rdflib/store.py index 915ca57ad4..a7aa8d0b09 100644 --- a/rdflib/store.py +++ b/rdflib/store.py @@ -364,6 +364,11 @@ def namespace(self, prefix): def namespaces(self): """ """ + # This is here so that the function becomes an empty generator. + # See https://stackoverflow.com/q/13243766 and + # https://www.python.org/dev/peps/pep-0255/#why-a-new-keyword-for-yield-why-not-a-builtin-function-instead + if False: + yield None # type: ignore[unreachable] # Optional Transactional methods diff --git a/test/test_store.py b/test/test_store.py new file mode 100644 index 0000000000..c1beb5e156 --- /dev/null +++ b/test/test_store.py @@ -0,0 +1,18 @@ +import unittest +from rdflib import Graph, URIRef +from tempfile import NamedTemporaryFile, TemporaryDirectory +from pathlib import Path, PurePath +from rdflib.store import Store + + +class TestAbstractStore(unittest.TestCase): + def test_namespaces(self): + """ + This tests that Store.namespaces is an empty generator. + """ + my_store = Store() + self.assertEqual(list(my_store.namespaces()), []) + + +if __name__ == "__main__": + unittest.main()