CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-jupyterlab-code-formatter

A JupyterLab extension to facilitate invocation of code formatters for multiple programming languages.

Pending
Overview
Eval results
Files

http-api-handlers.mddocs/

HTTP API Handlers

Server-side HTTP request handlers for formatter discovery and code formatting operations with authentication, error handling, and caching support.

Capabilities

Formatters API Handler

Handles requests for discovering available code formatters.

class FormattersAPIHandler(APIHandler):
    @tornado.web.authenticated
    def get(self) -> None:
        """Show what formatters are installed and available."""
        pass

Endpoint: GET /jupyterlab_code_formatter/formatters[?cached]

Query Parameters:

  • cached (optional) - Use cached formatter availability checks

Response Format:

{
  "formatters": {
    "formatter_name": {
      "enabled": boolean,
      "label": "Human-readable name"
    }
  }
}

Format API Handler

Handles code formatting requests.

class FormatAPIHandler(APIHandler):
    @tornado.web.authenticated
    def post(self) -> None:
        """Format code using specified formatter."""
        pass

Endpoint: POST /jupyterlab_code_formatter/format[?cached]

Request Body:

{
  "code": ["string array of code"],
  "formatter": "formatter_name",
  "notebook": boolean,
  "options": {
    "formatter_specific_options": "values"
  }
}

Response Format:

{
  "code": [
    {
      "code": "formatted_code_string"
    }
  ]
}

Error Response:

{
  "code": [
    {
      "error": "error_message"
    }
  ]
}

Handler Setup Function

Registers API handlers with the Jupyter server.

def setup_handlers(web_app) -> None:
    """Register API handlers with Jupyter server."""
    pass

Parameters:

  • web_app - Tornado web application instance

Usage Examples

Handler Registration

from jupyterlab_code_formatter.handlers import setup_handlers

def _load_jupyter_server_extension(server_app):
    """Register the API handlers to receive HTTP requests."""
    setup_handlers(server_app.web_app)
    server_app.log.info("Registered jupyterlab_code_formatter server extension")

Request Processing Flow

Formatters Discovery Request

# Client request: GET /jupyterlab_code_formatter/formatters
# Handler processes request:

def get(self) -> None:
    use_cache = self.get_query_argument("cached", default=None)
    
    response_data = {
        "formatters": {
            name: {
                "enabled": formatter.cached_importable if use_cache else formatter.importable,
                "label": formatter.label,
            }
            for name, formatter in SERVER_FORMATTERS.items()
        }
    }
    
    self.finish(json.dumps(response_data))

Code Formatting Request

# Client request: POST /jupyterlab_code_formatter/format
# Handler processes request:

def post(self) -> None:
    data = json.loads(self.request.body.decode("utf-8"))
    formatter_instance = SERVER_FORMATTERS.get(data["formatter"])
    use_cache = self.get_query_argument("cached", default=None)
    
    if formatter_instance is None or not (
        formatter_instance.cached_importable if use_cache else formatter_instance.importable
    ):
        self.set_status(404, f"Formatter {data['formatter']} not found!")
        self.finish()
        return
    
    notebook = data["notebook"]
    options = data.get("options", {})
    formatted_code = []
    
    for code in data["code"]:
        try:
            result = formatter_instance.format_code(code, notebook, **options)
            formatted_code.append({"code": result})
        except Exception as e:
            formatted_code.append({"error": str(e)})
    
    self.finish(json.dumps({"code": formatted_code}))

API Endpoints

Get Available Formatters

URL: /jupyterlab_code_formatter/formatters
Method: GET
Authentication: Required (Jupyter token)

Query Parameters:

  • cached (optional) - Enable cached availability checks

Success Response (200):

{
  "formatters": {
    "black": {
      "enabled": true,
      "label": "Apply Black Formatter"
    },
    "isort": {
      "enabled": true,
      "label": "Apply Isort Formatter"
    },
    "yapf": {
      "enabled": false,
      "label": "Apply YAPF Formatter"
    }
  }
}

Example Requests:

# Get current formatter availability
curl -H "Authorization: token YOUR_TOKEN" \
     http://localhost:8888/jupyterlab_code_formatter/formatters

# Get cached formatter availability  
curl -H "Authorization: token YOUR_TOKEN" \
     http://localhost:8888/jupyterlab_code_formatter/formatters?cached

Format Code

URL: /jupyterlab_code_formatter/format
Method: POST
Authentication: Required (Jupyter token)
Content-Type: application/json

Query Parameters:

  • cached (optional) - Use cached formatter availability

Request Body:

{
  "code": [
    "def hello():\n  pass",
    "import os\nimport sys"
  ],
  "formatter": "black",
  "notebook": true,
  "options": {
    "line_length": 88,
    "string_normalization": true
  }
}

Success Response (200):

{
  "code": [
    {
      "code": "def hello():\n    pass\n"
    },
    {
      "code": "import os\nimport sys\n"
    }
  ]
}

Error Response (200 with errors):

{
  "code": [
    {
      "error": "cannot use --safe with this Python version"
    }
  ]
}

Formatter Not Found (404):

Formatter unknown_formatter not found!

Example Request:

curl -X POST \
     -H "Authorization: token YOUR_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "code": ["def hello():\n  pass"],
       "formatter": "black",
       "notebook": true,
       "options": {"line_length": 88}
     }' \
     http://localhost:8888/jupyterlab_code_formatter/format

Authentication and Security

Jupyter Authentication

Both handlers use Tornado's @tornado.web.authenticated decorator:

  • Token-based: Uses Jupyter server's authentication system
  • Automatic: Authentication handled by base APIHandler class
  • Secure: Prevents unauthorized access to formatting capabilities

Input Validation

Request processing includes validation:

  • JSON Parsing: Validates request body is valid JSON
  • Required Fields: Checks for required fields in request data
  • Formatter Existence: Validates requested formatter exists
  • Sanitization: Processes user input safely

Error Handling

Comprehensive error handling:

  • HTTP Status Codes: Appropriate status codes for different error types
  • Error Messages: Clear error descriptions in responses
  • Exception Handling: Graceful handling of formatter exceptions
  • Logging: Error logging for debugging and monitoring

Handler Configuration

URL Pattern Registration

def setup_handlers(web_app):
    host_pattern = ".*$"
    base_url = web_app.settings["base_url"]
    
    # Register formatters endpoint
    web_app.add_handlers(
        host_pattern,
        [
            (
                url_path_join(base_url, "jupyterlab_code_formatter/formatters"),
                FormattersAPIHandler,
            )
        ],
    )
    
    # Register format endpoint
    web_app.add_handlers(
        host_pattern,
        [
            (
                url_path_join(base_url, "/jupyterlab_code_formatter/format"),
                FormatAPIHandler,
            )
        ],
    )

Base URL Handling

Handlers respect JupyterLab's base URL configuration:

  • Dynamic Base URL: Uses web_app.settings["base_url"]
  • URL Construction: Uses url_path_join() for proper URL construction
  • Flexible Deployment: Works with different JupyterLab deployment configurations

Performance Considerations

Caching Support

Both handlers support caching for improved performance:

  • Query Parameter: ?cached enables cached checks
  • Formatter Availability: Caches importable property checks
  • Persistent Cache: Cache persists for server session duration
  • Selective Caching: Can enable caching per request

Asynchronous Processing

Handlers are designed for async operation:

  • Non-blocking: Formatters run without blocking server
  • Concurrent Requests: Multiple formatting requests can be processed
  • Resource Management: Proper cleanup of formatter processes

Error Recovery

Robust error handling ensures server stability:

  • Isolated Errors: Formatter errors don't crash server
  • Partial Success: Individual code blocks can fail independently
  • Graceful Degradation: Server continues operating with failed formatters

Install with Tessl CLI

npx tessl i tessl/pypi-jupyterlab-code-formatter

docs

code-formatters.md

configuration-system.md

file-editor-formatting.md

frontend-integration.md

http-api-client.md

http-api-handlers.md

index.md

notebook-formatting.md

tile.json