Merge pull request #732 from meejah/issue653-async-await-examples
Issue653 async await examples
This commit is contained in:
commit
224370cd9d
@ -23,3 +23,13 @@ If you are new to Autobahn and WAMP, you should start with the following if you'
|
||||
Note that many of the examples use the same URIs for topics or RPC endpoints, so you can mix and match which `backend` or `frontend` script (whether Python or JavaScript) you use. For example, a Web browser tab could load a `backend.html` page that does publishes while you run a Python `frontend.py` that subscribes to those topics.
|
||||
|
||||
[Set up locally to run the examples](running-the-examples.md).
|
||||
|
||||
## Python 3
|
||||
|
||||
All the examples are now using modern Python 3.5+ syntax (`await` and `async def`).
|
||||
|
||||
However, **everything works fine with earlier syntax** (`yield from` and `@asyncio.coroutine`) **or** with Python 2 and the "trollius" library. To use an example with older syntax, you'll have to change any `await` to `yield from` (or just `yield` for trollius) and change any `async def` to a plain `def` with the `@asyncio.coroutine` decorator.
|
||||
|
||||
To use trollius, additionally change `import asyncio` to `import trollius as asyncio`
|
||||
|
||||
For Twisted users, everything will work with Python 2.7 or Python 3 without changes.
|
||||
|
@ -4,20 +4,20 @@ from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
|
||||
class MyComponent(ApplicationSession):
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
# a remote procedure; see frontend.py for a Python front-end
|
||||
# that calls this. Any language with WAMP bindings can now call
|
||||
# this procedure if its connected to the same router and realm.
|
||||
def add2(x, y):
|
||||
return x + y
|
||||
yield from self.register(add2, u'com.myapp.add2')
|
||||
reg = await self.register(add2, u'com.myapp.add2')
|
||||
print("registered 'com.myapp.add2' with id {}".format(reg.id))
|
||||
|
||||
# publish an event every second. The event payloads can be
|
||||
# anything JSON- and msgpack- serializable
|
||||
while True:
|
||||
self.publish(u'com.myapp.hello', 'Hello, world!')
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -4,16 +4,15 @@ from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
|
||||
class MyComponent(ApplicationSession):
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
# listening for the corresponding message from the "backend"
|
||||
# (any session that .publish()es to this topic).
|
||||
def onevent(msg):
|
||||
print("Got event: {}".format(msg))
|
||||
yield from self.subscribe(onevent, u'com.myapp.hello')
|
||||
await self.subscribe(onevent, u'com.myapp.hello')
|
||||
|
||||
# call a remote procedure.
|
||||
res = yield from self.call(u'com.myapp.add2', 2, 3)
|
||||
res = await self.call(u'com.myapp.add2', 2, 3)
|
||||
print("Got result: {}".format(res))
|
||||
|
||||
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -39,14 +34,13 @@ class Component(ApplicationSession):
|
||||
An application component that publishes an event every second.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
counter = 0
|
||||
while True:
|
||||
print("publish: com.myapp.topic1", counter)
|
||||
self.publish(u'com.myapp.topic1', counter)
|
||||
counter += 1
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -40,8 +35,7 @@ class Component(ApplicationSession):
|
||||
stop after having received 5 events.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
self.received = 0
|
||||
|
||||
@ -51,7 +45,7 @@ class Component(ApplicationSession):
|
||||
if self.received > 5:
|
||||
self.leave()
|
||||
|
||||
yield from self.subscribe(on_event, u'com.myapp.topic1')
|
||||
await self.subscribe(on_event, u'com.myapp.topic1')
|
||||
|
||||
def onDisconnect(self):
|
||||
asyncio.get_event_loop().stop()
|
||||
|
@ -27,12 +27,7 @@
|
||||
import random
|
||||
from os import environ
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn.wamp.types import SubscribeOptions
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -43,8 +38,7 @@ class Component(ApplicationSession):
|
||||
with complex payloads every second.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
counter = 0
|
||||
while True:
|
||||
print("publish: com.myapp.heartbeat")
|
||||
@ -55,7 +49,7 @@ class Component(ApplicationSession):
|
||||
self.publish(u'com.myapp.topic2', random.randint(0, 100), 23, c="Hello", d=obj)
|
||||
|
||||
counter += 1
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -27,12 +27,7 @@
|
||||
import random
|
||||
from os import environ
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn.wamp.types import SubscribeOptions
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -43,19 +38,18 @@ class Component(ApplicationSession):
|
||||
payload and of complex payload, and stops after 5 seconds.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
self.received = 0
|
||||
|
||||
def on_heartbeat(details=None):
|
||||
print("Got heartbeat (publication ID {})".format(details.publication))
|
||||
|
||||
yield from self.subscribe(on_heartbeat, u'com.myapp.heartbeat', options=SubscribeOptions(details_arg='details'))
|
||||
await self.subscribe(on_heartbeat, u'com.myapp.heartbeat', options=SubscribeOptions(details_arg='details'))
|
||||
|
||||
def on_topic2(a, b, c=None, d=None):
|
||||
print("Got event: {} {} {} {}".format(a, b, c, d))
|
||||
|
||||
yield from self.subscribe(on_topic2, u'com.myapp.topic2')
|
||||
await self.subscribe(on_topic2, u'com.myapp.topic2')
|
||||
asyncio.get_event_loop().call_later(5, self.leave)
|
||||
|
||||
def onDisconnect(self):
|
||||
|
@ -26,12 +26,7 @@
|
||||
|
||||
from os import environ
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
|
||||
@ -40,8 +35,7 @@ class Component(ApplicationSession):
|
||||
An application component that publishes an event every second.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
counter = 0
|
||||
while True:
|
||||
print("publish: com.myapp.topic1", counter)
|
||||
@ -50,7 +44,7 @@ class Component(ApplicationSession):
|
||||
print("publish: com.myapp.topic2 'Hello world.'")
|
||||
self.publish(u'com.myapp.topic2', "Hello world.")
|
||||
counter += 1
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -26,12 +26,7 @@
|
||||
|
||||
from os import environ
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn import wamp
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -42,13 +37,12 @@ class Component(ApplicationSession):
|
||||
stop after having received 5 events.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
self.received = 0
|
||||
|
||||
# subscribe all methods on this object decorated with "@wamp.subscribe"
|
||||
# as PubSub event handlers
|
||||
results = yield from self.subscribe(self)
|
||||
results = await self.subscribe(self)
|
||||
for res in results:
|
||||
if isinstance(res, wamp.protocol.Subscription):
|
||||
# res is an Subscription instance
|
||||
|
@ -26,12 +26,7 @@
|
||||
|
||||
from os import environ
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn.wamp.types import PublishOptions, EventDetails, SubscribeOptions
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -41,21 +36,20 @@ class Component(ApplicationSession):
|
||||
An application component that publishes an event every second.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
def on_event(i):
|
||||
print("Got event: {}".format(i))
|
||||
yield from self.subscribe(on_event, u'com.myapp.topic1')
|
||||
await self.subscribe(on_event, u'com.myapp.topic1')
|
||||
|
||||
counter = 0
|
||||
while True:
|
||||
publication = yield from self.publish(u'com.myapp.topic1',
|
||||
publication = await self.publish(u'com.myapp.topic1',
|
||||
counter,
|
||||
options=PublishOptions(acknowledge=True, exclude_me=False))
|
||||
print("Event published with publication ID {}".format(publication.id))
|
||||
counter += 1
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -26,12 +26,7 @@
|
||||
|
||||
from os import environ
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn.wamp.types import PublishOptions, EventDetails, SubscribeOptions
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -42,8 +37,7 @@ class Component(ApplicationSession):
|
||||
stop after having received 5 events.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
self.received = 0
|
||||
|
||||
def on_event(i, details=None):
|
||||
@ -52,7 +46,7 @@ class Component(ApplicationSession):
|
||||
if self.received > 5:
|
||||
self.leave()
|
||||
|
||||
yield from self.subscribe(on_event, u'com.myapp.topic1',
|
||||
await self.subscribe(on_event, u'com.myapp.topic1',
|
||||
options=SubscribeOptions(details_arg='details'))
|
||||
|
||||
def onDisconnect(self):
|
||||
|
@ -26,12 +26,7 @@
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
import ssl
|
||||
@ -42,14 +37,13 @@ class Component(ApplicationSession):
|
||||
An application component that publishes an event every second.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
counter = 0
|
||||
while True:
|
||||
print("publish: com.myapp.topic1", counter)
|
||||
self.publish(u'com.myapp.topic1', counter)
|
||||
counter += 1
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn.asyncio.wamp import ApplicationSession
|
||||
|
||||
|
||||
@ -39,11 +34,10 @@ class Component(ApplicationSession):
|
||||
An application component that publishes an event every second.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
counter = 0
|
||||
while True:
|
||||
self.publish(u'com.myapp.topic1', counter)
|
||||
counter += 1
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
|
@ -26,12 +26,7 @@
|
||||
|
||||
from os import environ
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
|
||||
@ -42,12 +37,10 @@ class Component(ApplicationSession):
|
||||
resubscribes for another run. Then it stops.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def test(self):
|
||||
async def test(self):
|
||||
self.received = 0
|
||||
|
||||
@asyncio.coroutine
|
||||
def on_event(i):
|
||||
async def on_event(i):
|
||||
print("Got event: {}".format(i))
|
||||
self.received += 1
|
||||
if self.received > 5:
|
||||
@ -55,20 +48,19 @@ class Component(ApplicationSession):
|
||||
if self.runs > 1:
|
||||
self.leave()
|
||||
else:
|
||||
yield from self.subscription.unsubscribe()
|
||||
await self.subscription.unsubscribe()
|
||||
|
||||
print("Unsubscribed .. continue in 5s ..")
|
||||
# can't use loop.call_later() with a coroutine for some reason
|
||||
yield from asyncio.sleep(5)
|
||||
yield from self.test()
|
||||
await asyncio.sleep(5)
|
||||
await self.test()
|
||||
|
||||
self.subscription = yield from self.subscribe(on_event, u'com.myapp.topic1')
|
||||
self.subscription = await self.subscribe(on_event, u'com.myapp.topic1')
|
||||
print("Subscribed with subscription ID {}".format(self.subscription.id))
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
self.runs = 0
|
||||
yield from self.test()
|
||||
await self.test()
|
||||
|
||||
def onDisconnect(self):
|
||||
asyncio.get_event_loop().stop()
|
||||
|
@ -12,22 +12,21 @@ from runner import ApplicationRunnerRawSocket
|
||||
|
||||
|
||||
class MyComponent(ApplicationSession):
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
# a remote procedure; see frontend.py for a Python front-end
|
||||
# that calls this. Any language with WAMP bindings can now call
|
||||
# this procedure if its connected to the same router and realm.
|
||||
def add2(x, y):
|
||||
log.debug('add2 called with %s %s', x, y)
|
||||
return x + y
|
||||
yield from self.register(add2, u'com.myapp.add2')
|
||||
await self.register(add2, u'com.myapp.add2')
|
||||
|
||||
# publish an event every second. The event payloads can be
|
||||
# anything JSON- and msgpack- serializable
|
||||
while True:
|
||||
self.publish(u'com.myapp.hello', 'Hello, world! Time is %s' % datetime.utcnow())
|
||||
log.debug('Published msg')
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -12,25 +12,24 @@ from autobahn.wamp import ApplicationError
|
||||
|
||||
|
||||
class MyComponent(ApplicationSession):
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
# listening for the corresponding message from the "backend"
|
||||
# (any session that .publish()es to this topic).
|
||||
def onevent(msg):
|
||||
log.info("Got event: {}".format(msg))
|
||||
yield from self.subscribe(onevent, u'com.myapp.hello')
|
||||
await self.subscribe(onevent, u'com.myapp.hello')
|
||||
|
||||
# call a remote procedure.
|
||||
count = 0
|
||||
while True:
|
||||
try:
|
||||
res = yield from self.call(u'com.myapp.add2', count, count+1)
|
||||
res = await self.call(u'com.myapp.add2', count, count+1)
|
||||
log.info("Got result: {}".format(res))
|
||||
except ApplicationError:
|
||||
pass
|
||||
count += 1
|
||||
|
||||
yield from asyncio.sleep(2)
|
||||
await asyncio.sleep(2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -40,8 +35,7 @@ class Component(ApplicationSession):
|
||||
of arguments.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
def ping():
|
||||
return
|
||||
@ -59,11 +53,11 @@ class Component(ApplicationSession):
|
||||
def arglen(*args, **kwargs):
|
||||
return [len(args), len(kwargs)]
|
||||
|
||||
yield from self.register(ping, u'com.arguments.ping')
|
||||
yield from self.register(add2, u'com.arguments.add2')
|
||||
yield from self.register(stars, u'com.arguments.stars')
|
||||
yield from self.register(orders, u'com.arguments.orders')
|
||||
yield from self.register(arglen, u'com.arguments.arglen')
|
||||
await self.register(ping, u'com.arguments.ping')
|
||||
await self.register(add2, u'com.arguments.add2')
|
||||
await self.register(stars, u'com.arguments.stars')
|
||||
await self.register(orders, u'com.arguments.orders')
|
||||
await self.register(arglen, u'com.arguments.arglen')
|
||||
print("Registered methods; ready for frontend.")
|
||||
|
||||
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -39,43 +34,42 @@ class Component(ApplicationSession):
|
||||
An application component calling the different backend procedures.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
yield from self.call(u'com.arguments.ping')
|
||||
await self.call(u'com.arguments.ping')
|
||||
print("Pinged!")
|
||||
|
||||
res = yield from self.call(u'com.arguments.add2', 2, 3)
|
||||
res = await self.call(u'com.arguments.add2', 2, 3)
|
||||
print("Add2: {}".format(res))
|
||||
|
||||
starred = yield from self.call(u'com.arguments.stars')
|
||||
starred = await self.call(u'com.arguments.stars')
|
||||
print("Starred 1: {}".format(starred))
|
||||
|
||||
starred = yield from self.call(u'com.arguments.stars', nick=u'Homer')
|
||||
starred = await self.call(u'com.arguments.stars', nick=u'Homer')
|
||||
print("Starred 2: {}".format(starred))
|
||||
|
||||
starred = yield from self.call(u'com.arguments.stars', stars=5)
|
||||
starred = await self.call(u'com.arguments.stars', stars=5)
|
||||
print("Starred 3: {}".format(starred))
|
||||
|
||||
starred = yield from self.call(u'com.arguments.stars', nick=u'Homer', stars=5)
|
||||
starred = await self.call(u'com.arguments.stars', nick=u'Homer', stars=5)
|
||||
print("Starred 4: {}".format(starred))
|
||||
|
||||
orders = yield from self.call(u'com.arguments.orders', u'coffee')
|
||||
orders = await self.call(u'com.arguments.orders', u'coffee')
|
||||
print("Orders 1: {}".format(orders))
|
||||
|
||||
orders = yield from self.call(u'com.arguments.orders', u'coffee', limit=10)
|
||||
orders = await self.call(u'com.arguments.orders', u'coffee', limit=10)
|
||||
print("Orders 2: {}".format(orders))
|
||||
|
||||
arglengths = yield from self.call(u'com.arguments.arglen')
|
||||
arglengths = await self.call(u'com.arguments.arglen')
|
||||
print("Arglen 1: {}".format(arglengths))
|
||||
|
||||
arglengths = yield from self.call(u'com.arguments.arglen', 1, 2, 3)
|
||||
arglengths = await self.call(u'com.arguments.arglen', 1, 2, 3)
|
||||
print("Arglen 1: {}".format(arglengths))
|
||||
|
||||
arglengths = yield from self.call(u'com.arguments.arglen', a=1, b=2, c=3)
|
||||
arglengths = await self.call(u'com.arguments.arglen', a=1, b=2, c=3)
|
||||
print("Arglen 2: {}".format(arglengths))
|
||||
|
||||
arglengths = yield from self.call(u'com.arguments.arglen', 1, 2, 3, a=1, b=2, c=3)
|
||||
arglengths = await self.call(u'com.arguments.arglen', 1, 2, 3, a=1, b=2, c=3)
|
||||
print("Arglen 3: {}".format(arglengths))
|
||||
|
||||
self.leave()
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.wamp.types import CallResult
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
@ -41,19 +36,18 @@ class Component(ApplicationSession):
|
||||
return complex results.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
def add_complex(a, ai, b, bi):
|
||||
return CallResult(c=a + b, ci=ai + bi)
|
||||
|
||||
yield from self.register(add_complex, u'com.myapp.add_complex')
|
||||
await self.register(add_complex, u'com.myapp.add_complex')
|
||||
|
||||
def split_name(fullname):
|
||||
forename, surname = fullname.split()
|
||||
return CallResult(forename, surname)
|
||||
|
||||
yield from self.register(split_name, u'com.myapp.split_name')
|
||||
await self.register(split_name, u'com.myapp.split_name')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.wamp.types import CallResult
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
@ -41,13 +36,12 @@ class Component(ApplicationSession):
|
||||
produce complex results and showing how to access those.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
res = yield from self.call(u'com.myapp.add_complex', 2, 3, 4, 5)
|
||||
res = await self.call(u'com.myapp.add_complex', 2, 3, 4, 5)
|
||||
print("Result: {} + {}i".format(res.kwresults['c'], res.kwresults['ci']))
|
||||
|
||||
res = yield from self.call(u'com.myapp.split_name', 'Homer Simpson')
|
||||
res = await self.call(u'com.myapp.split_name', 'Homer Simpson')
|
||||
print("Forname: {}, Surname: {}".format(res.results[0], res.results[1]))
|
||||
|
||||
self.leave()
|
||||
|
@ -27,12 +27,7 @@
|
||||
from os import environ
|
||||
import datetime
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn import wamp
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -42,13 +37,12 @@ class Component(ApplicationSession):
|
||||
An application component registering RPC endpoints using decorators.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
# register all methods on this object decorated with "@wamp.register"
|
||||
# as a RPC endpoint
|
||||
##
|
||||
results = yield from self.register(self)
|
||||
results = await self.register(self)
|
||||
for res in results:
|
||||
if isinstance(res, wamp.protocol.Registration):
|
||||
# res is an Registration instance
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -39,8 +34,7 @@ class Component(ApplicationSession):
|
||||
An application component calling the different backend procedures.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
procs = [u'com.mathservice.add2',
|
||||
u'com.mathservice.mul2',
|
||||
@ -48,7 +42,7 @@ class Component(ApplicationSession):
|
||||
|
||||
try:
|
||||
for proc in procs:
|
||||
res = yield from self.call(proc, 2, 3)
|
||||
res = await self.call(proc, 2, 3)
|
||||
print("{}: {}".format(proc, res))
|
||||
except Exception as e:
|
||||
print("Something went wrong: {}".format(e))
|
||||
|
@ -27,12 +27,7 @@
|
||||
from os import environ
|
||||
import math
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn import wamp
|
||||
from autobahn.wamp.exception import ApplicationError
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
@ -51,8 +46,7 @@ class Component(ApplicationSession):
|
||||
Example WAMP application backend that raised exceptions.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
# raising standard exceptions
|
||||
##
|
||||
@ -63,7 +57,7 @@ class Component(ApplicationSession):
|
||||
# this also will raise, if x < 0
|
||||
return math.sqrt(x)
|
||||
|
||||
yield from self.register(sqrt, u'com.myapp.sqrt')
|
||||
await self.register(sqrt, u'com.myapp.sqrt')
|
||||
|
||||
# raising WAMP application exceptions
|
||||
##
|
||||
@ -79,7 +73,7 @@ class Component(ApplicationSession):
|
||||
# forward keyword arguments in exceptions
|
||||
raise ApplicationError(u"com.myapp.error.invalid_length", min=3, max=10)
|
||||
|
||||
yield from self.register(checkname, u'com.myapp.checkname')
|
||||
await self.register(checkname, u'com.myapp.checkname')
|
||||
|
||||
# defining and automapping WAMP application exceptions
|
||||
##
|
||||
@ -89,7 +83,7 @@ class Component(ApplicationSession):
|
||||
if a < b:
|
||||
raise AppError1(b - a)
|
||||
|
||||
yield from self.register(compare, u'com.myapp.compare')
|
||||
await self.register(compare, u'com.myapp.compare')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -27,12 +27,7 @@
|
||||
from os import environ
|
||||
import math
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn import wamp
|
||||
from autobahn.wamp.exception import ApplicationError
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
@ -51,14 +46,13 @@ class Component(ApplicationSession):
|
||||
Example WAMP application frontend that catches exceptions.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
# catching standard exceptions
|
||||
##
|
||||
for x in [2, 0, -2]:
|
||||
try:
|
||||
res = yield from self.call(u'com.myapp.sqrt', x)
|
||||
res = await self.call(u'com.myapp.sqrt', x)
|
||||
except Exception as e:
|
||||
print("Error: {} {}".format(e, e.args))
|
||||
else:
|
||||
@ -68,7 +62,7 @@ class Component(ApplicationSession):
|
||||
##
|
||||
for name in ['foo', 'a', '*' * 11, 'Hello']:
|
||||
try:
|
||||
res = yield from self.call(u'com.myapp.checkname', name)
|
||||
res = await self.call(u'com.myapp.checkname', name)
|
||||
except ApplicationError as e:
|
||||
print("Error: {} {} {} {}".format(e, e.error, e.args, e.kwargs))
|
||||
else:
|
||||
@ -79,11 +73,11 @@ class Component(ApplicationSession):
|
||||
self.define(AppError1)
|
||||
|
||||
try:
|
||||
yield from self.call(u'com.myapp.compare', 3, 17)
|
||||
await self.call(u'com.myapp.compare', 3, 17)
|
||||
except AppError1 as e:
|
||||
print("Compare Error: {}".format(e))
|
||||
|
||||
yield from self.leave()
|
||||
await self.leave()
|
||||
|
||||
def onDisconnect(self):
|
||||
asyncio.get_event_loop().stop()
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.wamp.types import CallOptions, RegisterOptions, PublishOptions
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
@ -41,8 +36,7 @@ class Component(ApplicationSession):
|
||||
different kinds of arguments.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
def square(val, details=None):
|
||||
print("square called from: {}".format(details.caller))
|
||||
@ -57,7 +51,7 @@ class Component(ApplicationSession):
|
||||
self.publish(u'com.myapp.square_on_nonpositive', val, options=options)
|
||||
return val * val
|
||||
|
||||
yield from self.register(square, u'com.myapp.square', RegisterOptions(details_arg='details'))
|
||||
await self.register(square, u'com.myapp.square', RegisterOptions(details_arg='details'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.wamp.types import CallOptions, RegisterOptions, PublishOptions
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
@ -40,19 +35,18 @@ class Component(ApplicationSession):
|
||||
An application component calling the different backend procedures.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
def on_event(val):
|
||||
print("Someone requested to square non-positive: {}".format(val))
|
||||
|
||||
yield from self.subscribe(on_event, u'com.myapp.square_on_nonpositive')
|
||||
await self.subscribe(on_event, u'com.myapp.square_on_nonpositive')
|
||||
|
||||
for val in [2, 0, -2]:
|
||||
res = yield from self.call(u'com.myapp.square', val, options=CallOptions())
|
||||
res = await self.call(u'com.myapp.square', val, options=CallOptions())
|
||||
print("Squared {} = {}".format(val, res))
|
||||
|
||||
yield from self.leave()
|
||||
await self.leave()
|
||||
|
||||
def onDisconnect(self):
|
||||
asyncio.get_event_loop().stop()
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.wamp.types import CallOptions, RegisterOptions
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
@ -40,20 +35,18 @@ class Component(ApplicationSession):
|
||||
Application component that produces progressive results.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
@asyncio.coroutine
|
||||
def longop(n, details=None):
|
||||
async def longop(n, details=None):
|
||||
if details.progress:
|
||||
for i in range(n):
|
||||
details.progress(i)
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
else:
|
||||
yield from asyncio.sleep(1 * n)
|
||||
await asyncio.sleep(1 * n)
|
||||
return n
|
||||
|
||||
yield from self.register(longop, u'com.myapp.longop', RegisterOptions(details_arg='details'))
|
||||
await self.register(longop, u'com.myapp.longop', RegisterOptions(details_arg='details'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.wamp.types import CallOptions, RegisterOptions
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
@ -40,13 +35,12 @@ class Component(ApplicationSession):
|
||||
Application component that consumes progressive results.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
def on_progress(i):
|
||||
print("Progress: {}".format(i))
|
||||
|
||||
res = yield from self.call(u'com.myapp.longop', 3, options=CallOptions(on_progress=on_progress))
|
||||
res = await self.call(u'com.myapp.longop', 3, options=CallOptions(on_progress=on_progress))
|
||||
|
||||
print("Final: {}".format(res))
|
||||
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
@ -39,20 +34,18 @@ class Component(ApplicationSession):
|
||||
A math service application component.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
def square(x):
|
||||
return x * x
|
||||
|
||||
yield from self.register(square, u'com.math.square')
|
||||
await self.register(square, u'com.math.square')
|
||||
|
||||
@asyncio.coroutine
|
||||
def slowsquare(x, delay=1):
|
||||
yield from asyncio.sleep(delay)
|
||||
async def slowsquare(x, delay=1):
|
||||
await asyncio.sleep(delay)
|
||||
return x * x
|
||||
|
||||
yield from self.register(slowsquare, u'com.math.slowsquare')
|
||||
await self.register(slowsquare, u'com.math.slowsquare')
|
||||
print("Registered com.math.slowsquare")
|
||||
|
||||
|
||||
|
@ -27,12 +27,7 @@
|
||||
from os import environ
|
||||
import time
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from functools import partial
|
||||
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
@ -43,8 +38,7 @@ class Component(ApplicationSession):
|
||||
An application component using the time service.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
def got(started, msg, f):
|
||||
res = f.result()
|
||||
@ -59,7 +53,7 @@ class Component(ApplicationSession):
|
||||
d2 = self.call(u'com.math.square', 3)
|
||||
d2.add_done_callback(partial(got, t2, "Quick Square"))
|
||||
|
||||
yield from asyncio.gather(d1, d2)
|
||||
await asyncio.gather(d1, d2)
|
||||
print("All finished.")
|
||||
self.leave()
|
||||
|
||||
|
@ -24,12 +24,7 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from os import environ
|
||||
import datetime
|
||||
|
||||
@ -41,14 +36,13 @@ class Component(ApplicationSession):
|
||||
A simple time service application component.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
|
||||
def utcnow():
|
||||
now = datetime.datetime.utcnow()
|
||||
return now.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
yield from self.register(utcnow, u'com.timeservice.now')
|
||||
await self.register(utcnow, u'com.timeservice.now')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -27,12 +27,7 @@
|
||||
from os import environ
|
||||
import datetime
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner
|
||||
|
||||
|
||||
@ -41,10 +36,9 @@ class Component(ApplicationSession):
|
||||
An application component using the time service.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
try:
|
||||
now = yield from self.call(u'com.timeservice.now')
|
||||
now = await self.call(u'com.timeservice.now')
|
||||
except Exception as e:
|
||||
print("Error: {}".format(e))
|
||||
else:
|
||||
|
@ -25,13 +25,7 @@
|
||||
###############################################################################
|
||||
|
||||
import datetime
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
import asyncio
|
||||
from autobahn.asyncio.wamp import ApplicationSession
|
||||
|
||||
|
||||
@ -47,12 +41,11 @@ class Component(ApplicationSession):
|
||||
ApplicationSession.__init__(self, config)
|
||||
self.count = 0
|
||||
|
||||
@asyncio.coroutine
|
||||
def onJoin(self, details):
|
||||
async def onJoin(self, details):
|
||||
print("Realm joined (WAMP session started).")
|
||||
|
||||
try:
|
||||
now = yield from self.call(u'com.timeservice.now')
|
||||
now = await self.call(u'com.timeservice.now')
|
||||
except Exception as e:
|
||||
print("Error: {}".format(e))
|
||||
else:
|
||||
|
@ -38,15 +38,14 @@ class MyClientProtocol(WebSocketClientProtocol):
|
||||
def onConnect(self, response):
|
||||
print("Server connected: {0}".format(response.peer))
|
||||
|
||||
@asyncio.coroutine
|
||||
def onOpen(self):
|
||||
async def onOpen(self):
|
||||
print("WebSocket connection open.")
|
||||
|
||||
# start sending messages every second ..
|
||||
while True:
|
||||
self.sendMessage(u"Hello, world!".encode('utf8'))
|
||||
self.sendMessage(b"\x00\x01\x03\x04", isBinary=True)
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
def onMessage(self, payload, isBinary):
|
||||
if isBinary:
|
||||
|
@ -50,12 +50,7 @@ class MyServerProtocol(WebSocketServerProtocol):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
factory = WebSocketServerFactory(u"ws://127.0.0.1:9000")
|
||||
factory.protocol = MyServerProtocol
|
||||
|
@ -51,12 +51,7 @@ class SlowSquareClientProtocol(WebSocketClientProtocol):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
factory = WebSocketClientFactory(u"ws://127.0.0.1:9000")
|
||||
factory.protocol = SlowSquareClientProtocol
|
||||
|
@ -26,30 +26,24 @@
|
||||
|
||||
from autobahn.asyncio.websocket import WebSocketServerProtocol, \
|
||||
WebSocketServerFactory
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
import trollius as asyncio
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
|
||||
class SlowSquareServerProtocol(WebSocketServerProtocol):
|
||||
|
||||
@asyncio.coroutine
|
||||
def slowsquare(self, x):
|
||||
async def slowsquare(self, x):
|
||||
if x > 5:
|
||||
raise Exception("number too large")
|
||||
else:
|
||||
yield from asyncio.sleep(1)
|
||||
await asyncio.sleep(1)
|
||||
return x * x
|
||||
|
||||
@asyncio.coroutine
|
||||
def onMessage(self, payload, isBinary):
|
||||
async def onMessage(self, payload, isBinary):
|
||||
if not isBinary:
|
||||
x = json.loads(payload.decode('utf8'))
|
||||
try:
|
||||
res = yield from self.slowsquare(x)
|
||||
res = await self.slowsquare(x)
|
||||
except Exception as e:
|
||||
self.sendClose(1000, "Exception raised: {0}".format(e))
|
||||
else:
|
||||
|
@ -105,11 +105,7 @@ if __name__ == '__main__':
|
||||
|
||||
txaio.start_logging(level='info')
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
|
||||
factory = TesteeClientFactory(u"ws://127.0.0.1:9001")
|
||||
|
||||
|
@ -27,11 +27,7 @@
|
||||
import txaio
|
||||
txaio.use_asyncio()
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
# Trollius >= 0.3 was renamed
|
||||
import trollius as asyncio
|
||||
import asyncio
|
||||
|
||||
import autobahn
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user