8000 test PR to see figure out why the CI is timeout-ing by deronnax · Pull Request #1903 · django-extensions/django-extensions · GitHub
[go: up one dir, main page]

Skip to content

test PR to see figure out why the CI is timeout-ing #1903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

deronnax
Copy link

No description provided.

@deronnax deronnax force-pushed the investigate-timeout-ci-tests branch from a683aae to 51daa17 Compare December 31, 2024 14:34
@browniebroke
Copy link
Contributor

Seems to be hanging in tests/management/commands/test_pipchecker.py::PipCheckerTests::test_pipchecker_with_outdated_requirement?

@deronnax
Copy link
Author
deronnax commented Jan 2, 2025

yes, I figured it out locally. Needs to investigate why, now.

@deronnax
Copy link
Author
deronnax commented Jan 2, 2025

Partially found: TLDR:

  1. error response from PyPI: xmlrpc.client.Fault: <Fault -32500: 'RuntimeError: PyPI no longer supports the XMLRPC package_releases method. Use JSON or Simple API instead.
  2. poorly implemented seemingly-infinite retry:
                available = None
                while retry:
                    try:
                        available = pypi.package_releases(req["pip_req"].name, True) or pypi.package_releases(req["pip_req"].name.replace('-', '_'), True)
                        retry = False
                        sleep(1)  # crude way slow down to avoid HTTPTooManyRequests
                    except Fault as err:
                        self.stdout.write(err.faultString)
                        self.stdout.write("Retrying in 60 seconds!")
>                       sleep(60)
E                       Failed: Timeout >10.0s
  1. bonus: error output of these two seems to be masquered/swallown by the coverage.

full stack trace:

tests/management/commands/test_pipchecker.py::PipCheckerTests::test_pipchecker_with_outdated_requirement FAILED                                                                                                                                                          [100%]

=================================================================================================================================== FAILURES ===================================================================================================================================
__________________________________________________________________________________________________________ PipCheckerTests.test_pipchecker_with_outdated_requirement ___________________________________________________________________________________________________________

self = <django_extensions.management.commands.pipchecker.Command object at 0x103d68650>

    def check_pypi(self):
        """If the requirement is frozen to pypi, check for a new version."""
        for dist in get_installed_distributions():
            name = dist.project_name
            if name in self.reqs.keys():
                self.reqs[name]["dist"] = dist

        pypi = ServerProxy("https://pypi.python.org/pypi")
        for name, req in list(self.reqs.items()):
            if req["url"]:
                continue  # skipping github packages.
            elif "dist" in req:
                dist = req["dist"]
                dist_version = LooseVersion(dist.version)
                retry = True
                available = None
                while retry:
                    try:
>                       available = pypi.package_releases(req["pip_req"].name, True) or pypi.package_releases(req["pip_req"].name.replace('-', '_'), True)

django_extensions/management/commands/pipchecker.py:177:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../.pyenv/versions/3.11.10/lib/python3.11/xmlrpc/client.py:1122: in __call__
    return self.__send(self.__name, args)
../../.pyenv/versions/3.11.10/lib/python3.11/xmlrpc/client.py:1464: in __request
    response = self.__transport.request(
../../.pyenv/versions/3.11.10/lib/python3.11/xmlrpc/client.py:1166: in request
    return self.single_request(host, handler, request_body, verbose)
../../.pyenv/versions/3.11.10/lib/python3.11/xmlrpc/client.py:1182: in single_request
    return self.parse_response(resp)
../../.pyenv/versions/3.11.10/lib/python3.11/xmlrpc/client.py:1354: in parse_response
    return u.close()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <xmlrpc.client.Unmarshaller object at 0x103d8ae10>

    def close(self):
        # return response tuple and target method
        if self._type is None or self._marks:
            raise ResponseError()
        if self._type == "fault":
>           raise Fault(**self._stack[0])
E           xmlrpc.client.Fault: <Fault -32500: 'RuntimeError: PyPI no longer supports the XMLRPC package_releases method. Use JSON or Simple API instead. See https://warehouse.pypa.io/api-reference/xml-rpc.html#deprecated-methods for more information.'>

../../.pyenv/versions/3.11.10/lib/python3.11/xmlrpc/client.py:668: Fault

During handling of the above exception, another exception occurred:

self = <tests.management.commands.test_pipchecker.PipCheckerTests testMethod=test_pipchecker_with_outdated_requirement>

    def test_pipchecker_with_outdated_requirement(self):
        requirements_path = './requirements.txt'
        out = StringIO()

        f = open(requirements_path, 'wt')
        f.write('djangorestframework==3.0.0')
        f.close()

        subprocess.call([sys.executable, '-m', 'pip', 'install', '-r', requirements_path])
        # pip._vendor.pkg_resources = importlib.reload(pip._vendor.pkg_resources)
>       call_command('pipchecker', '-r', requirements_path, stdout=out)

tests/management/commands/test_pipchecker.py:49:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.tox/py311-dj42/lib/python3.11/site-packages/django/core/management/__init__.py:194: in call_command
    return command.execute(*args, **defaults)
.tox/py311-dj42/lib/python3.11/site-packages/django/core/management/base.py:458: in execute
    output = self.handle(*args, **options)
django_extensions/management/utils.py:62: in inner
    ret = func(self, *args, **kwargs)
django_extensions/management/commands/pipchecker.py:136: in handle
    self.check_pypi()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <django_extensions.management.commands.pipchecker.Command object at 0x103d68650>

    def check_pypi(self):
        """If the requirement is frozen to pypi, check for a new version."""
        for dist in get_installed_distributions():
            name = dist.project_name
            if name in self.reqs.keys():
                self.reqs[name]["dist"] = dist

        pypi = ServerProxy("https://pypi.python.org/pypi")
        for name, req in list(self.reqs.items()):
            if req["url"]:
                continue  # skipping github packages.
            elif "dist" in req:
                dist = req["dist"]
                dist_version = LooseVersion(dist.version)
                retry = True
                available = None
                while retry:
                    try:
                        available = pypi.package_releases(req["pip_req"].name, True) or pypi.package_releases(req["pip_req"].name.replace('-', '_'), True)
                        retry = False
                        sleep(1)  # crude way slow down to avoid HTTPTooManyRequests
                    except Fault as err:
                        self.stdout.write(err.faultString)
                        self.stdout.write("Retrying in 60 seconds!")
>                       sleep(60)
E                       Failed: Timeout >10.0s

django_extensions/management/commands/pipchecker.py:183: Failed
---------------------------------------------------------------------------------------------------------------------------- Captured stderr setup -----------------------------------------------------------------------------------------------------------------------------
Creating test database for alias 'default' ('file:memorydb_default?mode=memory&cache=shared')...
----------------------------------------------------------------------------------------------------------------------------- Captured stdout call -----------------------------------------------------------------------------------------------------------------------------
Requirement already satisfied: djangorestframework==3.0.0 in ./.tox/py311-dj42/lib/python3.11/site-packages (from -r ./requirements.txt (line 1)) (3.0.0)
--------------------------------------------------------------------------------------------------------------------------- Captured stderr teardown ---------------------------------------------------------------------------------------------------------------------------
Destroying test database for alias 'default' ('file:memorydb_default?mode=memory&cache=shared')...

@browniebroke
Copy link
Contributor

Nice find! Really good shout on pytest-timeout, I didn't know about it, very useful for debugging this problem 👍🏻

Taking a step back, I would challenge the mere presence of pipchecker command in django-extensions:

  • It doesn't sound very Django specific
  • It was added in 2013, and with the rise of modern package managers (Poetry, PDM, uv, ...) it's IMO becoming less useful.
  • There are a few opened issues mentioning it, and some seem to indicate issues with recent pip versions
  • By looking at the tests, it seems like a tricky one to maintain

Maybe I'll raise these separately but it sounds like we could:

  • Review whether pipchecker is still worth keeping around, and remove it if not. Could be turned into a standalone CLI.
  • pytest-timeout was useful here and might be a good one to keep around in this project, might help prevent a similar issue in the future

Disclaimer: I'm not a maintainer, only a user trying to help

@trbs
Copy link
Member
trbs commented Jan 2, 2025

Thanks everybody

@browniebroke I agree with your assessment, seams a command like pipchecker is less useful today.
And if it is still useful it could be perfectly served as a standalone package.

If I remember correctly some people where using this in automation for projects (not sure if that's still the case and if people might have moved on) so I would suggest the following.

Let's add a deprecation warning to the pipchecker command noting that it will be removed in a future version.
Then we can allow the tests to fail (or even disable the tests).

Then in a release or two, we cleanup the pipchecker command completely.

@deronnax
Copy link
Author
deronnax commented Jan 2, 2025

Since the pipchecker commands have already stopped working, seemingly as of September 26th this year (about three months ago), why not simply remove them in the next release? Unless, of course, they are still useful for some self-hosted PyPI/Warehouse users?

@trbs
Copy link
Member
trbs commented Jan 6, 2025

Since the pipchecker commands have already stopped working, seemingly as of September 26th this year (about three months ago), why not simply remove them in the next release? Unless, of course, they are still useful for some self-hosted PyPI/Warehouse users?

Even there are... (I know of none)

If it's truly broken, I see no reason to keep it around.
If it has some (even limited) functionality left, I normally prefer to give users that might be using that part of it some warning.

Would anybody be willing to create a PR to remove pipchecker ?

@browniebroke
Copy link
Contributor

Yes, it looks quite broken, from what I can see it doesn't do anything apart from trying to call a deprecated PyPI endpoint in a loop, sleeping 60 seconds between retries.

@browniebroke
Copy link
Contributor

#1906

@browniebroke
Copy link
Contributor

@deronnax thanks for your help tracking this down. The timeouts should be resolved on the main branch now that #1906 is merged, so we can probably close this.

@deronnax
Copy link
Author

Absolutely. Congrats and thanks to you.

@deronnax deronnax closed this Jan 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0