{"id":8268,"library":"lazr-restfulclient","title":"lazr-restfulclient","description":"lazr.restfulclient is a programmable client library that leverages commonalities among lazr.restful web services to provide extended functionality built upon wadllib. It is actively maintained, with the current version 0.14.6 released in January 2024, including updates for Python 3.12 compatibility.","status":"active","version":"0.14.6","language":"en","source_language":"en","source_url":"https://github.com/lazr/lazr.restfulclient","tags":["REST","client","API","Launchpad","wadl","HTTP","web services"],"install":[{"cmd":"pip install lazr-restfulclient","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Linux OS platform information API.","package":"python3-distro","optional":false},{"reason":"Comprehensive HTTP client library (version >= 0.7.7 required).","package":"python3-httplib2","optional":false},{"reason":"Library for parsing, manipulating, and generating URIs.","package":"python3-lazr.uri","optional":false},{"reason":"Generic, spec-compliant implementation of OAuth.","package":"python3-oauthlib","optional":false},{"reason":"Package Discovery and Resource Access (from setuptools).","package":"python3-pkg-resources","optional":false},{"reason":"Library for navigating WADL files (version >= 1.1.4 required).","package":"python3-wadllib","optional":false}],"imports":[{"note":"The primary class for instantiating a client to a RESTful service.","symbol":"ServiceRoot","correct":"from lazr.restfulclient.client import ServiceRoot"},{"note":"For package-level access, e.g., checking __version__.","symbol":"lazr.restfulclient","correct":"import lazr.restfulclient"}],"quickstart":{"code":"import os\nfrom lazr.restfulclient.client import ServiceRoot\nfrom lazr.restfulclient.errors import HTTPError\n\n# Example: Connect to a mock service root (replace with your actual service URL)\n# For Launchpad services, the root URL would be like 'https://api.launchpad.net/1.0/'\nSERVICE_ROOT_URL = os.environ.get('LAZR_SERVICE_URL', 'https://api.example.com/')\n\ntry:\n    # Initialize a ServiceRoot. The first argument is typically an authorizer, or None for unauthenticated access.\n    service = ServiceRoot(None, SERVICE_ROOT_URL)\n\n    # Attempt to access a top-level collection, e.g., 'users'\n    # This will trigger an HTTP GET request to SERVICE_ROOT_URL/users\n    # Note: Replace 'users' with an actual collection name for your service\n    users_collection = service.users\n    print(f\"Successfully accessed collection: {users_collection.lp_self_link}\")\n\n    # Example: Fetch a specific item from the collection (if it supports key-based lookup)\n    # Assuming 'users_collection' can be indexed by ID, e.g., user with ID '123'\n    # This will perform another HTTP GET request\n    # user = users_collection[123]\n    # print(f\"Fetched user: {user.display_name}\")\n\nexcept HTTPError as e:\n    print(f\"HTTP Error encountered: {e.status} - {e.reason}\\n{e.response}\")\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")","lang":"python","description":"Demonstrates how to initialize a `ServiceRoot` client and access a top-level collection. This example uses a placeholder URL and assumes a basic RESTful service structure."},"warnings":[{"fix":"Update to use the `lazr.authentication` library or the updated `lazr.restfulclient` authentication mechanisms if relying on the WSGI authentication middleware.","message":"The WSGI authentication middleware was moved from `lazr.restful` to `lazr.authentication` in `lazr.restfulclient` version 0.9.9. Direct usage of the old authentication middleware will break.","severity":"breaking","affected_versions":"<0.9.9"},{"fix":"Be aware that the object's available attributes and methods might change after a network fetch (`lp_refresh()` or first attribute access) based on the server's response. Inspect `lp_attributes` or `resource_type_link` after fetching to understand the object's current state.","message":"Client-side objects can 're-type' after fetching data. If a collection is initially configured to contain a generic resource type, but the server returns a more specific type upon fetching, the client-side object will adopt the properties of the actual, more specific type. This can be confusing if not expected.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Handle client-side HTTP errors (4xx) explicitly in your code, as `lazr.restfulclient` will not attempt to retry them. Use the `max_retries` constructor argument for `ServiceRoot` to adjust retry behavior for server errors if needed.","message":"The library automatically retries requests on transient server errors (HTTP 502, 503) a configurable number of times. However, it will NOT retry on client-side errors (e.g., HTTP 400 Bad Request or 404 Not Found), escalating them directly as exceptions.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Check `lazr.restfulclient`'s release notes for specific `httplib2` version requirements. As of 0.14.2, it requires `httplib2 >= 0.7.7` for Python 3. If issues persist, try upgrading or downgrading `httplib2` to a version explicitly known to work with your `lazr.restfulclient` version.","message":"Incompatibilities with `httplib2` versions have occurred. If you encounter unexpected HTTP connection issues or errors related to `httplib2`, ensure your `httplib2` version is compatible with `lazr.restfulclient`.","severity":"gotcha","affected_versions":"Various, particularly around `httplib2` 0.9 and 0.12.0"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure you have correctly configured your authentication (e.g., OAuth credentials, HTTP Basic Auth) for the `ServiceRoot`. If interacting with Launchpad, verify your project name and ownership, and configure 'quickly' with your Launchpad project name.","cause":"Attempting to perform an action on a service (e.g., Launchpad) without sufficient authentication or authorization, or trying to access a project you do not own/have permissions for.","error":"lazr.restfulclient.errors.Unauthorized: HTTP Error 401: Unauthorized"},{"fix":"Double-check the service root URL and the paths to collections and entries. Verify the resource ID or key if you are trying to fetch a specific item.","cause":"The requested resource (collection or entry) does not exist at the specified URL on the server.","error":"HTTP Error 404: Not Found"},{"fix":"Before saving, refresh the object using `obj.lp_refresh()` to get the latest server-side state. Then, re-apply your changes and attempt to save again. Implement optimistic locking logic if concurrent modifications are common.","cause":"Attempting to save changes to a resource that has been modified by another client since it was last fetched (e.g., a concurrent modification).","error":"ConflictError: HTTP Error 409: Conflict"}]}