#dev-contrib
1 messages ยท Page 127 of 1
that sounds even more problematic
Not quite sure why you'd want to remind on a role though
the helper role internally
I think going stricter to only accept mentions/ids like you said would be best here
You wouldn't do like !remind Helpers "remind all helpers of this" though
Or at least it's never happened in the 2ish years I've been a helper+
I think it was for staff meetings, or maybe admins/owners use it in their channels
idk
kutie has said they use it
Staff meeting pings are manual
Regardless, that Role should probably be restricted to the internal roles, or even removed depending on internal usage probably
Yeah
That makes me wonder if the people with the partner role who can mention others could mention voice verified ๐
I suppose we just need to make this Greedy[t.Union[UserMentionOrID, discord.Role]] then?
allowed mentions limits it to moderation roles
Given the nature of how a reminder works, if a bug in that case is ever introduced later, or functionality is changed, the reminder would still have the old role attached ยฏ_(ใ)_/ยฏ
that'll probably do it yea
yea, there are many vectors if we consider the possibility of anything that changes the bot's allowed mentions
true
my opinion is don't let the user set a role if they aren't in the allowed roles
If they're not staff they can't mention anyone
So it's probably fine (since already restricted to staff)
Oh right
They can't mention people but it will still convert
Same as if you do it
That's just how dpy's parsing works
er, it doesn't convert for me, but it converts for them
!remind 3d m
m is not a valid duration string.
still fails in the same way
? We don't use the reminder to ping roles. I don't think I've ever said that.
Partners won't change anything
Should the functionality be removed then?
Sure? I'm new to this convo. I just wanted to clear up what I have and have not said.
an issue should be opened so it can be discussed more in depth
It's just whether it's needed or not
It's not a case of "we have to remove it"
!remind 3d fix this
fix is not a valid duration string.
!remind [mentions]... <expiration> <content>
Can also use: reminder, reminders, remindme
Commands for managing your reminders.
Subcommands:
!remind delete <id_>
Delete one of your active reminders.
!remind edit
Commands for modifying your current reminders.
!remind list
View a paginated embed of all reminders for your user.
!remind new [mentions]... <expiration> <content>
Set yourself a simple reminder.
Just don't see a reason to remove something that works perfectly well
It's the greediness of discord.Member that needs to be changed here
The issue now is that you can unintentionally ping a user because it converts the string to a user if it matches. To fix that we just need it to take a user ID or a mention, right?
The question is to whether you want to limit it to only take an ID/mention for a member and not a role?
So changing Greedy[discord.Member] to Greedy[UserMentionOrID] basically
The question is to whether you want to limit it to only take an ID/mention for a member and not a role?
Basically yeah. Do we wantGreedy[t.Union[UserMentionOrID, discord.Role]]orGreedy[UserMentionOrID]?
If that's the only difference and we're already handling roles then I think we should keep the roles
I really dislike a reminder for an entire role, but maybe it has use for like DevOps or something?
But if this is only a fix then I agree with Zig.
I used a couple of times to ping mods and admins to do something when I knew I might not be available to look into it
if roles also match through names like the members then I think it should also go only through ids/mentions
Is that going to be an issue?
Probably not? Some role could come up though, not sure on all the formats the converter it uses for the expiration accepts
That converter doesn't currently exist so would mean adding it
!src remind
Commands for managing your reminders.
@cold island if we do keep the discord.Role conversion (which I think we will), should we make it only support id/mention like users?
Or do we still want name support?
If you try to do a time like 3d it converts to a user first since it's a bit too greedy
The issue there being the conversion of a plain str to a member
Because it tries to match by name?
mhm
icic
It's just a case of whether we keep using discord.Role (which has name support) or create a custom RoleMentionOrID converter just for this (to prevent the same greediness issue)
So what is easier and still works? lol
If there's a greediness issue then it doesn't seem we want it
But you don't need to support a role mention when creating a reminder
Easier is to just keep using discord.Role and hope there's no greediness issues
Because that would be really silly if we pinged the role while creating the reminder
There isn't a greediness issue with roles afaik, but there could be in the future
So it's whether we want to put the effort into something that may or may not be needed at some point
So the question is whether we might try to remind a user who has the name of a role?
Let's just go with discord.Role for now, the ones who can use role reminders are admins and we don't use names to refer to members in commands
Whether the reminder itself would start with a role name
The 1d becomes a duration, and then you move to the text
It would be !remind {role} {duration} {msg} which I'm guessing is never gonna happen
yeah
!remind test
expiration
!remind [mentions]... <expiration> <content>
Can also use: reminder, reminders, remindme
Commands for managing your reminders.
Subcommands:
!remind delete <id_>
Delete one of your active reminders.
!remind edit
Commands for modifying your current reminders.
!remind list
View a paginated embed of all reminders for your user.
!remind new [mentions]... <expiration> <content>
Set yourself a simple reminder.
Yeah, I think it's absolutely fine to keep using discord.Role
!remind 1d Moderators are still here?
Your reminder will arrive <t:1629757000:R>!
Your reminder will arrive <t:1629757025:R> and will mention 1 other(s)!
!remind delete 2860
That reminder has been deleted successfully!
!remind delete 2861
That reminder has been deleted successfully!
(I'd like to apologise for interrupting your conversation)
Hey I was browsing the decorators (in particular the in_whitelist check) and then found this function: https://github.com/pythondiscord/bot/blob/d375a66e3cd67832f93af29f37ec8d31e3254ef3/bot/utils/checks.py#L43
I might be very well wrong, but in case you define your whitelist context as for example: channel: bot-commands, and role: staff roles
The check will return True just by invoking the command in bot-commands, because it's the first if statement in the code and it'll immediately return with True, while not takin the Role parameter into account. Good example for this: https://github.com/python-discord/bot/blob/d375a66e3cd67832f93af29f37ec8d31e3254ef3/bot/utils/checks.py#L43
where there was an additional check added, besides the decorator. Fortunately I did not find any other examples for this.
(Again I might be very well wrong, but it seems strange for me)
Update: It seems like I can also invoke ping, whereas it seems like it was meant for roles=STAFF_ROLES
bot/utils/checks.py line 43
def in_whitelist_check(```
I'll open an issue and PR for this ๐ @cold island
It's intentional. It should be enough to satisfy just 1 of the whitelisted things
Oh, okay. Makes sense ๐ Totally forgot about the nature of how STAFFs can invoke commands ๐ I would've totally misused it though.
If a function declaration goes over the 120 char limitpy async def remind_group( self, ctx: Context, mentions: Greedy[t.Union[UserMentionOrID, discord.Role]], expiration: Duration, *, content: str ) -> None: is this the correct formatting to get around that?```py
async def remind_group(
self,
ctx: Context,
mentions: Greedy[t.Union[UserMentionOrID, discord.Role]],
expiration: Duration,
*,
content: str
) -> None:
Yes
Or make an alias for that annoration if it would shorten the length enough to avoid chopping the signature
Maybe Greedy[ReminderMention]?
Sure
Where should I define it? Where Mentionable is defined? (towards top of file)
Yes
Actually could be interesting merging those because they both edit the same file (assume it's gonna cause a conflict)
Unless they edit the same line I don't they they will
Ah okay, should be fine then
When one is merged to main, do a local merge with main and the other pr, and test it if you want to
Good morning folks! I will give a virtual cookie to anyone who can please please please review bot#1760. We are in dire needs for this feature, it would help us combat spam bots tremendously. Thank you!
@green oriole is smartconfig still being updated? Wondering, for this: https://github.com/python-discord/sir-lancebot/issues/527#issuecomment-732726288
I currently don't have time for smartconfig. I could try to have a look later this year.
is there a repo for smartconfig?
ye
yea
ye
what's its purpose again?
sounds similar to configurave lol
Configuration, easy override and server generation
@brisk brook going back to our mypy discussion a few days ago, there's a lot of errors. 959 to be precise.
A lot of them are things like where we have Union[int, None] instead of Optional[int] or where we have a Union[discord.Member, discord.User] then do .joined_at or something (when it's discord.User will error) but there's lots of other things too
Not sure how much we really want to fix because I know joe (and probs others too) are rather against the idea of a "clean-up PR" because of the review cost
This is the file if you're interested (has .bash extension since that seems to be the best syntax highlighting)
If you're modifying code and you see something that doesn't make sense I don't mind if you fix it, but otherwise I don't think it's worth the effort
It sourced from me noticing that the typehint for our pagination lines parameter is list[str] but there's multiple (iirc 5) instances where it's not
^^
So Sequence[str] would make more sense
Then Bluenix said about running mypy to see if there's any other easy-fix and do a PR
A kinda "fix annotations" PR
Yeah, if there's any obvious errors similar to the one you want to fix
The first one, I don't see the issue in changing that. The "review cost" of that is net-zero.
The second example probably isn't worth changing.
We're discussing this internally a bit at the moment. An issue we have is with dpy using typehints for converters. This could possibly be helped bot bot#1730 but also we can do two commits, one for non-command typehints, and for command typehints (that way they could be reviewed per-commit instead of the entire PR)
So one review would be just "is this the correct typehint" and the other would be "is this correct and does it convert as expected"
Well I mean I view this PR you're currently making as just uniforming types.
Changing List[X] to Sequence[X] and Union[X, None] to Optional[X] to make it uniform are somewhat trivial changed to review
What do you mean by "Trivial"?
Trivial means easy
Right yeah
Just got to be careful with attrs
E.g. List[x] to Sequence[x] when you have a .append()
Right, but if it's the correct type from the start this shouldn't be a worry
Easy, insignificant change with little consequence
Yeah,
I guess
You're just changing the annotations, not the actual type it returns. So there really will be no runtime disadvantage to making the types more ambiguous
The cases I'm thinking of would be causing an error already
So like if a tuple was passed but there's a .append
That's odd, I just merged main into bot#1731 and now it's failing tests ๐ค
Circular imports ^^
Ah right, sorry Numerlor ๐ฆ
Merged main into your PR before I was about to approve and it's causing a bunch of circular imports
Youโre just imagining things
xith how about we add support for both, like if the bot doesn't side quackstack api env var then it would generate the ducks itself?
I think we should just have the package so it requires less future maintenance/setup
wait when did lance get redis
am I dumb how long has this been here
very long
heck
I'd argue a public API has less maintenance than a local package, regarding upgrades
unless we're planning to make breaking changes to the public API, which I don't think we should
yeah he didn't know that earlier cuz of me/or got confused
i totally forgot quackstack has public api
What I meant was the quackstack running alongside the bot, that would probably require maintenance. A public API would probably be the least of all 3.
quack.quack.jb3.dev
lol jb3.com isn't even the right url for the meme
lol
it's jb3.dev 
welp
I'm done with going through all the issues in sir lance
I've distracted myself from my classes for long enough, I shall now go poof
yes
goto /docs
my proposals for quackstack btw:
- drop the idea of a pypi package, it just is going to end up being a pain to maintain
- use the api, make it use s3 for storage
cc @fervent sage for thoughts on it, but imo at least the best way to get this onto lance is to use the API, if we want to do a CLI down the line we can write a CLI that calls out to our public instance
This is now fixed ๐
!remind 3D maybe look into the viability of switching to poetry
Your reminder will arrive on <t:1629973625:F>!
!remind delete 2867
That reminder has been deleted successfully!
Yeah, I agree
okay solid, cc @vocal wolf @vale ibex @short snow we're not going to proceed with packaging quackstack for now
we'll build it as an API, if we want to add a CLI at a later time it will just call our API
sounds good
okay repo issues updated accordingly
@patent pivot i'd like to point out that https://github.com/python-discord/quackstack/pull/52 was also a massive code cleanup and general refactor to make it better, not just packaging
cause it was weirdโข๏ธ in structure
oo, might still be worth merging in that case okay
also it would be nice to have a package anyway just not for lance kek
then again for a cli i can just shove api requests at what we already have
if we host a public API there is no urgent need for a package
yea
down the line we can but packaging something just makes things hurt for projects getting off the ground like this
we can totally throw a CLI/api wrapper to pypi that just calls our API or allows you to point it at your own instance
I'll reopen that PR and it can be updated to align with the fact that we're not shipping a package short term
yup
pain
git cli thinks everything is fine, github thinks there are merge conflicts
lol
why are github's instructions "git push origin main"
that doesnt help me resolve the conflicts for a pr
ok it should be good to go, I tested it yonks ago when I first made it and the api still works exactly the same, just cleaned up the indentation issue and merge conflict now
alright ๐
bump :D
this is not related directly to PyDis, but it is related to open source.
let's say I want to fix a small issue in the docs of a project. in that case, should i open an issue first or should i open an issue and a pr at the same time?
Depends on the policies of the project youโre contributing to. Here for instance, we adopt a โdonโt PR until you get approvalโ, so you donโt waste your time, and that of reviewers if the changes you made arenโt desired
got it, thanks!
I'm adding a quick-fix to the !user command so that the name get's escaped. Not quite sure where to put the escape_markdown but think it's best to just do it at the end?```py
name = str(user)
if on_server and user.nick:
name = f"{user.nick} ({name})"
if user.public_flags.verified_bot:
name += f" {constants.Emojis.verified_bot}"
elif user.bot:
name += f" {constants.Emojis.bot}"
name = escape_markdown(name)```
Perhaps before adding the emojis actually
We don't want to be escaping the emojis, yeah
name = str(user)
if on_server and user.nick:
name = f"{user.nick} ({name})"
name = escape_markdown(name)
if user.public_flags.verified_bot:
name += f" {constants.Emojis.verified_bot}"
elif user.bot:
name += f" {constants.Emojis.bot}"
```like this?
Yep, this looks good
woops forgot the bot had tests ๐ณ
fwiw you could have left the auto merge, it wouldn't have merged until tests are passing
@vale ibex Were you planning anything with the merge on the converter typehint pr or can I overwrite it
I don't think he was planning anything
Nah, I went to approve it earlier so merged in main, but it caused some issues with the tests
I posted here about it, but I suppose I should have said on the PR too
@brisk brook do you have any remaining concerns about bot#1760 or can it be merged?
I'll take another look and approve if it looks good
@green oriole wait wait
@vocal wolf Sorry for the ping but I'm InvisibleOS on GitHub
I initially opened this issue (coin flip command) thinking that it would be a simple command (just how I coded it on my bot during those days) but then I was introduced to more complex types of things in Lancebot's code and the PR would need to be made according to Sir-LanceBot's coding style, which I currently am not aware of.
And since I have had a pretty busy schedule for the past few months and will also be having the same at least until October, I cannot guarantee that I will be able to create the command in the specific style (However, if I'm given more time until October or so then I can create it for sure).
That is why I would like someone else to do it for now - I have changed it on GitHub as well.
Once again, sorry for the delay in response.
bot/utils/message_cache.py lines 57 to 58
self._end = (self._end - 1) % self.maxlen
del self._message_id_mapping[self._messages[self._end].id]```
`bot/utils/message_cache.py` lines 47 to 48
```py
del self._message_id_mapping[self._messages[self._start].id]
self._start = (self._start + 1) % self.maxlen```
Do you want to change that or should I just approve?
It's on purpose. I need the old value of _start in the second del
And the new value of _end in the first one
Hmm I guess it would look nicer if I used pop on the dict
np, thanks for the response.
Although I don't need the value of the pop so I guess it's fine
Ah I see, mostly wanted to point it out in-case it wasn't. Because then someone would think it is on purpose, but since it is that's great!
If it looks better then that doesn't matter if you use the value. But I'll go ahead and approve it
class CoinSide(Converter):
HEADS: t.Tuple[str] = ("h", "head", "heads")
TAILS: t.Tuple[str] = ("t", "tail", "tails")
async def convert(ctx: Context, side: str) -> str:
if side in CoinSide.HEADS:
return "heads"
elif side in CoinSide.TAILS:
return "tails"
else:
raise BadArgument(f"{side!r} is not a valid coin side.")
@commands.command(name="coinflip", aliases=("flip", "coin", "cf"))
async def coinflip_command(self, ctx: Context, side: Optional[CoinSide]) -> None:
flipped_side = random.choice(["heads", "tails"])
if not side:
flipped_side = random.choice(["heads", "tails"])
await ctx.send(f"Flipped {flipped_side}!")
return
if side == flipped_side:
await ctx.send(f"Yay! It was {flipped_side}.")
else:
await ctx.send(f"Oh no! It was {flipped_side}.")```out of interest, is this the sort of thing you envisioned for the coin flip command?
(The example you sent is no longer accessible since the paste expired)
Yeah, it was something similar, let me send you the enhanced version of the code
@commands.command(aliases = ["toss", "coinflip"])
@commands.cooldown(1, 3, commands.BucketType.member)
async def flip(self, ctx, user_choice = None):
result = random.choice(["Heads", "Tails"])
if user_choice is None:
# embed = discord.Embed(description = result, color = 0x7289da)
await ctx.send(result)
else:
# embed = discord.Embed(description = "Flipping a coin...", color = 0x7289da)
message = await ctx.send("Flipping a coin")
await asyncio.sleep(.5)
if user_choice == "heads":
if result == "Heads":
# embed = discord.Embed(description = f"The coin flipped **{result}**\n{ctx.author.mention} won the toss!", color = 0x7289da)
await message.edit(content=f"The coin flipped **{result}**\n{ctx.author.mention} won the toss!")
elif result == "Tails":
# embed = discord.Embed(description = f"The coin flipped **{result}**\n{ctx.author.mention} lost the toss!", color = 0x7289da)
await message.edit(content=f"The coin flipped **{result}**\n{ctx.author.mention} lost the toss!")
elif user_choice == "tails":
if result == "Heads":
# embed = discord.Embed(description = f"The coin flipped **{result}**\n{ctx.author.mention} lost the toss!", color = 0x7289da)
await message.edit(content=f"The coin flipped **{result}**\n{ctx.author.mention} lost the toss!")
elif result == "Tails":
# embed = discord.Embed(description = f"The coin flipped **{result}**\n{ctx.author.mention} won the toss!", color = 0x7289da)
await message.edit(content=f"The coin flipped **{result}**\n{ctx.author.mention} won the toss!")
else:
embed = discord.Embed(description = "Invalid argument", color = 0xf35353)
await ctx.send(embed=embed, delete_after = 5)
```Yeah, this was really simple
It can be made shorter I think
And the embeds can be changed into messages
elpmaxe
.uwu example
exampwe
ExAMpLe
Yeah, even the rps command is not an embed
.rps
Your input was invalid: move is a required argument that is missing.
Usage:.rps <move>
.rps rock
@static canyon You and Sir Lancebot played rock, it's a tie.
right yeah
I think embed would look nicer personally but I guess there's some convention or something against using embeds?
Not sure but to be on the safer side, I think it can be converted into a message
I prefer the custom-converter version of the side argument but am interested in what other people think ^^
Even I would go with that if it makes the code more efficient. I just have a pretty basic version of it which works decently. It can still be made shorter and/or efficient.
@left flume Which of these sets of messages do you prefer?```py
if side == flipped_side:
await ctx.send(f"Yay {ctx.author.mention}! It was {flipped_side}.")
else:
await ctx.send(f"Oh no {ctx.author.mention}! It was {flipped_side}.")
message = f"{ctx.author.mention} The coin flipped **{flipped_side}**. "
if side == flipped_side:
message += "You guessed correctly! Congrats!"
else:
message += "You guessed incorrectly. Better luck next time!"
await ctx.send(message)```
Considering that both do the same thing, I'd go with any
It's just what message you think sounds/looks better
oh if youre talking about the message then...
yeah
let me think
The actual message
The second one as it sounds more formal and clear, I suppose
why not emoji first?
!remind 1h this
Your reminder will arrive on <t:1629749927:F>!
I did run this before and we were pretty alright, but I don't have the output on hand, so I'll run it again
It's worth noting we're not trying to hoard NSA data, lol, so not all of the points are entirely relevant
For getting @dusky shore to send a message like one of these two should I make the emojis a constant or just put the code directly?
constant at the top of the file at minimum
if someone has to work on the file tho they won't have the emojis which is the only reason why I can see using constants.py
What do you mean?
I'd do likepy LEMON_HYPERPLEASED = "" LEMON_PENSIVE = ""
I suppose I might as well put it in constants.py?
Unless stuff there is reserved for some reason
oh
this
just remembered that lance doesn't have a configuration system except for constants.py lol
top of the file you're working on, IMO
Okay
And should I add this coinflip command to an existing cog (e.g. bot.exts.evergreen.fun.Fun) or create a new one (bot.exts.evergreen.coinflip.CoinFlip)?
I suppose a new file since I'm creating another class
Yeah, I think that makes the most sense
Um
@vocal wolf
Hey
I just saw this message
But I didnโt respond to it in time
Is there a chance where I can still try?
Don't see why not if nobody started working on it
Yup, if nobody claimed it you can get back to it!
import random
from typing import Optional, Tuple
from discord.ext import commands
from bot.bot import Bot
LEMON_HYPERPLEASED = ""
LEMON_PENSIVE = ""
class CoinSide(commands.Converter):
HEADS: Tuple[str] = ("h", "head", "heads")
TAILS: Tuple[str] = ("t", "tail", "tails")
async def convert(self, ctx: commands.Context, side: str) -> str:
if side in CoinSide.HEADS:
return "heads"
elif side in CoinSide.TAILS:
return "tails"
else:
raise commands.BadArgument(f"{side!r} is not a valid coin side.")
class CoinFlip(commands.Cog):
"""Cog for the CoinFlip command."""
@commands.command(name="coinflip", aliases=("flip", "coin", "cf"))
async def coinflip_command(self, ctx: commands.Context, side: Optional[CoinSide]) -> None:
"""
Flips a coin.
If `coin_side` is provided will state whether you guessed the side correctly.
"""
flipped_side = random.choice(["heads", "tails"])
if not side:
flipped_side = random.choice(["heads", "tails"])
await ctx.send(f"{ctx.author.mention} Flipped **{flipped_side}**!")
return
message = f"{ctx.author.mention} Flipped **{flipped_side}**. "
if side == flipped_side:
message += f"You guessed correctly! {LEMON_HYPERPLEASED}"
else:
message += f"You guessed incorrectly. {LEMON_PENSIVE}"
await ctx.send(message)
def setup(bot: Bot) -> None:
"""Loads the coinflip cog."""
bot.add_cog(CoinFlip())
```does this look good? @left flume @fallen patrol
@clever wraith which issue is this?
one sec
730 i believe
sir-lancebot#730
yeap
I've re-assigned you to this issue, you can now work on it
Yeah, btw the code I use uses an API
But i believe itโs free
I havenโt touched the code since may lol
Looks like the issue shouldn't necessarily need an API, unless it's just to get a random word rather than using a word list file, which I guess is fine
Although actually I'm not sure how that would work... would have to see the usage
Here's your reminder: this
[Jump back to when you created the reminder](#dev-contrib message)
oh god my code is so spaghetti
jesus
it is currently at 120 ish lines
holy moly
How do I create a pull request from git? My understanding is I need to do something like hub pull-request -m "Create CoinFlip command" -m "Closes #612" -m "Adds a coinflip command to the bot." -a TizzySaurus -l "type: feature" but hub comes up as an unrecognised command
I'd recommend using gh now, but those two are github specific tools, you need to install them separately
Remember, pull requests aren't really a Git construct
GitHub Desktop should allow you to open a pull request, though I think that just opens a tab on your browser
Additional information related to our contributing guidelines.
Precommit hooks, stuff that run before you commit
Stuff like linters and tests, in this case Akarys is claiming that either of the two failed. It would've been caught by these
Ah right yeah
It will run flake8 before committing, making sure you get no failed lint, yep
I did know I was missing the docstrings but apparently forgot to add anyway
How do I undo a local commit again?
You made a commit that you haven't pushed, and would like to undo it but keep the changes?
how does this look for issue 730?
yeah
extremely spaghetti code - 140 lines
I made a commit fixing the docstrings that didn't completely fix the docstrings
dont h8 pls it was from may
git revert HEAD~1 iirc
All I can do is recommend GitHub Desktop haha ๐
just amend it
That sounds correct, the only command I got in my head was git reset but that would not keep the changes.
Reset will keep changes unless the hard flag is passed
Without --hard it keeps them
That's soft reset, not mixed
I am sure you've grown a bit as a programmer since, see if you can design it differently. Otherwise clean it up and submit a pull request, the way you've done it may be the only way.
Ah right, I see now @green oriole @cold island
yea i am gonna see if i can rewrite it
The amend flag is perfect for fixing lint errors though
mixed doesn't modify your files
git commit -a --amend --no-edit is my favorite
Hmm
Couldn't get it to work so just added another commit
If I really wanted to I could squash them but like can't be bothered
git revert is ussed to create a commit to revert others
Soft: delete commit, keep staged, keep changes
Mixed: delete commit, unstage, keep changes
Hard: nuke everything
Ah right, so it's reset
Revert will apply the invert of a commit, yeah
amends and fixups should be enough for most things like this
Eh I decided to squash in the end lol
I have been wondering about merge commits, would it be fine to add code to fix errors introduced from the merge in them, or should those be commited separately?
For example in https://github.com/python-discord/bot/pull/1731 the be9bc9c commit fixes an error introduced by the previous merge commit, would it be okay to do that in the merge?
I think so, I do that from time to time. I try to always have working commits, in case of a future bisect.
@clever wraith
how the united states national security agency views our kubernetes cluster
lmfao
I'll go through these at some point and correct, a lot of them are fairly trivial
immutable fs is fun
NSA has joined the chat (probably)
I mean they are already in every chat
yea this is doable on a lot of svcs
Merge commits include fixes to merge conflicts, so I think fixing less obvious issues which arise from the merge is fine too
sir-lancebot#814 also needs reviews please
heck yes, that should be allowed in every channel
thank god
Anyone want to check out Sir-Lancebot#805 ?
Looks great!
If it doesn't work, try with the full link
If the bot restarted, using only the ID won't work
Anything that takes messages will also work with links, glad it worked!
Yea, message IDs aren't enough to specifiy an exact message. You need a channel ID & message ID. If you supply just a message ID, we assume you are referring to a message in the current channel
You can either use a full link, or do channelID-messageID
IE 635950537262759947-879652841806004255
We don't have a set list of things that we approve or don't. It's more of a feeling of if something is suitable for our server
discord/ext/commands/converter.py lines 373 to 386
class MessageConverter(IDConverter[discord.Message]):
"""Converts to a :class:`โdiscord.Message`โ.
.. versionadded:: 1.1
The lookup strategy is as follows (in order):
1. Lookup by "{channel ID}-{message ID}" (retrieved by shift-clicking on "Copy ID")
2. Lookup by message ID (the message **must** be in the context channel)
3. Lookup by message URL
.. versionchanged:: 1.5
Raise :exc:`โ.ChannelNotFound`โ, :exc:`โ.MessageNotFound`โ or :exc:`โ.ChannelNotReadable`โ instead of generic :exc:`โ.BadArgument`โ
"""```
most stuff is default tbh
and control plane stuff is managed by Linode
eh, doubtful
kubeadm and k3s and whatnot have very sane defaults
A lot of the checks on control plane are things you need to explicitly configure to be unsafe, the defaults assume the most safety
I'd certainly view the default settings but Kubelet configuration can be hundreds of lines, and if you just keep defaults it's not worth overriding
What are the benefits of adding mypy to the CI?
less bugs for reviewers to take care of? Although I think more time will be spent on making the checker happy than what'll be gained
...and then the only solution will turn out to be slapping Any on half the things
I like static typing, but it always disappoints me
I disagree, it's also much clearer to work with and understand.
Because now you have a clear view of what a function takes and return, without reading the code or doc-string for quirks.
We don't need to run it on strict, bit just the normal one with errors could be good. As @static canyon has explored though, the codebase has a lot of these errors already
A lot of said errors are easy fixes though. Things like making t.List[str] into a t.Sequence[str] etc.
Some are even just making t.Union[x, None] into t.Optional[x]
#dev-announcements message , this is meant for people hosting snekbox themselves right?
This isn't snekbox, this is directly inside @stable mountain
Oh
Admins+ have the ability to exec code directly on the python instance using !internal eval
So this change means that if you share a testing server with someone else, they can't exec code on your computer by default
had the ability right?
No, we still have
There's now an env var BOT_DEBUG that is True by default
which disables internal eval to only the bot owner
we have that disabled in prod though
The python bot?
if so, then yea, it's here https://pythondiscord.com/pages/guides/pydis-guides/contributing/bot/
A guide to setting up and configuring Bot.
Oh thank you very much!
If an import is too long, how do I make it compliant to the 120 chars?py from bot.constants import Guild, Icons, MODERATION_ROLES, POSITIVE_REPLIES, Roles, STAFF_PARTNERS_COMMUNITY_ROLES, STAFF_ROLES
warp in parentheses and import the names on individual lines
from bot.constants import (
Guild,
Icons,
MODERATION_ROLES,
POSITIVE_REPLIES,
ROLES,
STAFF_PARTNERS_COMMUNITY_ROLES,
STAFF_ROLES
)```like this?
Usually isort goes with ```py
from bot.constants import (
Guild, Icons, MODERATION_ROLES, POSITIVE_REPLIES,
ROLES, STAFF_PARTNERS_COMMUNITY_ROLES, STAFF_ROLES
)
Unless you've changed it
It seems we do this normally though so I'll go with it
Thanks ๐
Any ideas how to shorten this to 120 chars (currently 136)?py # If the user is not staff, partner or part of the python community, we need to verify whether or not to make a reminder at all.
put a line break after community 
# If the user is not staff, partner or part of the python community,
# we need to verify whether or not to make a reminder at all.```so like this?
I've also got an issue with a docstring which is too long to be on one line but when I put it on its own line (separate from quotes) I get a lint error saying it should be on the same line (One-line docstring should fit on one line with quotes)
Tried adding a blankline after before ending quotes but that didn't work
This version is over 120 charspy """Lists all users who aren't staff, partners or members of the python community and have permission to stream."""and this gives error saying it should be on a single line (which makes it >120 chars)py """ Lists all users who aren't staff, partners or members of the python community and have permission to stream. """
Right, I guess we need a smaller docstring then
"""Lists all users who aren't staff, partners or members of the python community and have stream permissions."""
Exactly 120
Really Tizzy, please install precommit
I have no clue how
I'm able to do poetry run task lint but just keep forgetting to
(bot-6mLjCNeK-py3.9) C:\Users\tizzy\bot>poetry run task precommit
pre-commit installed at .git\hooks\pre-commit
yup that's it
So now whenever I commit it'll automatically run the task?
now, when you try to commit, it'll run the linting against the staged files
yup
Nice ๐
sometimes it'll even fix them for you
Wait what
The linting passes locally but failed on github
Nvm, it's because I did a merge
I think it's all good now ๐ค
Eh fuck
It broke the tests
No clue how to fix them
I think it's because the decorators use constants.STAFF_PARTNERS_COMMUNITY_ROLES but that's not defined in the test?
Yeah, I think so
I'll try and fix locally
Eh, I have no clue what I'm doing lol @vale ibex
@unittest.mock.patch("bot.exts.info.information.Information.create_user_embed")
async def test_staff_members_can_bypass_channel_restriction(self, create_embed, constants):
"""Staff members should be able to bypass the bot-commands channel restriction."""
constants.STAFF_ROLES = [self.moderator_role.id]
ctx = helpers.MockContext(author=self.moderator, channel=helpers.MockTextChannel(id=200))
await self.cog.user_info(self.cog, ctx)
create_embed.assert_called_once_with(ctx, self.moderator)
ctx.send.assert_called_once()
```this is one of the tests that I need to fix/update
It's staff and partners+python community members that can bypass so I suppose it should be updated to test all three?
The problem is coming from that fact that this test is overwriting constants.STAFF_ROLES to a set ID
but, we don't use that for the whitelist check anymore, and updating the constant there, doesn't also update the new constant
So the fix for this test would be to update the constant on the first line to the new one
๐ค
So... I guess constants.STAFF_PARTNERS_COMMUNITY_ROLE = [self.moderator_role.id]?
yup
There may be more tests that fail like this too
So you probably want to run poetry run task test before commiting
so you can get all the failures in one commit
Yeah there's 1 more
Have done ๐
Nice ๐
All works ๐
8 warnings but I'm assuming we don't care about those
Pushing ๐ค
Nice ๐
Hey! I know it's a fairly old issue, but I believe it's still relevant.
Could someone take a look at bot#1348 ?
ehhh, I'm not sure how I feel about this in general
I'm not sure what problem it's trying to solve
Generalising embed creation.
Like, sometimes we create embeds like
embed = Embed(title=random.choice(NEGATIVE_REPLIES), colour=Colours.soft_red)
Sometimes we use functions like:
def _get_error_embed(self, title: str, body: str) -> Embed:
"""Return an embed that contains the exception."""
return Embed(
title=title,
colour=Colours.soft_red,
description=body
)
That would make it way more convenient.
(Not sure why syntax highlighting is not working, I'm sorry :/ )
We already do this at times, when it's necessary
Do what, precisely?
Have a helper function
Yes, indeed. But that would generalise it, and you wouldn't have to define functions all around the code to make it easier to create an embed.
How exactly?
Well, I have an idea based on the previous discussions in that issue. It's explained there in depth. (bot#1348)
(I'd call it a suggestion, rather than an idea ๐ )
I don't think something as trivial as changing the colour needs to have a helper function
If there is a more complex set of operations that consistently need to be performed, then that's a good candidate
As mentioned in the issue, there would also be an option like allow_delete that would handle reaction based messaged delete.
(With the trash can emoji)
Also, if you want to add other operations along the way, it is as easy as adding it to the helper function this way it can be used everywhere.
Squeezing to much functionality into a single function can make for a clunky, confusing, and/or inflexible interface
As of now, the only functionalities it would have are categories, and handling the deletion of those embeds.
So the category would control the colour, and in the case of errors auto add the title
but for the other categories, it would still accept a title as an arg?
I believe so, yes.
So there, you're trading the import of the negative replies and flexibility, for the import of this helper function
automatically handling the deletion is nice though, having it in a helper function would mean that when we want to migrate to buttons that would be easier
I mean the only thing you did with these negative replies constants is basically chosing one ๐
Yes, right now if you were to do this, you'd have to modify a bunch of methods all around the code.
Keep in mind that the deletion cannot be added without actually sending the embed. It means a channel has to be passed to the function.
Indeed, but that would be handled by this helper function.
(Tbh. I might have made a bad example in the issue, I passed the whole context object as an arg)
yea, and actually when we want to swap to buttons, those aren't part of the embed
so would need to be done in the send itself too
Yes, you'd just pass the view in the send instead of reacting with an emoji and waiting for a reaction.
This would also mean that we need to send the embed within the helper function, which means we lose the option to add fields to it
unless we make this a whole class with a send function
It seems like quite a lot of effort for somewhat minimal gain
Yes, that was my first plan, but I trashed it because it did not seem consistent to have a separate send function.
since we could just make the view creation itself a util
How many instances does the code base have of all of the above
- Only sending 1 embed
- Not sending any messages or attachments with the embed
- Not modifying any of
wait_for_deletion's params besidesmessageanduser_ids
For more flexibility the embed can be created externally passed rather than passing args and having the util construct the embed object. Would also make for a cleaner interface.
when we migrate to d.py 2.0 I can see the use in having a generic delete ui.View, since that will have the same implementation for pretty much everything
Well, in that case it's also a solution to halt the issue until the release of dpy 2.0
I think that would be a separate issue though
to create the deletion button view
I don't think this issue itself is worth it
It was opened back in January, back then I believe dpy 2 was far away! ๐
hah yea
I guess, this issue can be closed, then? ๐
Yea I could be, unless other core devs are highly in favour of it
bot#1348?
I'd close it, yes
I agree with your comment, I don't see what it is trying to solve
yea, having generic ui.Views will be really useful when 2.0 comes
Ah yeah obviously I don't know anything about the 2.0 api
they're how you add buttons and drop downs
and define what happens when you click them
it's a new kwarg on .send() calls
So you make a thing, add it to the thing, and that gives you a thing you can send to the thing to have a thing you can click to do thingy things?
Is that a good abstract?
!paste
Pasting large amounts of code
If your code is too long to fit in a codeblock in discord, you can paste your code here:
https://paste.pydis.com/
After pasting your code, save it by clicking the floppy disk icon in the top right, or by typing ctrl + S. After doing that, the URL should change. Copy the URL and post it here so others can see it.
this is how I do the email thingy for the appeal
then I just do ctx.send("some message", view=ConfirmAppealResponse())
the init and stop methods are just so I could have more control
they're not needed
This manual lock interaction makes me go really sadge
I'm not even sure it is needed
I should really actually test it
We solve this in arthur by only allowing the author to click buttons afaik
but since I wanted anyone with access to click, I added this
didn't see any controls in d.py itself
Actually, i've simplified it, after reading me own code ๐ https://paste.pythondiscord.com/cofoguvaso.py
Wait I thought the dev-voice channel was locked before... just curious why it is unlocked now?
it was locked a while back
I think there was no reason for it to be locked, so it became unlocked
Oh ok, I see
Yea, but only contribs+ have speak perms
ye
Ohhh
that too
Joe unlocked it for the stream only afaik
we may never know
๐ฅฒ
Wait what is this stream about? Sorry I can't really join rn to listen and I just found out. Maybe I missed an announcement or smth
Joe is securing containers / pods in the Kubernetes cluster according to security guidelines created by the Kubernetes operators at NSA
Oh, I see
like read-only root filesystem, restricting access permissions
You can probably find the product of it in https://github.com/python-discord/kubernetes once he's done
Cool, thanks
Can I stay? ๐
I think some of the builtin docs are missing from @stable mountain , e.g. list.index, tuple.index
I believe this is a consequence of how Python organises their documentation.
These functions are not directly attributed to the list type. Instead they're documented under a more generic "mutable sequence" type which I don't think has an actual symbol.
Oh god
@patent pivot why use Redis ??
"it's webscale"
It's not the only one that "webscale" isn't it ??
i am the messenger, please interview @patent pivot
@patent pivot God night redis or good night redis ??
Also good and god night all
json is the only viable database /s
JSON IS THE BEST DATABASE FIGHT ME
Thank you! Bye!
lol, immutable fs & non-root is something I've wanted to do for a long while, this just reminded me
me, not noticing Chris had fucking automerge enabled: 
rip
Please leave it really isn't
Is bot#1382 still something we want? I don't think it was ever formally approved
I'm also not sure as to how exactly it would be implemented, since it's a tag and so content is hard-coded in a file
Could perhaps add a placeholder which we do str.format on but that seems untidy
it's a method of deploying and managing your applications, centered around containers
Itโs also only important in like py-gen, so itโs never been a problem I encountered, so maybe Iโm not the best judge
D.py too I assume
under the hood it uses something like docker but manifests like in https://GitHub.com/python-discord/kubernetes to deploy stuff
!paste
Kubernetes is the tool and platform, the above paper is on ensuring your usage is secure
(The message the bot sends would have a ping for you)
The idea was to make it clear who the message is for, within the message
And since embeds don't actually ping the user you don't have an issue of double pings
Yeah
I donโt like the idea, for the reasons I mentioned above. From an execution standpoint, it isnโt too difficult to inject to the beginning or end of the content
If people are against it then perhaps it should be closed
Keep in mind we want the ping in the embed, not the message.content so we'd have to edit how we read the files to inject it
Yeah, I got that. You donโt need to change anything
Just add a new line embed.content = embed.content + ping
If itโs immutable, clone it
Just basically people discussing here and on the issue
The things that are discussed are along the lines of:
- do we want this feature?
- will it cost too much?
- is it possible to technically implement
Well, sort of. One person is all thatโs needed to close something, we donโt have a set limit.
So far, no one has abused that power, so it remains the system.
I still don't see what https://github.com/python-discord/bot/issues/1382 is trying to solve
is
!paste Hey at-Scaleios, please use a paste for longer snippet
Pasting large amounts of code
If your code is too long to fit in a codeblock in discord, you can paste your code here:
https://paste.pydis.com/
After pasting your code, save it by clicking the floppy disk icon in the top right, or by typing ctrl + S. After doing that, the URL should change. Copy the URL and post it here so others can see it.
not enough?
Right yeah true. I forgot that was a thing
The idea is that the other people may see the embed and wonder who it was targetted at I think
In #python-discussion it can end up being 5-10 messages below at peak times
That seems to be an exaggeration actually
Should we use tags in pygen at peak times though?
because if it scrolls that fast, it doesn't seem like we want to
If they're still relevant then why not?
It's also public members doing it a lot of the time, and we can't exactly restrict that without restricting tags from #python-discussion to staff+ (and partners/py community I guess)
I think we should always use tags when they're relevant. Just need to be aware of the fact we may have to redirect people to a help channel/ot temporarily etc. if it really is too busy
why not just reply to the context message?
That was conceptualised and I think that could be a solution but it didn't go anywhere
And !paste @user would reply to the author not user
Suppose that's not a big deal though
Could probably even make it so that all tags reply to the invocation
Don't really see the harm in it
But then is it really needed?
In most cases it will be useless echo though
Yeah
I don't really think it's worth it to be honest
Nor do I think bot#1382 is really worth it
As a future idea, it might be also a solution (maybe a wrong one), that when you invoke a command like paste and a mention it'll send the mentioned user an embed with the title (eg.: "Pasting large amounts of code") and a button like Show more that'll reply with the full content in an ephemeral message.
But, that's still far away ๐
Yea that does sounds pretty nice
There's a whole bunch of new features we can make use of in Discord now, I think we mostly need to spend some time playing with them and I'm sure we'll think of loads of improvements we can make
Some easy ones are replacing emoji interactions with buttons
Is there any official statement when dpy. v2 might be released?
(This morning they released a changelog of a lot of changes that'd been made)
nope, no official release date
it's fairly stable now though and most of the things they wanted are in
There's still quite a few in To do here though https://github.com/Rapptz/discord.py/projects/3
We're using 2.0 in @brisk belfry and @radiant merlin right now, and it's working fairly well
But I believe you'll wait to implement it in @stable mountain , until it's officially stable.
Yup, that's the plan
I've been writing @brisk belfry in a way that the cogs can be dropped into Python with minimal changes
Oh, I see.
Though, it's quite hard to maintain a bot in production when..
- Message.start_thread was renamed to Message.create_thread
- TextChannel.start_thread was renamed to TextChannel.create_thread
๐
yea lol, I stumbled into that
I meanโฆ I presume most sane places lock versions. This is only a prod problem if youโve got real bad practices ๐คก
yea, that burn made me then lock the revision lol
Oh this wasnโt a dig at threadbot, I didnโt know lol
it should have been lol, I spent like30 minutes trying to figure out why it broke
Oh man, thatโs not fun
Hey @green oriole can we use a pipe in the env vars so we donโt need backslashes after every line?
Well then
Nvm
apparently you don't even need backslashes?
Not sure
Sadge it has to go through Poetry install every time
hmf
Seems aliases are not fully fully handled
Still better than nothing
Or what
I donโt acc understand
no I think the problem are the spaces between the ;
Yep
That's dumb
Yep, that's it. I am sending an upstream PR.
Does the pipe fix this
It does not
Youโre Italian, how could you have not tried the pipe
In YAML you have to convert the line breaks to space or keep line breaks, you can't have nothing
Bleh, no rush on the PR
btw @green oriole pls approve https://github.com/python-discord/site/pull/565 so it can be morged
yes sir
Ah I was about to say you could dismiss my review but you also need a core dev review
If anyone here doesn't know where that button, since it is pretty much hidden, it is right there
It allows you to basically void the review and pretend it never existed
Quite useful, even if the embed generated by the webhook sucks
Why? If you'd approve it again that would just override the Requested Changes review?
Yep, but imagine I wasn't around and the requirements were met, only my stale requested changes blocked the merge. Wookie could have dismissed my review since the changes have been applied, and merge.
ah nice, didn't know about that
Ooooh
I also dismiss reviews if someone approved, but there have been significant changes since then
Petition to auto dismiss reviews and make everyone suffer
I pretty sure we looked into doing that before
no 
I think we have (or had) it on forms
Hey! Any thoughts on this? site#369 it still seems to persist, and the migration to FastAPI is still far away. ๐
is this the place to put server related suggestions?
For general server suggestions #community-meta or even better create an issue on https://github.com/python-discord/meta/issues
If it's for a project-specific suggestion then create an issue on the relevant project or comment here
Suggestions for bots here, general server suggestions in #community-meta. There's also the GitHub page that mark just linked for general server suggestions
cheers
@patent pivot can you push your templates to meta?
yep yep, will put them there now
I think they are decent and we can refine them as we go, but anything is better than what we currently have
where did we land on blank issues?
I don't think we landed
hm, personally I'd rather keep them off because we have defined a set of good flows with the templates, but it does break mobile support
ah right, that's better then
I guess I agree. Keep it off
Thanks
yep, already posted it in our dev-ops chat
we'll likely standardise some stuff
notably kubernetes deployments & maybe docker image builds
will probably move to single manifests again too
Are there docs for this. Iโve read the blog post and guide, but those are more general overviews
If there arenโt, anyone know how secrets are handled? Namely, can you have a secret in the action repo that you use in the final repo
Taking a blind guess but I really don't think secrets will be copied. We have all of our secrets as org secrets either way
Did github change its colours?
Where?
The bot will still ban them (you can ban people who aren't in the server)
It didn't just now because I got the id wrong
No
That's not the case for user ids. name#discrim etc. won't work but ids will
Yes
Mhm
Our ban has MemberOrUser since we do extra stuff if they're in the server (such as sending dm)
oooo dev voice
the green colour on approval, then the review file area, the yellow review equest are kinda more darker imo
Yes, it is now open to everyone, but only contributors have speak perms apparently
I see.
are you on the default theme?
default dark
I'd expect that to change the color
.int e print("test")
test
๐
Can I get some reviews on bot#1778 please? Just a small little addition
of course :P
Thank you 
Hey! Any opinions on this issue? bot#1057
It's a fairly simple thing, still quite useful.
What's your thought on this @timid sentinel ?
It wasn't like that before ๐คท
This cog doesn't exist anymore, I've added a comment. Also I meant issue, not project haha
You could probably .split the title and then redact the individual words individually, it could give some weird results (e.g. if the title was ben and jerry it would remove all occurences of the word and), but at least wouldn't give the answer away. It could also be good to replace the words with placeholders of the same length to give a bit of a hint (e.g. hello you would become ***** ***) although I don't mind about that
Yeah, but actually the issue was mostly about handling discord.NotFound errors all around the code (if not handled already) in case something raises one. I guess it was just an example.
Some errors are not worth handling
For instance, theoretically any time we communicate with the discord API, we run into the risk of hitting a 500 error
But that doesnโt mean we should wrap every single api call
Have we hit recent 404 issues, like with applying the muted role?
Just ones that we know are problems
I don't think we want to handle every 404, we surely want to be aware where they can happen and see if it is an expected failure or not
not that I am aware of
Honestly having the global handler block 5xx from generating Sentry issue would be.. nice
Like sending a log?
If the 404 is handled locally it won't be of any issue.
Because if a user leaves while we try to apply the muted role, what happens?
It doesn't apply it, and next time they join it is applied
We run the risk of hitting a genuine discord bug, that we should know of
What I mean is we want to handle them locally, not have a global handler for the whole bot. Isn't that was you were suggesting?
I mean, do we really investigate 5xx issues
not saying that we shouldn't, but we don't do that currently
Do we really get all that many 500s to begin with
Yes, sure. That global handler would serve as an.. "indicator"? It would maybe trigger a sentry error? ๐
Any error already triggers a sentry error
There isnโt anything a global handler can change other than swallow up the error
To go back to the original issue, if itโs no longer relevant, because the code has been removed, we should close it. We shouldnโt add anything extra globally here. If we have 404s in the future, weโll handle them as needed
This is my official medical designer opinion
Well, yes that's a valid point. Nevermind, at least the issue is closed now .
look back at the large major outage and the two thousand events it generated
Not sure what youโre talking about, havenโt been following alerts. Were they not grouped?
You wish
Every execution path creates a new alert
we had roughly 50-100 alerts this day?
Hello
I was trying to run a bot that can use snekbox for an eval command and wanted to know how I could add some external environments to it if it is possible?
i'm using docker compose to run the snekbox and the discord bot
I could probably do that, not the best idea but the only idea lol ๐
https://github.com/python-discord/bot/pull/1785 by this would we also be able to see this?
What is this in your message?
the public URL
example 
Yea, i still don't understand what you were asking
Are you asking if my change means you now have access to metabase?
Yeah, if we can see the query results, from what I remember you need to be logged in to interact with the Metabase, you can't do anything if you are logged in, but then you said, so when you mentioned "sharing link" I thought that was meant for sharing it to us.
Ah, right ok. So yea, metabase has a way for you to open a given question (their term for report) to public, this change is jsut a bug fix so that it uses the right URL
Since only admins have normal access to metabase, not admin access which is needed to share something, we use this command as a way for admins to share reports with mods during raids, or others if needed
Ohh, could you run an example query?
Nice, you don't get the โจ graphs โจ ?
@severe tangle in what context do you imagine this new tag would be used? bot#1784
Ah, well many people in #discord-bots channel tend to use global variables for their functions, but using bot variables is considered better for discord.py
Ok, so this tag would be used when a user is trying to use a global variable in their code, so we can show them a preferred way?
Yup
Alright, I think we should simplify the tag a lot to focus on that then
or if they want to use a variable across different files, where they can access the bot instance
Ah, thanks for that!
Also, in future, please open an issue before writing a PR
ah ok. sorry, my bad :c
since we can have these discussions before you raise a PR
ohk
Oh right you're in here, so we can discuss it here over IRC
ah, better haha
BTW, would there be really a need to add the name kwarg in the decorator?
Bot variables are a new type of global variables
They're not really global variables, so we shouldn't call them that
I think think tag should be, why global vars are bad, and how to define bot attr vars
ah
everything else is just noise that dissuades users from actually reading it
Uhh, I made some changes to the docstrings of those commands. Other than that, I am at the ends of my knowledge. I don't really think there is anything else which I can change (Though thanks to you for suggesting all those changes)...
What I am specifically looking to change is the first and last messages. We want to explain the following:
- Bots are classes that you can add attributes - no need to explain them, just mention they're like variables
- You can both get and set attributes as you wish
- You can reach these attributes anywhere you have the bot because the attributes are on the bot itself
- They may overwrite discord.py attributes, so be careful
Currently, you're explaining this:
- In ONLY discord.py there's something called bot variables, they're new - you won't find this definition elsewhere so users can't google to learn more
- You can access them anywhere you have your bot instance
- They're better than global variables because they can be accessed anywhere you have the bot
- They can overwrite existing attributes
Oh
To be fair, there's actually nothing wrong with using global x. But using an attribute on the bot is much more swifter agreed
Many people only have their bot in one file, so it makes sense
We should clarify that it's when the bot is over several files that it is the most helpful
But people who are seriously into some advanced bot deving would certainly divide their bots into many files/Cogs. So this tag can become helpful for them.
Oh yeah I am not doubting the tags effectiveness, it will be useful.
Since this tag is discord.py focused, I think it should also say "You can do the same to cogs (self)" or similar
Ah, ok
So I can just start the tag with something like, Bot variable is something, that the library allows us to set, by setting attributes to the existing commands.Bot instance
Ehh, no. I dislike the term "bot variable". It's not called a bot variable, that's not a thing.
Also, it's not like this is something special that discord.py is allowing us to do, it's just attributes
hmm
edited the message (also those are known as Bot Variables in the discord.py server also and I didn't come up with that term myself haha)
Changing discord.py to the library doesn't really help in my opinion, you're still referring to discord.py right?
Sure, that's what you usually call an attribute on the bot class. But in of itself it's not a bot variable, it's an attribute
uhh, I haven't really used any other library, so I cannot say anything about any other lib tbh, so I am just referring to discord.py itself. But changing to the library just makes it more general, imho
yup
You could start it more or less along the lines of
In Python you can set attributes to any class instance, your bot is one such instance. By setting attributes on your bot you can have variables across the whole bot
Ah, so just make it more targeted towards General Python?
Because we want to get the idea across that "Here's a Python thing that's useful, here's how to utilize it in discord.py"
ah
Yes, because then they can apply it past their discord.py bots
yup, understood
lemme do the required changes
Python allows you to set custom attributes to instances and your bot is one such instance. You can add custom attributes to your bot instance and access them **anywhere** you access you bot.
in the next line, I can do something like. In discord.py, these attributes are commonly known as bot variables?
Yeah something like that, just so that users reading the tag understands what people mean when they say that.
(I commited the changes, u can take a look)
Blue since you are active, what do you think the next steps are for Sir-Lancebot#805 ?
Thank you for the reminder, I'll take another quick look
Where's the documentation for this api?
I can understand lol
In an email I got from a Real Python dev, here is the body of it:
๐
Cheers I've got it
I'm just going to reach out to Dan directly to get explicit approval
why so?
slapping an attribute on an object after instantiation and then relying on it being there everywhere seems worse than having a variable in a module that can be imported globally
an alternative approach is to use proper dependency injection, i.e. instead of passing the gorilla and the entire jundge, pass the banana, i.e. things you need (like a cache or a handle to a database pool)
but it surely seems more convenient to just pass the entire bot object everywhere ๐คท
No? The object instance is always from that one singleton where the attribute is created directly after.
When you use an attribute on an object, you rely on __init__() being called to set these. We know, thanks to how Python works, that it will always have happened.
The same way we know that the bot will always have said attribute, notice how test is initialized at first. If it wasn't, and was only set in the command then yes you could have a case where you'd get an AttributeError
Yes this is pretty standard stuff
@dim pelican are you planning on just changing the commit that included those changes, or squash a substantial amount of commits to clean up the history?
Changing the commit that included those changes
Actually, now that I think about, what's the purpose of passing the bot instance to each cog?
There's a circular dependency anyway
I do not think it is the same situation at all. If you have a function that's supposed to take a Bot instance, it's weird to rely on the instance having an attribute that's not part of the type's definition... the correct solution seems to be to subclass Bot to extend the attributes it carries, so that you can reason about it statically
What I recommend you do is to make another commit that removes those changes, and then squash it into the commit that added them. Do you use any visual software like GitHub Desktop or Git Kraken?
I know it works, but I don't know whether there should be a tag incentivising beginners to be solving problems in this way
Not on this current PC, but I will in about an hour. Maybe sooner! brb
For events, you don't get the bot otherwise. It's also actually optional, it has just gotten convention at this point to do so even when you don't use it.
The bot is basically global state anyway
May as well be explicit and transparent about it
but why not access the bot from the place where it's stored as the global singleton?
Discord is real tricky
Python really isn't statically typed by any means, and at the point where members will subclass the bot they will already be adding the attributes inside of their new __init__().
It's better to recommend this, which is very common thing to do, instead of pulling someone into subclassing/super/self/methods. This is just a small step into understanding classes with us explaining attributes
They seem to use a custom JWT format
You mean importing it from the file it was instantiated in?
bot/__init__.py line 25
instance: "Bot" = None # Global Bot instance.```
this thing
That's still somewhat of a work-around no?
around what?
I've never had issues of circular imports the way bot is passed around with discord.py
Circular imports, since it's set to None
I don't think I've seen this used to be honest, at least in the PRs I've reviewed
To avoid circular imports, you just need to use namespaced import, i.e. import module instead of from module import X
since there's a circular dependency anyway, might as well make it explicit ๐คท
I don't understand how this fixes it, I know Python can do things a bit differently, but why would that not cause a circular import?
Can you clarify what you mean by that?
Do you know how Python treas them differently?
Unlike a class, a module object exists before its body is fully executed. You can get a so called "partially initialized module"
For example, if you have a situation like
# a.py
import b
def foo():
print(b.bar)
# b.py
import a
def bar():
print(a.foo)
There's no reason to reject this, because neither of the files needs to access the other module to complete execution.
I understand it's common, yet I don't think that makes it a good solution, especially if both the language and the framework give you tools to solve the problem. Adding an attribute to the instance's namespace post-instantiation doesn't seem to be a good solution ever. If you annotate your cog's init as needing bot: Bot, but internally you rely on bot.test, that's already an unnecessary lie making it more difficult to reason about the program statically, regardless of whether it is statically typed or not, and I don't think beginners should be told that it is a good solution; the tag brings a lot of authority.
it also doesn't play very well with the plans to add mypy to the CI
...this is exactly the situation with cogs -- the code accessing the bot instance is inside a class
In d.py I believe cogs are registered by passing their path as a string
and letting the lib do the importing & dynamic lookup of the setup
Wait... aren't we already subclassing commands.Bot? I don't see what you're saying
Yes, to solve the same problem, we are
but the tag in question is saying to just assign bot.test = "something" and be done with it
despite Bot.test not being a thing you can statically reason about
yeah that sounds terrible
that's the sort of thing people outside of Python say "sounds like Python" to
d.py also does a funny thing where it force-reloads modules when you reload an extension, which can be convenient doing development, but it forces types to be redefined, so insintance and except ErrorType begin magically failing

But- no ๐
No one annotates nothing as needing nothing. This is pretty standard thing to do, hence I would say it's good advice. Python is a dynamically typed language and we're utilizing that. You're not meant to be able to statically reason about anything.
The point where someone needs their bot to pass MyPy or Pyright as well have custom attributes and complex knowledge about classes, they're already knowledgeable in what the tag teaches you.
Because it is Python no?
have you come across a situation where the proposed solution would be good, that wasn't a discord bot?
Yes, FastAPI applications for one
fastapi has request.state right?
Any other case where you're using a library that resolved around a single instance of an object
