Discord-py - Using Guild ID as the Guild Object - python-requests

I have been trying to print in the console all channels IDs of a server with just the guild's ID; I've been reading the docs to make it:
https://discordpy.readthedocs.io/en/rewrite/api.html#discord.Guild, and this is what I've done so far.
#client.command()
async def getchannels(ctx, id):
a = client.get_guild(id)
for c in a.channels():
print(c.id)
But once I run the command, I get this error:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'channels'

If you take a look at the documentation for client.get_guild, it states that it will return None if the guild could not be found which is what is happening here and is what is causing your error. Because None is being returned and you are trying to access channels on what is being returned, it is throwing an error because None doesn't have an attribute called channels.
The reason why get_guild can return None is because it only checks its internal cache for a guild and doesn't actually make an API call. So if the guild is not in the cache, it will return None. The solution is to use client.fetch_guild instead. The difference between get_guild and fetch_guild is that fetch_guild will send a request to the API instead of looking in the internal cache. Another thing to keep in mind is that you may not have access to a guild, in which case a Forbidden exception will be raised. Another issues is that you are doing guild.channels() when you should be doing guild.channels. The channels attribute isn't a function so you don't need to call it with the two parenthesis.
Finally, fetch_guild is an async function which means you need to await it.
Here is some example code:
from discord import Forbidden
#client.command()
async def get_channels(ctx, id):
try:
guild = await client.get_guild(id)
except Forbidden:
await ctx.send("I do not have access to that guild or it doesn't exist.")
else:
for channel in guild.channels:
print(channel.id)

Related

Async SQLalchemy: accessing eagerly-loaded empty relationship triggers new lazy-load, raising error

I am using sqlalchemy + asyncpg, and 'selectin' eager loading.
I have Person items that have one-to-many relationships with Friends.
I insert a Person into my database, with no related Friend entries. If in the same session I try and get that Person from the database, I can access their static (non-relationship) columns fine, but cannot access the friends relationship.
I think trying to access person.friends is triggering a lazy load, despite it being enforced previously as a selectin load. Why is this? How can I avoid it?
# Create the ORM model
class Person(Base):
__tablename__ = 'items'
id_ = Column(POSTGRES_UUID(as_uuid=True), primary_key=True)
name = Column(String(32))
friends = relationship('Friend', lazy='selectin')
# Create an instance
person_id = uuid4()
person = Person(id_=person_id, name='Alice') # Note that this Person's friends are not set
# Add to database
async with AsyncSession(engine, expire_on_commit=False) as session:
try:
session.begin()
session.add(person)
await session.commit()
except:
await session.rollback()
raise
# Get the added person from the database
created_person = await session.get(person, person_id)
print(created_person.id_) # Works fine
print(created_person.friends) # Raises error
Error:
sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_() here.
Was IO attempted in an unexpected place? (Background on this error at: https://sqlalche.me/e/14/xd2s)
The solution is to use the populate_existing parameter in get:
populate_existing – causes the method to unconditionally emit a SQL query and refresh the object with the newly loaded data, regardless of whether or not the object is already present.
Replace
created_person = await session.get(person, person_id)
with
created_person = await session.get(person, person_id, populate_existing=True)
session.get documentation
See also: https://github.com/sqlalchemy/sqlalchemy/issues/7176
#theo-brown's answers goes straight to the point, but wanted to add some interesting information here.
Adding extra context on lazy loading and async SQLAlchemy:
When you fetch data using async SqlAlchemy, every model being queried spawns a coroutine. If you don't eager load your relationships, you'll end up with partially populated models.
Imagine this use case that I'm working on: I have a batch_job object, that relates to a batch_file and batch_job entries, all of which are tables in my database. When I don't eager load them, see what happens in the debugger:
The Traceback that I get when returning the object from an endpoint is this one:
greenlet_spawn has not been called; can't call await_only() here. Was IO attempted in an unexpected place? (Background on this error at: https://sqlalche.me/e/14/xd2s)
The reason is that I didn't await these values, and that's what eager loading does for you in async sqlalchemy.
However, you might not have to eager load if you're working inside the application scope and you'll want to use these values later, and hence you could await them.
For those who are using the ORM, you could do it with the good old loading options:
results = await db_session.execute(select(YourModel).options(joinedload(YourModel.relationshipcolumn)).all()

How to make Web API return all errors for the validated model?

ModelState returns only 1 error at a time when validation occurs. How to force Web API to return all errors at once.
services.AddControllers()
.ConfigureApiBehaviorOptions(setupAction =>
{
setupAction.InvalidModelStateResponseFactory = context =>
{
// context.ModelState here always contains only 1 error, even if I have more invalid fields in
}
};
Considering your scenario, it can be said that,
In InvalidModelStateResponseFactory there is a constructor callled ModelStateDictionary() under this you would get ErrorCount which can get you number of error.
But if you are expecting you would get all the error details together, you cannot do that. It will always fetch first one and terminates execution and entered to your custom InvalidModelStateResponseFactory middleware.
Note: So when any error encounters it terminates and return rather executing further as a results we always get first one. You
could get our official document here
Hope it would help you to guide you through.

Exception when GetItemQueryIterator() can't find a matching document in Cosmos DB

So, I'm trying to query cosmos collection for a specific document, with the following line of code:
FeedIterator<dynamic> querieditem = container.GetItemQueryIterator<dynamic>(mysqlquery);
When there exists an item in the database, this goes without any problems. However, when there doesn't exist any match in the database, I get the following exception:
System.Private.CoreLib: Exception while executing function: TestFunction. Microsoft.Azure.Cosmos.Client: Response status code does not indicate success: NotFound (404); Substatus: 0; ActivityId:123123; Reason: (Message: {"Errors":["Resource Not Found. Learn more: https://aka.ms/cosmosdb-tsg-not-found"]}
Does this really mean, that I need to add a try/catch, in case GetItemQueryIterator() can't find anything in Cosmos? Given that it is necessary, why does this make sense?
Some of the methods in the SDK throw exceptions on 404 as a legacy holdover. The better alternative is to use the Stream variants of the methods, which don't throw and use HTTP status codes instead that can be used to evaluate success. You just need an extra step to deserialize the response stream yourself.
See the docs and examples for GetItemQueryStreamIterator

Axon - How to get #QueryHandler handle method to return an Optional<MyType>

Note:
The point of this question is not to just getting back a value that I ultimately want.
I can do that by simply not using Optional.
I would like an elegant solution so I could start returning Optional.
Explanation of what I tried to do:
I used the QueryGateway with a signature that will query my handler.
I broke out my code so you can see that on my CompletableFuture I will do a blocking get in order to retrieve the Optional that contains the object I really want.
Note that I am not looking for a class that holds my optional.
If this is not elegant then I may as well just do my null check.
The call to the query works, but I get the following error:
org.axonframework.axonserver.connector.query.AxonServerQueryDispatchException: CANCELLED: HTTP/2 error code: CANCEL
Received Rst Stream
AXONIQ-5002
58484#DESKTOP-CK6HLMM
Example of code that initiates the query:
UserProfileOptionByUserQuery q = new UserProfileOptionByUserQuery(userId);
CompletableFuture<Optional<UserProfile>> query =
queryGateway.query(q,ResponseTypes.optionalInstanceOf(UserProfile.class));
Optional<UserProfile> optional = query.get();
Error occurs on the query.get() invocation.
Example of my Query Handler:
#QueryHandler
Optional<UserProfile> handle(UserProfileOptionByUserQuery query, #MetaDataValue(USER_INFO) UserInfo userInfo) {
assertUserCanQuery(query, userInfo);
return userProfileRepository.findById(query.getUserId());
}
The query handler works fine.
Other efforts such as using OptionalResponseType would not initiate my query as desired.
I think the key lies with the exception you are receiving Stephen.
Just to verify for my own good, I've tested the following permutations when it comes to Optional query handling:
Query Handler returns Optional, Query Dispatcher uses OptionalResponeType
Query Handler returns MyType, Query Dispatcher uses OptionalResponeType
Query Handler returns Optional, Query Dispatcher uses InstanceResponeType
Added, I've tried out these permutations both with the SimpleQueryBus and Axon Server. Both buses on all three options worked completely fine for me.
This suggest to me that you should dive in to the AxonServerQueryDispatchException you are receiving.
Hence, I am going to give you a couple of follow up questions to further deduce what the problem is. I'd suggest to update you original question with the response(s) to them.
Do you have a more detailed stack trace per chance?
And, what versions of Axon Framework and Axon Server are you using?
Are you on the Standard Edition? Enterprise edition?
Does this behavior only happen for this exact Optional query handler you've shared with us?

Cloud Endpoints - Google Glass object has no attribute 'mirror_service'

I'm attempting to incorporate cloud enpoints into my app, I'm currently using the Python Quickstart for proof of concept. I'm having an issue when I attempt to call a method to send a card to my glass. Below is my code, please ignore the indentation is missing.
#endpoints.api(name='tasks', version='v1',
description='API for TaskAlert Management',
allowed_client_ids=[CLIENT_ID, endpoints.API_EXPLORER_CLIENT_ID])
class TaskAlertApi(remote.Service):
#endpoints.method(Task, Task,
name='task.insert',
path='tasker',
http_method='POST')
def insert_task(self, request):
TaskModel(author=request.author, content=request.content, date=request.date).put()
themirror = MainHandler()
themirror._insert_map_with_distance_from_home()
return request
So when "themirror._insert_map_with_distance_from_home()" is called I am getting the following error. Does anyone have any suggestions? I am trying to call this from myappspot.com/_ah/api/explorer.
in _insert_map_with_distance_from_home
self.mirror_service.timeline().insert(body=body).execute()
AttributeError: 'MainHandler' object has no attribute 'mirror_service'
I'm afraid you will have to rethink your code quite a bit for this but I'll try to get the basics explained here.
The main problem is that the MainHandler does quite a bit when actually receiving a HTTP request. The most important thing is what happens in the #util.auth_required decorator of the MainHandler's get method, which actually creates the mirror_service, authenticated for the current user. When you access the MainHandler directly from your code, none of this actually happens, so there is no mirror_service available (which results in the error you get).
Since the way endpoints are called is quite different from the way normal RequestHandlers are called, you also can't rely on stored session credentials or similar to match an Endpoints User to the Mirror User.
Basically what you would have to do is to create a new mirror_service inside of your endpoint method.
For this you will have to call your API authenticated (adding the Mirror API scopes to the authentication scopes). You can then extract the used access_token from the request header and use this access_token to create OAuth2Credentials to create the mirror_service.
Some code snippets without promises of completeness since it's hard to tell without knowing your actual code:
import os
from oauth2client.client import AccessTokenCredentials
# extract the token from request
if "HTTP_AUTHORIZATION" in os.environ:
(tokentype, token) = os.environ["HTTP_AUTHORIZATION"].split(" ")
# create simple OAuth2Credentials using the token
credentials = AccessTokenCredentials(token, 'my-user-agent/1.0')
# create mirror_service (using the method from util.py from the quickstart(
mirror_service = create_service('mirror', 'v1', credentials)
Of course you would then also have to change the _insert_map_with_distance_from_home to use this mirror_service object, but moving this method away from your MainHandler would make more sense in this context anyway.

Resources