I am working on building an asyncio.Future integration with my Tornado app so I can request a callback. Essentially, I instantiated a class within a class, this creates a future and adds a callback to the function.
However, when I call this I get a bunch of error messages:
Traceback (most recent call last):
File "/Users/robot/tornado/venv/lib/python3.8/site-packages/tornado/web.py", line 1713, in _execute
result = await result
File "pending/request_seven.py", line 31, in get
await self.scheduleFuture._future(client.fetch('https://books.toscrape.com'), self.on_response)
File "pending/request_seven.py", line 25, in _future
fut = self.create_future()
AttributeError: '_asyncio.Future' object has no attribute 'create_future'
Here is what I have tried with my script:
define('port', default = 9057, help="run port 9060", type=int)
class requestFour(tornado.web.RequestHandler):
class scheduleFuture(asyncio.SelectorEventLoop):
#staticmethod
def unwrapper(fut: asyncio.Future, function):
return function()
def _future(self, fun1 ):
fut = self.create_future()
fut.add_done_callback(func(self.unwrapper, function=fun1))
return fut
async def get(self):
client = tornado.httpclient.AsyncHTTPClient()
await self.scheduleFuture._future(client.fetch('https://books.toscrape.com'), self.on_response)
def on_response(self, response):
body = response.body
self.write(body)
self.finish()
def my_app():
app = tornado.web.Application(handlers = [(r'/', requestFour)])
http_server = tornado.httpserver.HTTPServer(app)
return http_server
async def main():
app = my_app()
app.listen(options.port)
shutdown_event = asyncio.Event()
await shutdown_event.wait()
if __name__ == '__main__':
asyncio.run(main())
Related
I am trying to add websockets to my app. I use JWT tokens so I have to overide middleware for it.
#database_sync_to_async
def get_user(token):
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=ALGORITHM)
except:
return AnonymousUser()
token_exp = datetime.fromtimestamp(payload['exp'])
if token_exp < datetime.utcnow():
return AnonymousUser()
try:
response = requests.get(settings.OAUTH_URL, headers={'Authorization': f"Bearer {token}"})
if response.status_code == 200:
user = response.json()
return user
except:
error_logger.exception("Server is not available!")
class TokenAuthMiddleware(BaseMiddleware):
async def __call__(self, scope, receive, send):
close_old_connections()
try:
token_key = (dict((x.split('=') for x in scope['query_string'].decode().split("&")))).get('token', None)
except ValueError:
token_key = None
scope['user'] = await get_user(token_key)
return await super().__call__(scope, receive, send)
def JwtAuthMiddlewareStack(inner):
return TokenAuthMiddleware(AuthMiddlewareStack(inner))
My service is a microservice so the User model is located in another service. So I have to send a request to the service where the instance model is located. When I try to add "user" dict-like object to scope it returns me an error:
helpdesk_web | File "/usr/local/lib/python3.10/site-packages/channels/auth.py", line 176, in resolve_scope
helpdesk_web | scope["user"]._wrapped = await get_user(scope)
helpdesk_web | AttributeError: 'dict' object has no attribute '_wrapped'
If I delete this line scope['user'] = await get_user(token_key) or pass to the function model instance everything works.
Is there a way to add 'users' dict-like object instead of model instance to scope?
This is the code:
class ticket_launcher(discord.ui.View):
def __init__(self) -> None:
super().__init__(timeout=None)
#discord.ui.Button(label='Create a ticket', style = discord.ButtonStyle.blurple, custom_id = 'ticket_button')
async def ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
ticket = discord.utils.get(interaction.guild.text_channels, name = f'ticket-for-{interaction.user.name}-{interaction.user.discriminator}')
if ticket is not None: await interaction.response.send_message(f'You already have a ticket open at {ticket.mention}!', ephemeral = True)
else:
overwrites = {
interaction.guild.default_role: discord.PermissionOverwrite(view_channel = False),
interaction.user: discord.PermissionOverwrite(view_channel = True, send_messages = True, attach_files = True, embed_links = True),
interaction.guild.me: discord.PermissionOverwrite(view_channel = True, send_messages = True, read_message_history = True)
}
channel = await interaction.guild.create_text_channel(name=f'ticket-for-{interaction.user.name}-{interaction.user.discriminator}', overwrites=overwrites, reason=f'Ticket for {interaction.user}.')
await channel.send(f'{interaction.user.mention} created a ticket!')
await interaction.response.send_message(f'I have opened a ticket for you at {channel.mention}.', ephemeral=True)
tree = app_commands.CommandTree(client=client)
#tree.command(guild = discord.Object(id=TICKET_CHANNEL), name='ticket', description='Launches the ticket system.')
async def ticket(interaction: discord.Interaction):
embed = discord.Embed(title='If you have any problems click the big blue button below!', color=discord.Colour.blue())
await interaction.channel.send(embed=embed, view=ticket_launcher())
await interaction.response.send_message('Ticketing system has been launched successfully.', ephemeral=True)
it gives me this error message in the output:
Traceback (most recent call last):
File "c:\Users\schul\Desktop\MORE PYTHON\bot.py", line 214, in <module>
class ticket_launcher(discord.ui.View):
File "c:\Users\schul\Desktop\MORE PYTHON\bot.py", line 219, in ticket_launcher
async def ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
TypeError: 'Button' object is not callable
So can anyone mind helping me out with this, as this kinda annoying, would be thankfull if you would've helped me out :)
In your button decorator, use button in lowercase:
#discord.ui.button(label='Create a ticket', style = discord.ButtonStyle.blurple, custom_id = 'ticket_button')
Docs: https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=button#discord.ui.button
How to fix the error, but at the same time the class and self should remain?
Here Are the TraceBack:
Traceback (most recent call last):
File "C:\Users\sasha\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\sasha\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 855, in invoke
await self.prepare(ctx)
File "C:\Users\sasha\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 789, in prepare
await self._parse_arguments(ctx)
File "C:\Users\sasha\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 697, in _parse_arguments
transformed = await self.transform(ctx, param)
File "C:\Users\sasha\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 542, in transform
raise MissingRequiredArgument(param)
discord.ext.commands.errors.MissingRequiredArgument: ctx is a required argument that is missing.
And here are the code:
#!/usr/bin/python3
from discord.ext import commands
import discord
import inspect
class StarBot(commands.Bot):
def __init__(self, command_prefix, **options):
super().__init__(command_prefix, **options)
members = inspect.getmembers(self)
for name, member in members:
if isinstance(member, commands.Command):
if member.parent is None:
self.add_command(member)
async def on_ready(self):
print('Logged on as {0}!'.format(self.user))
#commands.command(name='reg', help='Для регистрации', pass_context=True)
async def reg(self, ctx):
if ' '.join(str(ctx.channel).split(' ')[:2]) == 'Direct Message':
await self.embed(ctx.channel, "Начало регистрации")
async def embed_channel(self, channel, title, string='', color=0xff9900):
embed = discord.Embed(color=color, title=title, description=string)
msg = await channel.send(embed=embed)
return msg
intents = discord.Intents.all()
bot = StarBot(command_prefix='/', intents=intents)
bot.run(TOKEN)
The issue with the code here:
#commands.command(name='reg', help='Для регистрации', pass_context=True)
async def reg(self, ctx):
if ' '.join(str(ctx.channel).split(' ')[:2]) == 'Direct Message':
await self.embed(ctx.channel, "Начало регистрации")
Here, you have (self,ctx):
async def reg(self, ctx):
In a cog it needs to be (client,ctx):
async def reg(client, ctx):
It should look like:
#commands.command(name='reg', help='Для регистрации', pass_context=True)
async def reg(client, ctx):
if ' '.join(str(ctx.channel).split(' ')[:2]) == 'Direct Message':
await self.embed(ctx.channel, "Начало регистрации")
I've been grokking some of my sample async code and I'm struggling to understand the flow of the data and how often I find myself awaiting.
Am I using await correctly? Also - are my output types correct? I'd imagine some these should be outputting coroutines (but my Pyright/Pylance type hinting keeps telling me that's wrong...)
The functions that require inspection are governed requests, send, governed_send, and governed_sendall. Maybe I'm not understanding what await is doing completely - and how this interacts with function scopes.
The code works correctly; I'd like to understand why and whether I can optimize out some of these awaits or if that's unnecessary.
import time
import asyncio
import httpx
from typing import Any, Callable, Coroutine, Dict, List
from rich import print
class GovernedClient:
def __init__(self):
self.client = httpx.AsyncClient()
self.loop = asyncio.get_event_loop()
self.semaphore = asyncio.BoundedSemaphore(4)
def __del__(self) -> None:
# Define a destructor that closes the client and the loop.
async def close(self: GovernedClient) -> None:
# An async function is required to await aclose
await self.client.aclose()
self.loop.run_until_complete(close(self))
self.loop.close()
def govern_requests(fn: Callable) -> Callable:
# govern_requests applies semaphore locking to a given callable.
async def call(self, *args, **kwargs):
async with self.semaphore:
return await fn(self, *args, **kwargs)
return call
async def send(self, method: str, url: str) -> httpx.Response:
# A single send.
request = httpx.Request(method, url, headers={'accept': 'application/json'})
return await self.client.send(request)
#govern_requests
async def governed_send(self, method: str, url: str) -> httpx.Response:
# Applies semaphore locking via decorator.
return await self.send(method, url)
def governed_sendall(self, urls: List[str]) -> List[httpx.Response]:
async def goverened_sendall(urls: List[str]) -> List[httpx.Response]:
start = time.time()
awaitables = [self.governed_send('GET', url) for url in urls]
responses = []
for response in asyncio.as_completed(awaitables):
responses.append(await response)
print('Total time: ', int(1000 * (time.time() - start)))
return responses
return self.loop.run_until_complete(goverened_sendall(urls))
if __name__ == '__main__':
URL = 'https://www.icanhazdadjoke.com'
bc = GovernedClient()
urls = [URL for url in range(20)]
responses = bc.governed_sendall(urls)
for response in responses:
print(response.json())
You know that async is a function that will not block the code. Right?
You know that await is an async function caller that when called it will not block the code. Right?
So There's no using too much async/await because if you using it it will not blocking your code unlike def and functioname().
I guess you may understand.
Happy day!
Ive been having trouble with this for a little while now. When declaring a async function like:
async def init(loop):
and then I call the function it returns a:
NameError: name 'init' is not defined
Here is how the code all looks:
class Server:
def __init__(self, port):
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
server = loop.run_until_complete(init(loop))
print("Serving on {}".format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
print("\rclosing the server")
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
async def init(loop):
server = await loop.create_server(handle_request, '127.0.0.1', 8881)
return server
async def handle_request():
Any direction that you could point me in would be helpful.
Thanks!
Seems like def init() is inside your class. Move it out of the class by unindenting it:
class Server:
def __init__(self, port):
#....
loop.close()
# IT SHOULD NOT BE HERE
#IT SHOULD BE HERE!!!
async def init(loop):
server = await loop.create_server(handle_request, '127.0.0.1', 8881)
return server