Skip to content

Commit aaba461

Browse files
committed
Make it possible to wrap API calls
And show how it can be used to make them synchronous, for use in interactive shells. Closes #5.
1 parent 665316a commit aaba461

2 files changed

Lines changed: 48 additions & 14 deletions

File tree

example/sync-example.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import asyncio
2+
import openspace
3+
4+
# This is an example of how to make synchronous calls to the API
5+
# This is not so useful in scripts but has its use in interactive shells, instead of prepending
6+
# every call with `await`.
7+
8+
ADDRESS = 'localhost'
9+
PORT = 4681
10+
# Create an OpenSpaceApi instance with the OpenSpace address and port
11+
api = openspace.Api(ADDRESS, PORT)
12+
13+
# You might want to handle this differently according to your environment or use-case.
14+
# For instance, this works in a regular python shell or in IPython but `python3 -m asyncio` is
15+
# different.
16+
loop = asyncio.new_event_loop()
17+
def sync_wrapper(f, *args, **kwargs):
18+
return loop.run_until_complete(f(*args, **kwargs))
19+
20+
# warning: all async calls must be performed on the same loop
21+
22+
loop.run_until_complete(api.connect())
23+
sync_os = loop.run_until_complete(api.singleReturnLibrary(sync_wrapper))
24+
25+
# Calls to methods of `sync_os` will block until the call is made and a result is returned:
26+
sync_os.printInfo("foo")
27+
print(sync_os.propertyValue("Scene.Earth.Scale.Scale"))
28+
29+
api.disconnect()

src/openspace/src/api.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from traceback import print_exc
44
from .topic import Topic
55
from .socketwrapper import SocketWrapper
6+
from functools import partial
67
from typing import Callable, NamedTuple
78
from collections import namedtuple
89

@@ -337,20 +338,19 @@ async def executeLuaFunction(self, function: str, args, getReturnValue = True):
337338
else:
338339
topic.cancel()
339340

340-
async def library(self) -> dict:
341+
async def library(self, wrapper: None|Callable = None) -> dict:
341342
""" Get an object representing the OpenSpace lua libarary. \n
343+
:param wrapper: if set, wraps all API calls (may be used to make them synchronous)
342344
:return - The lua library, mapped to async python functions. """
343345

344-
def generateAsyncSingleRetFunction(functionName):
345-
async def fun(*args):
346-
try:
347-
luaTable = await self.executeLuaFunction(functionName, args)
348-
if luaTable:
349-
return luaTable['1']
350-
return None
351-
except Exception as e:
352-
print("Lua exception error: \n", e)
353-
return fun
346+
async def async_lua_call(functionName, *args):
347+
try:
348+
luaTable = await self.executeLuaFunction(functionName, args)
349+
if luaTable:
350+
return luaTable['1']
351+
return None
352+
except Exception as e:
353+
print("Lua exception error: \n", e)
354354

355355
docs = await self.getDocumentation('lua')
356356

@@ -369,13 +369,18 @@ async def fun(*args):
369369
_lib = '' if subPyLibrary == pyLibrary else libraryName + '.'
370370
fullFunctionName = 'openspace.' + _lib + func['name']
371371

372-
subPyLibrary[func['name']] = generateAsyncSingleRetFunction(fullFunctionName)
372+
lua_call = partial(async_lua_call, fullFunctionName)
373+
if wrapper is not None:
374+
lua_call = partial(wrapper, lua_call)
375+
subPyLibrary[func['name']] = lua_call
373376

374377
return toNamedTuple(pyLibrary, libraryName)
375378

376-
async def singleReturnLibrary(self):
379+
async def singleReturnLibrary(self, wrapper=None):
377380
""" Get an object representing the OpenSpace lua library. \n
381+
(deprecated. Use library() instead)
382+
:param wrapper: if set, wraps all API calls (may be used to make them synchronous)
378383
:return - The lua library, mapped to async python functions. This method only
379384
returns the first return value. """
380385

381-
return await self.library(False)
386+
return await self.library(wrapper)

0 commit comments

Comments
 (0)