Browser-based Pyright
This package provides a browser-compatible build of `basedpyright`, an advanced static type checker for Python. As a fork of Microsoft's Pyright, `basedpyright` offers robust type analysis, diagnostic reporting, and language server capabilities. `browser-basedpyright` enables the integration of these features directly into web environments, such as online Python playgrounds, web-based IDEs, and educational tools, without requiring a Node.js backend. It follows a rapid release cadence, frequently updating to incorporate the latest upstream Pyright features and bug fixes, with the current stable version being `1.39.3`. Its primary differentiator is enabling comprehensive Python type checking entirely within the client-side browser context.
Common errors
-
TypeError: createLanguageService is not a function
cause The `browser-basedpyright` package was either not correctly installed, an incorrect import path/syntax was used, or the problematic `v1.39.2` version was installed which contained no exports.fixEnsure `browser-basedpyright` is installed and updated to `v1.39.3` or later. Verify the import statement: `import { createLanguageService } from 'browser-basedpyright';`. -
Pyright: Incompatible types in assignment (expression of type 'str' cannot be assigned to type 'int')
cause This is a Pyright diagnostic indicating a type mismatch in the Python code being analyzed. The language service correctly identified that a string value was provided where an integer was expected.fixReview the Python code for type correctness. For example, change a call like `process_data("hello")` to `process_data(123)` if the parameter expects an integer. -
ReferenceError: SharedArrayBuffer is not defined
cause Web Workers, especially those utilizing shared memory features for performance (common in language servers), require specific Cross-Origin Isolation (COOP/COEP) headers to be served by the web server. Without these, `SharedArrayBuffer` might not be available in the worker context.fixConfigure your web server to send `Cross-Origin-Opener-Policy: same-origin` and `Cross-Origin-Embedder-Policy: require-corp` HTTP response headers for the HTML page hosting the application and potentially for the worker script itself.
Warnings
- breaking The `browser-basedpyright` package was accidentally published as an empty package in `v1.39.2`, rendering it unusable. Users updating to this specific version would encounter runtime errors or missing exports.
- gotcha A new diagnostic rule, `reportEmptyAbstractUsage`, was introduced in `v1.39.0`. This rule will now report errors for Python classes explicitly extending `ABC` (or using `ABCMeta`) without abstract methods if the class itself is then instantiated, which was previously allowed without complaint.
- gotcha A critical bug causing the language server to crash on specific Python code involving abstract setters without parameters was fixed in `v1.38.1`. Users on earlier versions might experience instability or crashes when processing such Python code.
- gotcha Due to the package's rapid release cycle and its nature as a browser build mirroring `basedpyright` (which itself tracks upstream Pyright), API stability might not be strictly guaranteed across minor versions. While efforts are made to maintain compatibility, unexpected behavior or minor API adjustments may occur.
Install
-
npm install browser-basedpyright -
yarn add browser-basedpyright -
pnpm add browser-basedpyright
Imports
- createLanguageService
const { createLanguageService } = require('browser-basedpyright');import { createLanguageService } from 'browser-basedpyright'; - createInMemoryLanguageServiceHost
import createInMemoryLanguageServiceHost from 'browser-basedpyright/host';
import { createInMemoryLanguageServiceHost } from 'browser-basedpyright'; - LanguageService
import { LanguageService } from 'browser-basedpyright';import type { LanguageService } from 'browser-basedpyright';
Quickstart
import { createLanguageService, createInMemoryLanguageServiceHost, type LanguageService } from 'browser-basedpyright';
// --- Setup the host for the language service ---
// This host simulates a file system and provides content for the language service.
const pythonCode = `
class MyClass:
def __init__(self, name: str):
self.name = name
def greet(self) -> str:
return f"Hello, {self.name}!"
def process_data(value: int):
# This should be flagged if 'value' is not an int or if 'value' is a str
if value == "test": # This will cause a pyright warning
print("Test string")
obj = MyClass("World")
print(obj.greet())
process_data(123)
process_data("hello") # Pyright should flag this as type error
`;
const virtualFilePath = '/src/main.py';
const host = createInMemoryLanguageServiceHost({
getOpenFileContents: (path: string) => {
if (path === virtualFilePath) {
return pythonCode;
}
return undefined; // Or throw error for unknown files
},
getWorkspaceFiles: () => [virtualFilePath],
getPythonVersion: () => '3.10',
getPyrightConfig: () => ({
reportMissingImports: "warning",
reportUnknownMemberType: "warning"
}),
});
// --- Initialize the language service ---
const service: LanguageService = createLanguageService(host);
// --- Get diagnostics for the file ---
async function getAndPrintDiagnostics() {
const diagnostics = await service.getDiagnostics(virtualFilePath);
console.log(`Diagnostics for ${virtualFilePath}:`);
if (diagnostics.length === 0) {
console.log("No issues found.");
} else {
diagnostics.forEach(d => {
console.log(` [${d.severity}] ${d.message} at line ${d.range.start.line + 1}, col ${d.range.start.character + 1}`);
});
}
}
getAndPrintDiagnostics();
// Example of updating content and re-checking
setTimeout(async () => {
const updatedCode = `
class AnotherClass:
def say_hi(self):
print("Hi!")
another_obj = AnotherClass()
another_obj.say_hi()
# Fix the previous error
def process_data_fixed(value: int):
if value == 1:
print("One")
process_data_fixed(42)
# process_data_fixed("oops") // This would still be an error if uncommented
`;
host.setOpenFileContents(virtualFilePath, updatedCode);
console.log("\n--- Updated code and re-checking ---");
await getAndPrintDiagnostics();
}, 2000);