From 35d873032ea6495b7ca9baacfd2520af212202af Mon Sep 17 00:00:00 2001 From: janezd Date: Sat, 15 Aug 2026 09:16:02 +0200 Subject: [PATCH 1/8] wikipedia_api: Add user agent --- orangecontrib/text/wikipedia_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/orangecontrib/text/wikipedia_api.py b/orangecontrib/text/wikipedia_api.py index 3f1e64be2..a02d6f545 100644 --- a/orangecontrib/text/wikipedia_api.py +++ b/orangecontrib/text/wikipedia_api.py @@ -7,6 +7,7 @@ class NetworkException(IOError, wikipedia.exceptions.HTTPTimeoutError): pass +wikipedia.set_user_agent("Orange3-Text/1.0 (https://orange.biolab.si)") class WikipediaAPI: """ Wraps Wikipedia API. From 4c7b01bfb717dd135baebefb2f40d05c04ab7acd Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 21 Aug 2026 11:58:48 +0200 Subject: [PATCH 2/8] Add Uzbek language ISO code --- orangecontrib/text/language.py | 1 + 1 file changed, 1 insertion(+) diff --git a/orangecontrib/text/language.py b/orangecontrib/text/language.py index 536ad2531..7dd7fdd8f 100644 --- a/orangecontrib/text/language.py +++ b/orangecontrib/text/language.py @@ -99,6 +99,7 @@ "ug": "Uyghur", "uk": "Ukrainian", "ur": "Urdu", + "uz": "Uzbek", "vi": "Vietnamese", "zh": "Chinese", "zh_char": "Chinese - Chinese Characters", From 92dced302977d133535e15cd75be9306c6086748 Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 21 Aug 2026 11:59:30 +0200 Subject: [PATCH 3/8] StopWords.supported_languages: Fix classmethod+property decorators --- orangecontrib/text/preprocess/filter.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/orangecontrib/text/preprocess/filter.py b/orangecontrib/text/preprocess/filter.py index a8ea4b901..c24a0fd6c 100644 --- a/orangecontrib/text/preprocess/filter.py +++ b/orangecontrib/text/preprocess/filter.py @@ -20,6 +20,14 @@ 'PosTagFilter', 'NumbersFilter', 'WithNumbersFilter'] +class classproperty: + def __init__(self, fget): + self.fget = fget + + def __get__(self, obj, cls): + return self.fget(cls) + + class BaseTokenFilter(TokenizedPreprocessor): def __call__(self, corpus: Corpus, callback: Callable = None) -> Corpus: if callback is None: @@ -116,8 +124,7 @@ def lang_to_iso(language: str) -> str | None: """ return LANG2ISO.get(StopwordsFilter.NLTK2LANG.get(language, language)) - @classmethod - @property + @classproperty @wait_nltk_data def supported_languages(_) -> Set[str]: """ From 8d892b4398fc696962f91a004d84ea6697f17759 Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 21 Aug 2026 11:59:50 +0200 Subject: [PATCH 4/8] Concordances: Fix crash on data without metas --- orangecontrib/text/widgets/owconcordance.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orangecontrib/text/widgets/owconcordance.py b/orangecontrib/text/widgets/owconcordance.py index af34ee284..5c80472af 100644 --- a/orangecontrib/text/widgets/owconcordance.py +++ b/orangecontrib/text/widgets/owconcordance.py @@ -211,7 +211,7 @@ class Outputs: class Warning(OWWidget.Warning): multiple_words_on_input = Msg("Multiple query words on input. " - "Only the first one is considered!") + "Only the first one is considered.") def __init__(self): super().__init__() @@ -302,7 +302,7 @@ def set_word_from_input(self, topic): self.Warning.multiple_words_on_input.clear() if self.is_word_on_input: # word changed, clear selection self.selected_rows = [] - self.is_word_on_input = topic is not None and len(topic) > 0 + self.is_word_on_input = topic is not None and topic.metas.size > 0 self.input.setEnabled(not self.is_word_on_input) if self.is_word_on_input: if len(topic) > 1: From cbec50ec54264570cf42c43cb72d8c14cf95e329 Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 21 Aug 2026 12:00:12 +0200 Subject: [PATCH 5/8] WordList: Fix crash on empty words input --- orangecontrib/text/widgets/owwordlist.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/orangecontrib/text/widgets/owwordlist.py b/orangecontrib/text/widgets/owwordlist.py index f87e6abd6..fb6c14415 100644 --- a/orangecontrib/text/widgets/owwordlist.py +++ b/orangecontrib/text/widgets/owwordlist.py @@ -465,6 +465,8 @@ def _init_controls(self): self.__input_words_model.set_domain(domain) if len(self.__input_words_model) > 0: self.words_var = self.__input_words_model[0] + else: + self.words_var = None self.__input_box.setEnabled(bool(self.__input_words_model)) self._enable_words_actions() @@ -488,7 +490,7 @@ def _apply_update_rule(self): lib_words = self.library_model[lib_index].cached_words else: lib_words = self.words_model[:] - if self.__input_words is not None: + if self.words_var is not None: in_words = self.__input_words.get_column(self.words_var) in_words = list(in_words) update_rule = self.update_rule_index From 82d4ad1f2882a51908424fbf2fa32855bb50dda8 Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 21 Aug 2026 12:18:19 +0200 Subject: [PATCH 6/8] Keywords: Relax tests --- orangecontrib/text/widgets/tests/test_owkeywords.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orangecontrib/text/widgets/tests/test_owkeywords.py b/orangecontrib/text/widgets/tests/test_owkeywords.py index 76c4f36d0..9e04449c5 100644 --- a/orangecontrib/text/widgets/tests/test_owkeywords.py +++ b/orangecontrib/text/widgets/tests/test_owkeywords.py @@ -197,8 +197,8 @@ def test_sort_nans_asc(self): self.send_signal(widget.Inputs.corpus, self.corpus, widget=widget) self.wait_until_finished(widget=widget) output = self.get_output(widget.Outputs.words, widget=widget) - self.assertListEqual(list(output.metas[:, 0]), - ["System", "Widths", "opinion"]) + self.assertEqual(set(output.metas[:, 0]), + {"System", "Widths", "opinion"}) def test_scoring_methods(self): # speed-up the test execution From bd03c1d6aefd8a02b3a6720363ee6d0a843d3ab0 Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 21 Aug 2026 12:27:58 +0200 Subject: [PATCH 7/8] Bump pandas on 'oldest' to fix tests on Python 3.11 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index be265eaf3..1abcc0f7e 100644 --- a/tox.ini +++ b/tox.ini @@ -28,7 +28,7 @@ deps = oldest: orange3==3.38.1 oldest: orange-canvas-core==0.2.5 oldest: orange-widget-base==4.25.0 - oldest: pandas==1.4.0 + oldest: pandas==1.5.3 oldest: nltk==3.9.1 latest: https://github.com/biolab/orange3/archive/refs/heads/master.zip#egg=orange3 latest: https://github.com/biolab/orange3-network/archive/refs/heads/master.zip#egg=orange3-network From 83dbaf9be6d0bb78a51e78b5621272cfb37bfd7f Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 21 Aug 2026 13:35:05 +0200 Subject: [PATCH 8/8] NYT: Patch tests to not ask for credentials --- orangecontrib/text/widgets/tests/test_ownyt.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/orangecontrib/text/widgets/tests/test_ownyt.py b/orangecontrib/text/widgets/tests/test_ownyt.py index 19661b9e8..20c489766 100644 --- a/orangecontrib/text/widgets/tests/test_ownyt.py +++ b/orangecontrib/text/widgets/tests/test_ownyt.py @@ -1,4 +1,5 @@ import unittest +from unittest.mock import patch from orangecontrib.text.widgets.ownyt import OWNYT from orangecontrib.text.widgets.utils import CheckListLayout @@ -7,7 +8,9 @@ class TestOWNYT(WidgetTest): def setUp(self) -> None: - self.widget = self.create_widget(OWNYT) + with patch("orangecontrib.text.widgets.ownyt.OWNYT.APICredentialsDialog"): + self.widget = self.create_widget(OWNYT) + def test_text_includes_gui(self): """Check that Text includes section has all controls"""