CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-osfclient

A Python library and command-line interface for interacting with the Open Science Framework

Pending
Overview
Eval results
Files

python-api.mddocs/

Python API

Core Python library functionality for programmatic access to OSF projects. The main entry point is the OSF class, which provides authentication and project access capabilities.

Capabilities

OSF Client Class

Main client class for interacting with the Open Science Framework. Handles authentication and provides access to projects.

class OSF:
    def __init__(self, username=None, password=None, token=None):
        """
        Initialize OSF client with optional authentication.

        Args:
            username (str, optional): OSF username for basic authentication
            password (str, optional): OSF password for basic authentication  
            token (str, optional): Personal Access Token for token authentication

        Note:
            Authentication is attempted during initialization. If it fails,
            can_login property will be False but the client can still be used
            for public projects.
        """

    def login(self, username=None, password=None, token=None):
        """
        Authenticate user for protected API calls.

        Args:
            username (str, optional): OSF username
            password (str, optional): OSF password
            token (str, optional): Personal Access Token

        Raises:
            OSFException: If no login details provided

        Note:
            Token authentication takes precedence over username/password if both provided.
        """

    def project(self, project_id):
        """
        Fetch project by project ID.

        Args:
            project_id (str): OSF project ID (GUID)

        Returns:
            Project: Project instance

        Raises:
            OSFException: If project ID is unrecognized type or not accessible
        """

    def guid(self, guid):
        """
        Determine JSONAPI type for provided GUID.

        Args:
            guid (str): OSF GUID

        Returns:
            str: JSONAPI type ('nodes', 'registrations', etc.)
        """

    @property
    def username(self):
        """
        Get authenticated username.

        Returns:
            str or None: Username if using basic auth, None otherwise
        """

    @property
    def password(self):
        """
        Get authenticated password.

        Returns:
            str or None: Password if using basic auth, None otherwise
        """

    @property
    def token(self):
        """
        Get authentication token.

        Returns:
            str or None: Token if using token auth, None otherwise
        """

    @property
    def can_login(self):
        """
        Check if authentication succeeded.

        Returns:
            bool: True if authentication was successful, False otherwise
        """

Usage Examples

Basic authentication:

from osfclient import OSF

# Token authentication (recommended)
osf = OSF(token='your_personal_access_token')

# Basic authentication
osf = OSF(username='user@example.com', password='password')

# Check if authentication worked
if osf.can_login:
    print(f"Authenticated as: {osf.username or 'token user'}")
else:
    print("Authentication failed, can only access public projects")

Working with projects:

# Get a project
project_id = '9zpcy'
project = osf.project(project_id)
print(f"Project: {project.title}")
print(f"Description: {project.description}")

# Check project type
guid_type = osf.guid(project_id)
print(f"Project type: {guid_type}")  # 'nodes' or 'registrations'

Environment-based authentication:

import os
from osfclient import OSF

# Using environment variables
# Set OSF_TOKEN, OSF_USERNAME, OSF_PASSWORD environment variables
osf = OSF(
    username=os.getenv('OSF_USERNAME'),
    password=os.getenv('OSF_PASSWORD'),
    token=os.getenv('OSF_TOKEN')
)

Session Management

The OSF class uses OSFSession internally for HTTP operations with built-in rate limiting and authentication handling. OSFSession extends requests.Session with OSF-specific configuration.

class OSFSession:
    def __init__(self):
        """
        Handle HTTP session related work with OSF-specific configuration.
        
        Automatically configures OSF API headers and base URL.
        Inherits from requests.Session for full HTTP functionality.
        """

    def basic_auth(self, username, password):
        """
        Configure basic authentication.

        Args:
            username (str): OSF username
            password (str): OSF password
            
        Note:
            Removes any existing Authorization header and stores credentials
            for HTTP basic authentication. Mutually exclusive with token auth.
        """

    def token_auth(self, token):
        """
        Configure token authentication.

        Args:
            token (str): Personal Access Token
            
        Note:
            Sets Authorization: Bearer header and stores token.
            Takes precedence over basic authentication.
        """

    def get(self, url, *args, **kwargs):
        """
        Rate-limited GET request with automatic 401 error handling.
        
        Args:
            url (str): Request URL
            *args, **kwargs: Passed to requests.Session.get()
            
        Returns:
            requests.Response: HTTP response object
            
        Raises:
            UnauthorizedException: If response status is 401
            
        Note:
            Rate limited to 1 request per second.
        """

    def put(self, url, *args, **kwargs):
        """
        Rate-limited PUT request with automatic 401 error handling.
        
        Args:
            url (str): Request URL
            *args, **kwargs: Passed to requests.Session.put()
            
        Returns:
            requests.Response: HTTP response object
            
        Raises:
            UnauthorizedException: If response status is 401
            
        Note:
            Rate limited to 1 request per second.
        """

    def patch(self, url, *args, **kwargs):
        """
        PATCH request with automatic 401 error handling.
        
        Args:
            url (str): Request URL
            *args, **kwargs: Passed to requests.Session.patch()
            
        Returns:
            requests.Response: HTTP response object
            
        Raises:
            UnauthorizedException: If response status is 401
        """

    def delete(self, url, *args, **kwargs):
        """
        DELETE request with automatic 401 error handling.
        
        Args:
            url (str): Request URL
            *args, **kwargs: Passed to requests.Session.delete()
            
        Returns:
            requests.Response: HTTP response object
            
        Raises:
            UnauthorizedException: If response status is 401
        """

    def build_url(self, *args):
        """
        Build OSF API URLs with canonical trailing slash.

        Args:
            *args: URL path components

        Returns:
            str: Complete OSF API URL ending with '/'
            
        Example:
            build_url('nodes', 'abc123', 'files') 
            # Returns: 'https://api.osf.io/v2/nodes/abc123/files/'
        """

    @property
    def base_url(self):
        """
        OSF API base URL.

        Returns:
            str: 'https://api.osf.io/v2/'
        """

    @property
    def auth(self):
        """
        Basic authentication credentials.

        Returns:
            tuple or None: (username, password) if basic auth configured, None otherwise
        """

    @property
    def token(self):
        """
        Authentication token.

        Returns:
            str or None: Personal Access Token if token auth configured, None otherwise
        """

    @property
    def last_request(self):
        """
        Timestamp of last HTTP request for rate limiting.

        Returns:
            float or None: Unix timestamp of last request, None if no requests made
        """

    @property
    def headers(self):
        """
        Default HTTP headers for OSF API requests.

        Returns:
            dict: Headers including Accept, Content-Type, User-Agent, and Authorization
            
        Note:
            Automatically configured with OSF-specific headers:
            - Accept: application/vnd.api+json
            - Accept-Charset: utf-8
            - Content-Type: application/json
            - User-Agent: osfclient v{version}
            - Authorization: Bearer {token} (if token auth configured)
        """

Advanced session usage:

from osfclient.models import OSFSession
from osfclient.exceptions import UnauthorizedException

# Custom session configuration
session = OSFSession()
session.token_auth('your_token')

# Build custom URLs
url = session.build_url('nodes', 'project_id', 'files')
# Returns: 'https://api.osf.io/v2/nodes/project_id/files/'

# Direct HTTP operations with rate limiting and error handling
try:
    response = session.get(url)
    data = response.json()
    print(f"Found {len(data['data'])} files")
except UnauthorizedException:
    print("Authentication required or token expired")

# Check session state
print(f"Using token auth: {session.token is not None}")
print(f"Using basic auth: {session.auth is not None}")
print(f"Base URL: {session.base_url}")

# Access default headers
headers = session.headers
print(f"User-Agent: {headers.get('User-Agent')}")
print(f"Accept: {headers.get('Accept')}")

Rate Limiting and Error Handling

OSFSession implements automatic rate limiting (1 request per second) and consistent error handling:

import time
from osfclient.models import OSFSession

session = OSFSession()
session.token_auth('your_token')

# Rate limiting example
start_time = time.time()
response1 = session.get('https://api.osf.io/v2/nodes/project_id/')
response2 = session.get('https://api.osf.io/v2/nodes/project_id/files/')
elapsed = time.time() - start_time

# Second request automatically delayed to respect rate limit
print(f"Two requests took {elapsed:.2f} seconds (min 1.0s due to rate limiting)")

# Automatic 401 error handling
try:
    session.basic_auth('invalid', 'credentials')
    response = session.get('https://api.osf.io/v2/nodes/private_project/')
except UnauthorizedException as e:
    print(f"Authentication failed: {e}")
    # Session automatically handles 401 responses

Install with Tessl CLI

npx tessl i tessl/pypi-osfclient

docs

cli-interface.md

index.md

project-management.md

python-api.md

utilities.md

tile.json