From 28266712bec21f329a1087d670bea31a091b09b3 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sun, 21 Dec 2025 04:32:28 -0500 Subject: [PATCH 1/2] Fix GitHub tests without a network connection The wrapper is supposed to catch connection errors and turn them into `xfail`, but `test_rmdir_not_empty` _also_ catches connection errors because they are `OSError` (which is what it expect, thus the test still fails everything. Instead, change the `xfail_on_github_rate_limit` function to check for networking first, and mark everything `xfail` directly. Also, remove the `_xfail_on_rate_limit_errors` fixture, which is redundant to the above and doesn't work fully because it only applies to the class's direct test methods and not its inherited test methods. --- upath/tests/implementations/test_github.py | 24 ++++++++-------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/upath/tests/implementations/test_github.py b/upath/tests/implementations/test_github.py index a5318917..b6ac2065 100644 --- a/upath/tests/implementations/test_github.py +++ b/upath/tests/implementations/test_github.py @@ -25,16 +25,12 @@ def xfail_on_github_rate_limit(func): @functools.wraps(func) def wrapped_method(self, *args, **kwargs): - import requests - try: return func(self, *args, **kwargs) except AssertionError as e: if "nodename nor servname provided, or not known" in str(e): pytest.xfail(reason="No internet connection") raise - except requests.exceptions.ConnectionError: - pytest.xfail(reason="No internet connection") except Exception as e: if "rate limit exceeded" in str(e): pytest.xfail("GitHub API rate limit exceeded") @@ -49,10 +45,18 @@ def wrap_github_rate_limit_check(cls): Class decorator to wrap all test methods with the xfail_on_github_rate_limit decorator. """ + import requests + + try: + requests.get("http://example.com") + except requests.exceptions.ConnectionError: + wrapper = pytest.mark.xfail(reason="No internet connection") + else: + wrapper = xfail_on_github_rate_limit for attr_name in dir(cls): if attr_name.startswith("test_"): orig_method = getattr(cls, attr_name) - setattr(cls, attr_name, xfail_on_github_rate_limit(orig_method)) + setattr(cls, attr_name, wrapper(orig_method)) return cls @@ -70,16 +74,6 @@ def path(self): path = "github://ap--:universal_pathlib@test_data/data" self.path = UPath(path) - @pytest.fixture(autouse=True) - def _xfail_on_rate_limit_errors(self): - try: - yield - except Exception as e: - if "rate limit exceeded" in str(e): - pytest.xfail("GitHub API rate limit exceeded") - else: - raise - def test_is_GitHubPath(self): """ Test that the path is a GitHubPath instance. From 4f4d06a87119ff028817ad839d9cf106525f2b13 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Sun, 21 Dec 2025 15:40:16 +0100 Subject: [PATCH 2/2] tests: improve stability of github connection / ratelimit error checking --- upath/tests/implementations/test_github.py | 57 ++++++++++------------ 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/upath/tests/implementations/test_github.py b/upath/tests/implementations/test_github.py index b6ac2065..4783b823 100644 --- a/upath/tests/implementations/test_github.py +++ b/upath/tests/implementations/test_github.py @@ -18,49 +18,42 @@ ) -def xfail_on_github_rate_limit(func): - """ - Method decorator to mark test as xfail when GitHub rate limit is exceeded. - """ +def xfail_on_github_connection_error(func): + """Method decorator to xfail tests on GitHub rate limit or connection errors.""" @functools.wraps(func) - def wrapped_method(self, *args, **kwargs): + def wrapper(self, *args, **kwargs): try: return func(self, *args, **kwargs) - except AssertionError as e: - if "nodename nor servname provided, or not known" in str(e): - pytest.xfail(reason="No internet connection") - raise except Exception as e: - if "rate limit exceeded" in str(e): + str_e = str(e) + if "rate limit exceeded" in str_e or "too many requests for url" in str_e: pytest.xfail("GitHub API rate limit exceeded") + elif ( + "nodename nor servname provided, or not known" in str_e + or "Network is unreachable" in str_e + ): + pytest.xfail("No internet connection") else: raise - return wrapped_method + return wrapper -def wrap_github_rate_limit_check(cls): - """ - Class decorator to wrap all test methods with the - xfail_on_github_rate_limit decorator. - """ - import requests - - try: - requests.get("http://example.com") - except requests.exceptions.ConnectionError: - wrapper = pytest.mark.xfail(reason="No internet connection") - else: - wrapper = xfail_on_github_rate_limit - for attr_name in dir(cls): - if attr_name.startswith("test_"): - orig_method = getattr(cls, attr_name) - setattr(cls, attr_name, wrapper(orig_method)) - return cls - - -@wrap_github_rate_limit_check +def wrap_all_tests(decorator): + """Class decorator factory to wrap all test methods with a given decorator.""" + + def class_decorator(cls): + for attr_name in dir(cls): + if attr_name.startswith("test_"): + orig_method = getattr(cls, attr_name) + setattr(cls, attr_name, decorator(orig_method)) + return cls + + return class_decorator + + +@wrap_all_tests(xfail_on_github_connection_error) class TestUPathGitHubPath(BaseTests): """ Unit-tests for the GitHubPath implementation of UPath.