sdk: add generic params to StreamService + generate AsyncGenerator type hints in Python (#1527)

This commit is contained in:
Brett Jia
2024-07-12 11:08:28 -04:00
committed by GitHub
parent cf5e010faf
commit 4a4b077132
3 changed files with 30 additions and 8 deletions

View File

@@ -4,7 +4,7 @@ try:
from typing import TypedDict
except:
from typing_extensions import TypedDict
from typing import Union, Any
from typing import Union, Any, AsyncGenerator
from .other import *
@@ -1202,7 +1202,7 @@ class ObjectDetection:
async def detectObjects(self, mediaObject: MediaObject, session: ObjectDetectionSession = None) -> ObjectsDetected:
pass
async def generateObjectDetections(self, videoFrames: MediaObject | VideoFrame, session: ObjectDetectionGeneratorSession) -> ObjectDetectionGeneratorResult:
async def generateObjectDetections(self, videoFrames: MediaObject | AsyncGenerator[VideoFrame, None], session: ObjectDetectionGeneratorSession) -> AsyncGenerator[ObjectDetectionGeneratorResult, None]:
pass
async def getDetectionModel(self, settings: Any = None) -> ObjectDetectionModel:
@@ -1463,7 +1463,7 @@ class StartStop:
class StreamService:
"""Generic bidirectional stream connection."""
async def connectStream(self, input: Any = None, options: Any = None) -> Any:
async def connectStream(self, input: AsyncGenerator[Any, None] = None, options: Any = None) -> AsyncGenerator[Any, None]:
pass
@@ -1543,7 +1543,7 @@ class VideoClips:
class VideoFrameGenerator:
async def generateVideoFrames(self, mediaObject: MediaObject, options: VideoFrameGeneratorOptions = None) -> VideoFrame:
async def generateVideoFrames(self, mediaObject: MediaObject, options: VideoFrameGeneratorOptions = None) -> AsyncGenerator[VideoFrame, None]:
pass

View File

@@ -79,6 +79,11 @@ fs.writeFileSync(path.join(__dirname, '../gen/index.ts'), contents);
const discoveredTypes = new Set<string>();
discoveredTypes.add('EventDetails');
// When computing method signatures, we push the generic parameter types
// into this set. We can then convert them to Any.
// Pop the types off when we're done.
const parameterTypes = new Set<string>();
function toPythonType(type: any): string {
if (type.type === 'array')
return `list[${toPythonType(type.elementType)}]`;
@@ -88,7 +93,11 @@ function toPythonType(type: any): string {
return `tuple[${type.elements.map((et: any) => toPythonType(et)).join(', ')}]`;
if (type.type === 'union')
return type.types.map((type: any) => toPythonType(type)).join(' | ')
if (type.name === 'AsyncGenerator')
return `AsyncGenerator[${toPythonType(type.typeArguments[0])}, None]`;
type = type.typeArguments?.[0]?.name || type.name || type;
if (parameterTypes.has(type))
return 'Any';
switch (type) {
case 'boolean':
return 'bool';
@@ -133,11 +142,24 @@ function toPythonMethodDeclaration(method: any) {
}
function selfSignature(method: any) {
for (const typeParameter of method.signatures[0].typeParameter || []) {
parameterTypes.add(typeParameter.name);
}
const params = (method.signatures[0].parameters || []).map((p: any) => toPythonParameter(p));
parameterTypes.clear();
params.unshift('self');
return params.join(', ');
}
function selfReturnType(method: any) {
for (const typeParameter of method.signatures[0].typeParameter || []) {
parameterTypes.add(typeParameter.name);
}
const retType = toPythonReturnType(method.signatures[0].type);
parameterTypes.clear();
return retType
}
const enums = schema.children?.filter((child: any) => child.kindString === 'Enumeration') ?? [];
const interfaces = schema.children?.filter((child: any) => Object.values(ScryptedInterface).includes(child.name)) ?? [];
let python = '';
@@ -210,7 +232,7 @@ ${toDocstring(td)}
`
}
for (const method of methods) {
python += ` ${toPythonMethodDeclaration(method)} ${method.name}(${selfSignature(method)}) -> ${toPythonReturnType(method.signatures[0].type)}:
python += ` ${toPythonMethodDeclaration(method)} ${method.name}(${selfSignature(method)}) -> ${selfReturnType(method)}:
${toDocstring(method, true)}
`
@@ -229,7 +251,7 @@ for (const td of interfaces) {
let pythonEnums = ''
for (const e of enums) {
if (e.children) {
if (e.children) {
pythonEnums += `
class ${e.name}(str, Enum):
${toDocstring(e)}
@@ -331,7 +353,7 @@ try:
from typing import TypedDict
except:
from typing_extensions import TypedDict
from typing import Union, Any
from typing import Union, Any, AsyncGenerator
from .other import *

View File

@@ -1525,7 +1525,7 @@ export interface VideoFrameGenerator {
* Generic bidirectional stream connection.
*/
export interface StreamService {
connectStream(input?: AsyncGenerator<any, void>, options?: any): Promise<AsyncGenerator<any, void>>;
connectStream<Input, Output=Input>(input?: AsyncGenerator<Input, void>, options?: any): Promise<AsyncGenerator<Output, void>>;
}
/**
* TTY connection offered by a remote device that can be connected to