🔍 Code Extractor

function get_client

Maturity: 29

Asynchronous singleton factory function that retrieves or initializes a global Client instance with optional device registration prompting.

File:
/tf/active/vicechatdev/rmcl/api.py
Lines:
383 - 390
Complexity:
moderate

Purpose

This function implements a thread-safe singleton pattern for managing a global Client instance. It ensures only one Client object exists throughout the application lifecycle, initializing it on first access and optionally prompting for device registration. The function uses an async lock to prevent race conditions in concurrent environments and is decorated with @add_sync to provide both synchronous and asynchronous interfaces.

Source Code

async def get_client(allow_prompt=True):
    global _client
    async with _client_lock:
        if _client is None:
            _client = Client()
            if allow_prompt:
                await _client.prompt_register_device()
    return _client

Parameters

Name Type Default Kind
allow_prompt - True positional_or_keyword

Parameter Details

allow_prompt: Boolean flag (default: True) that controls whether the client should prompt the user for device registration during initialization. Set to False to skip the interactive registration prompt, useful for automated scripts or when device is already registered.

Return Value

Returns a Client instance (singleton). On first call, creates and initializes a new Client object, optionally prompting for device registration. Subsequent calls return the same cached Client instance. The Client object appears to handle authentication and API interactions based on the imported modules (AuthError, DEVICE_TOKEN_URL, etc.).

Dependencies

  • asks
  • trio
  • logging
  • enum
  • io
  • json
  • sys
  • textwrap
  • uuid

Required Imports

from __future__ import annotations
import trio
from sync import add_sync

Conditional/Optional Imports

These imports are only needed under specific conditions:

from config import Config

Condition: Required if Client class uses Config for initialization or configuration settings

Required (conditional)
from exceptions import AuthError

Condition: Required if Client operations may raise authentication errors

Required (conditional)
from exceptions import DocumentNotFound

Condition: Required if Client operations may raise document not found errors

Required (conditional)
from exceptions import ApiError

Condition: Required if Client operations may raise general API errors

Required (conditional)

Usage Example

import trio
from sync import add_sync

# Global variables (typically at module level)
_client = None
_client_lock = trio.Lock()

# Async usage
async def main():
    # Get client with device registration prompt
    client = await get_client()
    
    # Get client without prompting (e.g., for automated scripts)
    client = await get_client(allow_prompt=False)
    
    # Use the client for API operations
    # await client.some_method()

# Synchronous usage (via add_sync decorator)
def sync_main():
    # The decorator provides a sync version
    client = get_client(allow_prompt=False)
    # Use client synchronously

if __name__ == '__main__':
    trio.run(main)

Best Practices

  • Always use within an async context (trio.run or similar) unless using the sync version provided by @add_sync decorator
  • Set allow_prompt=False in automated scripts or non-interactive environments to prevent blocking on user input
  • The function maintains a global singleton, so the first call determines whether device registration prompting occurs
  • Ensure _client and _client_lock are properly initialized at module level before calling this function
  • The async lock prevents race conditions, but be aware that multiple concurrent calls will wait for the lock sequentially
  • Consider error handling for AuthError and ApiError exceptions that may be raised during Client initialization or device registration
  • The Client instance is cached globally, so configuration changes after first initialization won't take effect without resetting _client to None

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function register_device 67.5% similar

    Asynchronously registers a device using a provided registration code by delegating to the client's register_device method.

    From: /tf/active/vicechatdev/rmcl/api.py
  • function get_filecloud_client 65.0% similar

    Singleton factory function that returns a globally cached FileCloud API client instance, handling initialization, authentication, and re-authentication as needed.

    From: /tf/active/vicechatdev/CDocs/controllers/filecloud_controller.py
  • function get_driver 55.0% similar

    Singleton function that initializes and returns a Neo4j database driver instance with connection verification.

    From: /tf/active/vicechatdev/CDocs/db/__init__.py
  • function _get_conn 54.6% similar

    Lazy initialization function that returns a singleton SQLite database connection, creating the database and required table schema if they don't exist.

    From: /tf/active/vicechatdev/rmcl/datacache.py
  • class Client 51.6% similar

    API Client for the Remarkable Cloud that handles authentication, communication, and document management with the Remarkable Cloud service.

    From: /tf/active/vicechatdev/rmcl/api.py
← Back to Browse