Skip to content

googleapiclient modules use urllib.parse but only import urllib, crashing when urllib.parse was not imported elsewhere #2803

Description

@skippdot

Environment details

  • OS type and version: macOS 15 (also reproduced on Linux)
  • Python version: 3.14.6 (affects all supported versions, 3.7+ semantics are identical)
  • pip version: 25.x
  • google-api-python-client version: main at 65bbea2 (release 2.200.0)

Steps to reproduce

Run this two-line program (no other imports):

import googleapiclient._helpers as h
h._add_query_parameter("http://example.com", "a", "b")

Result:

  File ".../googleapiclient/_helpers.py", line 183, in _update_query_params
    parts = urllib.parse.urlparse(uri)
            ^^^^^^^^^^^^
AttributeError: module 'urllib' has no attribute 'parse'

Root cause

Four modules import the bare urllib package but call urllib.parse.* functions:

module urllib.parse call sites
googleapiclient/_helpers.py 4
googleapiclient/discovery.py 6
googleapiclient/http.py 6
googleapiclient/model.py 1

In Python, import urllib does not import its submodules; urllib.parse only becomes accessible as an attribute of the package after some module somewhere executes import urllib.parse (or from urllib.parse import ...). The library currently works only because httplib2, imported transitively by discovery.py/http.py/model.py, happens to register urllib.parse first. _helpers.py imports nothing but the standard library, so using it before anything has imported urllib.parse crashes as above.

Visible symptom in this repository's own test suite

pytest tests/test__helpers.py
# 7 failed, 3 passed — every failure is AttributeError: module 'urllib' has no attribute 'parse'

The same tests pass in a full-suite run because other test modules import urllib.parse first — the same accidental-transitive-import mechanism.

Proposed fix

Replace import urllib with import urllib.parse in the four modules listed above. Call sites keep their current urllib.parse.urlparse(...) spelling, so the change is one line per module. This removes the undeclared dependency on third-party import side effects for all four modules, not just the one that currently crashes.

I can send a PR with the fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions