#dev-contrib
1 messages ยท Page 1 of 1 (latest)
I'm not sure how/if my changes broke it
or if I'm just misunderstanding how it's supposed to work
!timeit ```py
import time
time.sleep(4)
print("hello")
@vale ibex :warning: Your 3.11 timeit job timed out or ran out of memory.
[No output]
!timeit 0
@brazen charm :white_check_mark: Your 3.11 timeit job has completed with return code 0.
20000000 loops, best of 5: 14.3 nsec per loop
Seems fine? Sleeping 4 sec probably takes too long when it loops
ahhh right, yea ok now I also understand why it fails
ignore me then, it was my misunderstanding of how it worked
Could snekbox differentiate between oom kill and a timeout to make that clearer?
NSJail uses sigkill for both, not sure if we can get the specific reason from nsjail or not
it seems to use the same return code for both
It's possible by parsing the log
Is there a specific reasoning to not being able to use !remind in topic channels or ot?
I'd think the only place you shouldn't be able to use it is the Occupied Help Channels category since the message could be sent when a channel is closed or even worse interrupt someone else's help (and maybe also shouldn't in pygen since it can be so fast moving)
The idea is you can't predict when the messages will appear and under what conditions. The channel could be entirely dead, or it could interrupt an on-going conversation
In that aspect, it's better to run it in a channel where that doesn't matter like #bot-commands
Right, fair enough
Also, how do you do bot-core testing? I'm trying to run it with docker-compose run --build but keep getting file dir issues since the docker-compose.yml is in /dev instead of /
Do I just move the file into /?
No the docker compose is broken right now
Not that it would matter, the image just installs dependencies
We haven't nailed down an official testing method, but I have a bare bones bot which I just keep in the project repo and test features with
You'd need to write some code anyway, so a final solution wouldn't look too different, we'd just ship the boilerplate
That and unittests, but we don't enforce them too tightly right now
What do you mean?
async def clean_text_or_reply(ctx: Context, text: Optional[str] = None) -> Optional[str]:
"""Returns cleaned version of `text`, if given, else referenced message, if found, else `None`."""
clean_content_converter = clean_content(fix_channel_mentions=True)
if text:
return await clean_content_converter.convert(ctx, text)
if (
(replied_message := getattr(ctx.message.reference, "resolved", None)) # message has a cached reference
and isinstance(replied_message, Message) # referenced message hasn't been deleted
):
return await clean_content_converter.convert(ctx, ctx.message.reference.resolved.content)
# No text provided, and either no message was referenced or we can't access the content
return None
```for reference, this is what I'm testing (bot-core#100)
Like we can include something like:
from discord import bot
bot = Bot()
@bot.command()
async ...
bot.run(token)
But beyond that, what you need is entirely dependent on what feature you're testing
So we couldn't really include a way to run that's anything more than this template
Right yeah, fair enough
For your converter, you could use it in a command and make sure it works
If you like, you could also install the project into bot and test there directly
From the bot's venv: pip install /path/to/botcore -e
After that it'll exist and stay up to date with your changes so you can use it in bot
I haven't tested, so I'm not sure if it's compatible with the editable option, or if you need to run install again each time
Cool, thanks
.bm testing bot-core in bot/sir-lancebot
I don't seem to be able to get the bot to start```py
from os import getenv
import discord
from discord.ext.commands import BadArgument, Bot
from dotenv import load_dotenv
from botcore.utils.commands import clean_text_or_reply
bot = Bot(command_prefix='~', intents=discord.Intents.default())
@bot.command()
async def test(ctx, text=None):
cleaned_text = await clean_text_or_reply(ctx, text)
if not cleaned_text:
raise BadArgument("Missing text/reply for parameter `text`")
await ctx.send(f"Here's your cleaned text: `{cleaned_text}`")
load_dotenv()
bot.run(getenv("BOT_TOKEN"))
C:\Users\tizzy\AppData\Local\pypoetry\Cache\virtualenvs\bot-core-vZsMerCK-py3.9\Scripts\python.exe C:/Users/tizzy/bot-core/testbot.py
[2022-07-23 09:07:09] [INFO ] discord.client: logging in using static token
[2022-07-23 09:07:09] [INFO ] discord.gateway: Shard ID None has sent the IDENTIFY payload.
[2022-07-23 09:07:09] [INFO ] discord.gateway: Shard ID None has connected to Gateway (Session ID: 42af6a97863f09ebcdfe93c2fd314770).
```
I get those 3 log messages and that's it
And the command/bot doesn't respond
Lol I was just writing a script which looks identical to this
Ok let's see uhh do you need the message intent for this?
Is that enabled by default
Hmm still doesn't seem to be working
from os import getenv
import discord
from discord.ext.commands import BadArgument, Bot
from dotenv import load_dotenv
from botcore.utils.commands import clean_text_or_reply
intents = discord.Intents.all()
intents.presences = False
bot = Bot(command_prefix='~', intents=intents)
""""@bot.event
async def on_message(message):
print(message.content)
await bot.process_commands(message)
"""
@bot.command()
async def test(ctx, text=None):
cleaned_text = await clean_text_or_reply(ctx, text)
if not cleaned_text:
raise BadArgument("Missing text/reply for parameter `text`")
await ctx.send(f"Here's your cleaned text: `{cleaned_text}`")
load_dotenv()
bot.run(getenv("BOT_TOKEN"))
The on_message runs when I uncomment it so the bot's seeing the message, just not running the command for some reason
Wait I did the wrong prefix ๐คฆ
btw why are we using this as a function instead of a converter?
Because it's not possible to do as a converter
Because of the ctx?
Since text is optional, and a converter parameter cannot be optional
Does typing.Union or optional not work for that?
Nope
You'd have to do something likepy async def test(ctx, text: str = None): await Converter().convert(ctx, text)but we decided at that point to just use a util
I see
bot-core#101, bot#2220 and bot#2031 are all ready for reviews now if anyone's free ๐
@vale ibex why is allowed roles explicitly separated from all the kwargs in the BotBase init? It's just passed to the super init with all the other kwargs anyway, so it seems redundant. It's also mandatory for some reason
Exactly that reason, so that it's mandatory
Alright thanks
Ok I've written some pretty nice boilerplate now for bot-core, I'll push that as a PR
I've written an md file for it, wonder if it can be included in the docs. I think sphinx or one of the hundred extensions does support md
@static canyon we're good to merge now I think. We just need to include some changelog stuff and bump version, would you like to do that?
If you can walk me through that I'll implement
The changelog format is basically ```
- :type:
PR numberDescription
Type and PR number you already have: feature & 101
Description can be anything, it just needs to be descriptive enough to get a general idea of what changed
For instance: Add a utility to get text from message contents or replies
This would go at the very top of the changelog.rst file under the changelog title
Right above it, you'd include a similar entry to this, but with type release. That takes the form ```
- :release:
x.y.z <23rd July 2022>
Where x.y.z is the next version number according to semver
Right, okay
Our current pyproject is on 7.4.0, so the next feature release is 7.5.0
Do I do this under the same branch?
Yeah all in the same PR it's fine
Let me actually check with chris first, since he's claimed 7.4 for a beta
Hmm, let's merge it without a release, then we can cut a release once chris' beta is done
So it would just be the changelog feature
Aight
Thanks
So the only thing I add is```
- :feature:
100Add a utility to clean a string or referenced message's content```?
Ah
Is that good? Just pushed
Hmm actually
Would it be better to make the function take a Message instead of the Context?
Nvm, it needs to have Context for the converter
๐
I can merge it now if you're ready
Yep
If it doesn't see a release soon, feel free to poke me about it
Aight
!remind 1h
Your reminder will arrive on <t:1658587673:F>!
The release is now live: https://bot-core.pythondiscord.com/main/output/botcore.utils.commands.html
!reminder cancel 4841
That reminder has been deleted successfully!
It's going to be live on docs, but you can't install it on botcore since we didn't cut an actual release
(That process would involve the things I mentioned above and adding a git tag)
Let me see what the blocker is on that beta version
the beta is done
7.4.0 released fully
I just never removed the tag
Do we want to get into the habit of forcepushing beta tags away?
we could just leave them
You wouldnโt push it would you? Just a normal push
Anyways it doesnโt matter it doesnโt do any harm
Ah yea, it would just be a git push --delete
only need forcepush to change the commit it references
Sorry, I only review the PRs of people who have 10+ years of experience with bot-core, no exceptions and bot doesn't count
I just disabled the branch protection to push the version bump
And I'll do it again don't you test me
you need to do that to push tags?
Nah but changelog and pyproject
ahhh lol
wait lol
I just rebased a dependabot pr, didn't see you already did the other
Oh it's a race now ๐๏ธ
it's hardly a race if I can cancel your actions
Lmao
Re-request review lol
We're almost at 100 PRs now, wonder how many are dependabot
53
Are we even writing any code lol
winner
The game is rigged
Chris bought off the judges
I was going to unironically rebase the pre-commit PR
I wrote it and locked it, but it completely rewrote the lockfile because poetry can't agree on the order of the dependencies
I probably just need to update poetry
Why did you review, I was rebasing :O
lol
I looked up sphinx tables
Half the results were actual physical tables
The other half were the shittiest imaginable syntax possible
I don't know which one is less helpful
You requested it โ
Nah it's unrelated
My last commit before the push had a typo
I force pushed the typo away
oh lol
Everything before is unchanged
You should know this, you wrote this commit after all
a great web dev
Lmfaoooooo this is
wow ok
Alright I've rebased this and I'll push it but let's not cut a release for it
We'll bundle it with the next feature
Or 3.10
sgtm
Can I get some assistance with implementing this? https://github.com/python-discord/bot/pull/2089#discussion_r811486432
bot#2089
Bluenix suggested continuing it as an ephemeral, but not really sure how to do that
Let me check the code.
https://github.com/python-discord/bot/blob/1ffc3466eaff2e8e35912e928eb7cad94825a3d3/bot/exts/utils/reminders.py#L344:L348
Maybe you should make that one ephemeral?
bot/exts/utils/reminders.py lines 344 to 348
try:
m = await partial_message.reply(
content=f"{additional_mentions}",
embed=embed,
view=snooze_button_view```
Oh, wait. No. The response snooze_button_view sends.
On second thought, I was right.
And how do I do that?
Just ephemeral=True?
Oh, wait. That's a partial message.
Let me think.
Okay, so one thing you could do, is instead of editing the message (the one that the bot sends with using the snippet I sent) you send another message with the Dropdown.
So I change L150 await interaction.response.edit_message(view=snooze_select_view) to instead send a new message?
Yes, to an ephemeral one.
So send_message instead of edit_message?
And maybe after clicking the Snooze button, you could disable the button.
?
Yep, yep.
Isn't that what L157 does?
bot/exts/utils/reminders.py line 157
self.parent_view.reminder_was_snoozed = True```
Errr no
There's a self.parent_view.stop() a couple of lines below this
I forgot my line numbers are different because I've made other changes
Not exactly, it stops "listening" to the view, but the buttons will still be "clickable"
So how do I disable it completely?
So when you click on that you get "Interaction Failed"
- await interaction.response.edit_message(view=snooze_select_view)
+ await interaction.response.send_message(view=snooze_select_view, ephemeral=True)
```This?
I believe so, yes. It'll make the message that contains the dropdown an ephemeral message.
Well, actually a new one.
Now just this ^
And actually, thinking about it, I think this code is in the wrong place. Shouldn't I be stopping it inside the select_snooze_duration()?
At the moment it's stopping when you press the button, not when you snooze (select a duration)
Actually the problem with that, is that you'd have to set the disabled attribute to True which means you'd have to respond with a new view, so I don't thank that's feasible that way, correct me if I'm wrong though.
Hmm
I think you can get away with it if I move it to the select_snooze_duration()
I'll mess around with it, thanks
Yeah, no worries.
Hmm actually this is wrong
It's fine where it is
Because of the .wait()
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/discord/client.py", line 847, in runner
await self.start(token, reconnect=reconnect)
File "/usr/local/lib/python3.9/site-packages/discord/client.py", line 780, in start
await self.login(token)
File "/bot/bot/bot.py", line 258, in login
await self.stats.create_socket()
File "/bot/bot/async_stats.py", line 29, in create_socket
self._transport, _ = await self._loop.create_datagram_endpoint(
File "/usr/local/lib/python3.9/site-packages/discord/client.py", line 110, in __getattr__
raise AttributeError(msg)
AttributeError: loop attribute cannot be accessed in non-async contexts. Consider using either an asynchronous main function and passing it to asyncio.run or using asynchronous initialisation hooks such as Client.setup_hook
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
...
await self.start(token, reconnect=reconnect)
File "/usr/local/lib/python3.9/asyncio/locks.py", line 226, in wait
await fut
RuntimeError: Task <Task pending name='Task-3' coro=<Client.run.<locals>.runner() running at /usr/local/lib/python3.9/site-packages/discord/client.py:847> cb=[_run_until_complete_cb() at /usr/local/lib/python3.9/asyncio/base_events.py:184]> got Future <Future pending> attached to a different loop
ERROR: 1```Any idea why I get this error when doing `docker-compose run bot`? @molten perch
bot/exts/utils/reminders.py line 169
scheduling.create_task(self.reschedule_reminders(), event_loop=self.bot.loop)```
hmmm
Let me give you an example how to resolve this issue.
No, no there is a new async init method for cogs, but I keep forgeting the name
there is a gist on the topic I'm trying to find it lol
ah lol
Okay, I might be totally wrong lol. Haven't gotten used to this change.
That seems to be when you do bot.loop.create_task but we're doing scheduling.create_task here, just referencing bot.loop
The only thing I can think of is moving that line into a async def cog_load
Whiiicch doesn't work lol
async def setup(bot):
await bot.add_cog(MyCog(bot))
add cog is now async.
Did you move the create_task back to init?
AttributeError: loop attribute cannot be accessed in non-async contexts. Consider using either an asynchronous main function and passing it to asyncio.run or using asynchronous initialisation hooks such as Client.setup_hook
During handling of the above exception, another exception occurred:
RuntimeError: Task <Task pending name='Task-3' coro=<Client.run.<locals>.runner() running at /usr/local/lib/python3.9/site-packages/discord/client.py:847> cb=[_run_until_complete_cb() at /usr/local/lib/python3.9/asyncio/base_events.py:184]> got Future <Future pending> attached to a different loop```
Then what goes in the async def cog_load()?
class Reminders(Cog):
"""Provide in-channel reminder functionality."""
def __init__(self, bot: Bot):
self.bot = bot
self.scheduler = Scheduler(self.__class__.__name__)
async def cog_load(self):
scheduling.create_task(self.reschedule_reminders(), event_loop=self.bot.loop)
async def setup(bot: Bot) -> None:
"""Load the Reminders cog."""
await bot.add_cog(Reminders(bot))```is what I've got at the moment
I'm a bit lost
you should rebase onto main, the async cog_load logic is already there
Yeah, yeah. So I was a tiny bit wrong. You can still access self.bot.loop, what I was thinking of is Client.loop
So I don't need to change anything from the original, just rebase?
I can't say you won't need to change anything since I'm not sure what's already in your PR
All I'm saying is that the Reminders cog has already been rewritten to remove the create_task on load
So instead of merge I want rebase?
either will work, depends on what you want your history to look like in the branch
merge will add a merge commit to your branch, with all the changes. Rebasing will move all your commits "up the tree" so it's as if you started (based) your branch from the current version of main
now that's a hotly debated topic ๐
heh
I usually rebase unless another person is already working on the same branch
or if PR comments have already been made
rebasing messes up existing PR comments
They have, so I guess I'll merge
๐
What I'm not sure about, is if your branch was based of the main branch in February, why won't it work with the initial settings ๐ค
Wait I just realised something
this was the wrong thing
I need like git merge main or something
If you do git merge main you should do git fetch before, but just doing git pull is probably easier. (Ofc. with the proper parameters)
But, I'm sure you figured it out, by the time I answered ๐
Actually, no lmao
I instead went down a rabbit hole of ruining my git log
But I'm back now lol
So if I do git pull what are the "proper parameters"?
well, since you're merging git pull origin main
right, okay
You might have to set a "pull strategy"
* branch main -> FETCH_HEAD
error: The following untracked working tree files would be overwritten by merge:
bot/exts/info/resources.py
bot/exts/utils/thread_bumper.py
bot/resources/tags/dashmpip.md
bot/resources/tags/regex.md
bot/resources/tags/type-hint.md
tests/bot/exts/moderation/test_clean.py
Please move or remove them before you merge.
Aborting
What do I do?
@molten perch
I think the easiest solution would be just to re-clone the repo and pull main, up-front.
But, blindly I can't really say anything for sure
That error is saying that the files listed you have got uncommited changes to.
So if you pull, it will overwrite those uncommitted changes
Hmm
So go to my main branch and do this?
wrong reply, meant your command
I can't checkout because there's differences
can't checkout main?
I do not know what IDE you're using or what action causes that.
Are you trying to checkout main?
PyCharm
yes
Alright, then you can stash your changes on that branch and then checkout main
stash?
Yea, run git stash while you're on your branch
that will save your uncomitted changes on that branch to a stash
PS C:\Users\tizzy\bot> git status
On branch add-reminder-snoozing
Your branch is ahead of 'origin/add-reminder-snoozing' by 2 commits.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
bot/exts/info/resources.py
bot/exts/utils/thread_bumper.py
bot/resources/tags/dashmpip.md
bot/resources/tags/regex.md
bot/resources/tags/type-hint.md
tests/bot/exts/moderation/test_clean.py
nothing added to commit but untracked files present (use "git add" to track)
alright, do git stash push -u
what does git status look like now?
PS C:\Users\tizzy\bot> git status
On branch add-reminder-snoozing
Your branch is ahead of 'origin/add-reminder-snoozing' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
PS C:\Users\tizzy\bot> git reset --hard origin/main
HEAD is now at 31110a78 Merge pull request #2220 from python-discord/fix-bot-2168
```done
then checkout this branch, run git stash pop to re-apply the stash and then git merge main to merge in main
PS C:\Users\tizzy\bot> git merge main
error: The following untracked working tree files would be overwritten by merge:
bot/exts/info/resources.py
bot/exts/utils/thread_bumper.py
bot/resources/tags/dashmpip.md
bot/resources/tags/regex.md
bot/resources/tags/type-hint.md
tests/bot/exts/moderation/test_clean.py
Please move or remove them before you merge.
Aborting
lol
I did the pop first
ah alright, stash them again and pop after the merge
Let's see...
Also I have no clue why these are a thing
you can always delete them if you don't need them anymore
aight
git log seems to be a little cursed now but it works
or more likely I'm forgetting how git log ordering works
a merge commit will mean all the commits since you made your commits will be above your commits in the tree
it's orders on commit date
Right, yeah
It's fine then
ERROR: Service "snekbox" was pulled in as a dependency of service "bot" but is not enabled by the active profiles. You may fix this by adding a common profile to "snekbox" and "bot".
A rebase re-writes the commits in your branch to have a new commit date, so they'll be further up
Yea, run docker compose --profile 3.10 up bot
or just docker compose up
I've got a fix for that issue in my PR atm
PS C:\Users\tizzy\bot> docker-compose up
ERROR: Service "snekbox" was pulled in as a dependency of service "bot" but is not enabled by the active profiles. You may fix this by adding a common profile to "snekbox" and "bot".
Yea, you'll need to do the first one then
Things are building
You can remove the bot on the end if you want all logs
Yeah it's running, thanks
discord.ext.commands.errors.ExtensionFailed: Extension 'bot.exts.utils.thread_bumper' raised an error: ResponseCodeError: Status: 404 Response:```can this be ignored?
is there more to the error?
https://paste.pythondiscord.com/uzajibuzim is the full error
the bot's running so I should be good
ah right
fair enough
I'll do that next start
Another tracebackpy bot_1 | Traceback (most recent call last): bot_1 | File "/usr/local/lib/python3.9/site-packages/discord/ext/commands/bot.py", line 917, in _load_from_module_spec bot_1 | spec.loader.exec_module(lib) # type: ignore bot_1 | File "<frozen importlib._bootstrap_external>", line 850, in exec_module bot_1 | File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed bot_1 | File "/bot/bot/exts/utils/snekbox.py", line 10, in <module> bot_1 | from botcore.utils import interactions bot_1 | ImportError: cannot import name 'interactions' from 'botcore.utils' (/usr/local/lib/python3.9/site-packages/botcore/utils/__init__.py) bot_1 | bot_1 | The above exception was the direct cause of the following exception: bot_1 | bot_1 | Traceback (most recent call last): bot_1 | File "/usr/local/lib/python3.9/site-packages/discord/ext/commands/bot.py", line 995, in load_extension bot_1 | await self._load_from_module_spec(spec, name) bot_1 | File "/usr/local/lib/python3.9/site-packages/discord/ext/commands/bot.py", line 920, in _load_from_module_spec bot_1 | raise errors.ExtensionFailed(key, e) from e bot_1 | discord.ext.commands.errors.ExtensionFailed: Extension 'bot.exts.utils.snekbox' raised an error: ImportError: cannot import name 'interactions' from 'botcore.utils' (/usr/local/lib/python3.9/site-packages/botcore/utils/__init__.py)
bot keeps running though
7.4.0
Ah, fun. Now my code has an errorpy bot_1 | 2022-07-23 21:34:22 | discord.ui.view | ERROR | Ignoring exception in view <SnoozeSelectView timeout=30 children=1> for item <Select placeholder='Select the snooze duration' min_values=1 max_values=1 options=[<SelectOption label='1 minute' value='1 minute' description=None emoji=None default=False>, <SelectOption label='5 minutes' value='5 minutes' description=None emoji=None default=False>, <SelectOption label='15 minutes' value='15 minutes' description=None emoji=None default=False>, <SelectOption label='30 minutes' value='30 minutes' description=None emoji=None default=False>, <SelectOption label='1 hour' value='1 hour' description=None emoji=None default=False>, <SelectOption label='3 hours' value='3 hours' description=None emoji=None default=False>, <SelectOption label='6 hours' value='6 hours' description=None emoji=None default=False>, <SelectOption label='1 day' value='1 day' description=None emoji=None default=False>, <SelectOption label='1 week' value='1 week' description=None emoji=None default=False>, <SelectOption label='1 month' value='1 month' description=None emoji=None default=False>, <SelectOption label='3 months' value='3 months' description=None emoji=None default=False>, <SelectOption label='6 months' value='6 months' description=None emoji=None default=False>, <SelectOption label='1 year' value='1 year' description=None emoji=None default=False>] disabled=False> bot_1 | Traceback (most recent call last): bot_1 | File "/usr/local/lib/python3.9/site-packages/discord/ui/view.py", line 412, in _scheduled_task bot_1 | await item.callback(interaction) bot_1 | File "/bot/bot/exts/utils/reminders.py", line 83, in select_snooze_duration bot_1 | selected_duration = interaction.data["values"][0] bot_1 | AttributeError: 'Select' object has no attribute 'data'
@discord.ui.select(placeholder="Select the snooze duration")
async def select_snooze_duration(self, _: discord.ui.Select, interaction: discord.Interaction) -> None:
"""Drop down menu which contains a list of snooze durations one can choose."""
selected_duration = interaction.data["values"][0]```has the order of parameters changed or something?
!d discord.ui.select
discord.ui.select(*, placeholder=None, custom_id=..., min_values=1, max_values=1, options=..., disabled=False, row=None)```
A decorator that attaches a select menu to a component.
The function being decorated should have three parameters, `self` representing the [`discord.ui.View`](https://discordpy.readthedocs.io/en/latest/interactions/api.html#discord.ui.View "discord.ui.View"), the [`discord.Interaction`](https://discordpy.readthedocs.io/en/latest/interactions/api.html#discord.Interaction "discord.Interaction") you receive and the [`discord.ui.Select`](https://discordpy.readthedocs.io/en/latest/interactions/api.html#discord.ui.Select "discord.ui.Select") being used.
In order to get the selected items that the user has chosen within the callback use [`Select.values`](https://discordpy.readthedocs.io/en/latest/interactions/api.html#discord.ui.Select.values "discord.ui.Select.values").
right
running now
Yeah, that seems to have fixed it
Thanks
So, turns out this is actually an issue. I rely on it being the same interaction later on in the code, where I get the embed of the original reminder message and re-send it
I guess I don't need to re-send it
In https://github.com/python-discord/bot/pull/2229/commits/a2380873ec312c4f979fd68809a810900b545c4f (part of bot#2229) I removed all usages of the namespace_lock, as it's been removed from async-rediscache now.
I think this should be fine for most, but possibly causes a problem in the custom set method, as there are a few calls out to redis in the function (a ttl call, a hset call and an expire call)
Should I add a our lock_arg deco onto this call, to lock on the DocItem, using the wait arg too
Ah, that won't work since lock_arg needs an int or str
guess I could use the lock deco and write a function to return a resource_id based on the DocItem attrs
Can I remove this lock_arg? It's causing issues because now that I have a wait() in it the cog doesn't load for 5 minutes
bot/exts/utils/reminders.py line 309
@lock_arg(LOCK_NAMESPACE, "reminder", itemgetter("id"), raise_error=True)```
bot/exts/utils/reminders.py line 362
await snooze_button_view.wait()```
yeah
you could move the delete logic to the view's timeout
The exact code is changed now but shows rough idea
and make it timeout after 5 min
that way the function itself isn't waiting, but is triggered on the view timeout
The view being SnoozeButtonView?
Yea
you can add a async def on_timeout() function to that view, and it will be called on timeout
The issue is that I need to do one thing on timeout and another thing when it doesn't timeout
Which as far as I know can only be achieved with wait()
Not my area of expertise, but from what I understand of the code I can't really see there being any problem with just removing the lock.
you are calling stop when the button is pressed
which will mean the on_timeout function won't get called
yeah but how do I run the other code
What is the other code?
isn't that on button press?
Yea, I'm not sure of the history of why it was needed
There are 3 separate awaits in that set call, so there is some room for concurrency issues
I'm going to guess package+group+symbol_id would be enough to serialise a unique identifier for that DocItem
so not too difficult to implement our own lock using the existing deco
@brazen charm when you get some time, do you happen to know why the namespace locks were required on the DocRedisCache?
They were removed in async-rediscache 1.0.0 so I want to know if we need to re-implement locking using our lock deco, or if they're fine without
bot#2229 for reference
I think it was mostly being safe and following the code that was in async-rediscache. There should be a possible race condition with the ttl await as it could execute multiple times if the connection to redis is slow or something, but the only thing that'd to is move the ttl by a tiny bit
I guess there's also a potential race at the end where an existing expire may cause the whole hash to expire before a new one is set, but that was there before too
The issue with this is that I can't reschedule the reminder from outside the Reminders cog class
Since I don't have access to the scheduler nor the self.send_reminder that gets called at the end of the expiry
So it seems I actually can't move that, which in turn means I can't move the on_timeout stuff, which means we're stuck with the 5 minute hang again
Can you pass something to the view that gives you access to those things?
I mean, I can but it'd be super messy
I'd be passing the reminder instance itself through 3 levels of classes
I can do that but I don't know how I feel about that
I can't think of a better way though ๐คท
Doesn't the ctx have the cog instance or something?
I don't have the ctx though
The only thing is the bot instance, and that's so that I can do the API calls
So I guess I can just make that the Reminders class instance
yeah it does
The view class always felt messy to me, you so often need to make a subclass to take the context, although technically a view isn't tied to a single context
I determined that f"{item.package}.{item.symbol_id}" was enough to be a unique_id for that docitem
Yea, it sounds like you want to pass the bot instance and the scheduler class to the view, so that both the view and the button can access them
I also suggest using/subclassing https://bot-core.pythondiscord.com/main/output/botcore.utils.interactions.html#botcore.utils.interactions.ViewWithUserAndRoleCheck as it has an interaction check built-in, meaning you don't need to do that in the button
I'm gonna push something in a minute so you can see what I've done for now
Contribute to Python Discord's Open Source Projects
Looking to contribute to Open Source Projects for the first time? Want to add a feature or fix a bug on the bots on this server? We have on-going projects that people can contribute to, even if you've never contributed to open source before!
Projects to Contribute to
โข Sir Lancebot - our fun, beginner-friendly bot
โข Python - our utility & moderation bot
โข Site - resources, guides, and more
Where to start
- Read our contribution guide
- Chat with us in #dev-contrib if you're ready to jump in or have any questions
- Open an issue or ask to be assigned to an issue to work on
Actually, I'm going to use the existing item_key function, since that's what is used for the redis key
was going to say that it may cause issues for empty symbol names. A tuple with the item_key and symbol id should work
The ttl is done on the item_key directly well redis_key = f"{self.namespace}:{item_key(item)}" but close enough
So we should likely lock on that, rather than allow concurrent sets for individual symbols
The second race condition I mentioned would also be nice to fix, though it is out of scope for the pr and nothing immediately comes to mind for it
Ahh yea true
I didn't fully read that message, clearly
I see what you mean now though
it should fix itself on the next set call but still is not ideal
Just pushed it to bot#2089 if you want to take a look @vale ibex. It's gone 1am now so I'm gonna go to bed
๐ค
This is really annoying
The site test suite failed on one test where the ID was greater than expected (implying dead data?) but running it again it passed
which test?
I despise flaky tests
It was one of the infraction tests, it expected ID 25 and ended up with 28
I donโt have the log anymore
I've ran that individual test suite 45 times, and the whole test suite 20 times, and I can't reproduce the error :(
Are you running pytest-xdist locally by chance?
Nah Iโve dumped those changes completely
The only thing that was different from main is that my compose port PR, but that shouldnโt affect it in any way
How did you test it 45 times you absolute troll
just had it running in a loop on 2 machines lol
That is some serious dedication lol
Iโll assume something bugged out, maybe a networking error and call it a day
Yea
May I take over bot#2172? It seems the original assignee has gone AWOL.
It's a small thing so could possibly even implement it as part of bot#2089
Hey guys ๐
If you got some time, have a look at sir-lancebot#1060, it's fairly a simple PR with plain fixes here and there. I believe anyone who's just starting out like me can also review it 
Can I get any help related to Django here?
this channel is for discussions related to this discord server's projects. ask in #web-development instead
Okay. Thanks
Hey, if there's any studious discord snek bot devs around I had a thought
what if you made a slash command for executing, the first field is code, and other fields are inputs? or just a second optional field is input to be fed so that input()'s would work
you could do that with text commands as well
!e currently combines all given code blocks IIRC
Yea, the downside of slash commands is that they don't support code blocks, so it can make it hard to actually write you code out
We could do soemthing smart with the code block language, if it's marked and input or something then we can pass that as stdin, rather than code
teaching people to use that seems strictly harder than
# guess = input("Your guess: ")
guess = "12"
You could also theoretically switch out stdin with a stringio so you donโt need to modify all the code
But most of the time changing it out is the cleanest solution
bump
I'd give it another couple days
That way it's been two weeks
Actually why not you can start work now
@static canyon you're good to start
Cool, thanks
Since it's small should I include it in my current reminders PR?
Link?
It's above
Sounds good
Aight, I'll add another commit for it ๐
I seem to once again be unable to start bot with docker. 2 days ago I was told to do docker-compose --profile 3.10 up bot as a temp fix but now that's not working either (it did 2 days ago)?
I get Error response from daemon: network bot_default not found
Prune the entire thing and then set it up again?
... can you compose up just the network?
idts
docker-compose up gives the same thing
Do you mean docker-compose down?
docker-compose down -v
for stopping the services and networks and removing the associated volumes
that would remove way too much stuff 
Still broken after doing this
what do you get as output from docker-compose up -d bot?
no such service: snekbox
I was told to do this instead to get around that
But now that's broken too
and what does that output? network not found?
PS C:\Users\tizzy\bot> docker-compose --profile 3.10 up bot
[+] Running 5/4
- Container bot-postgres-1 Created 0.1s
- Container bot-redis-1 Created 0.1s
- Container bot-metricity-1 Created 0.1s
- Container bot-web-1 Created 0.1s
- Container bot-bot-1 Created 0.1s
Attaching to bot-bot-1
Error response from daemon: network bot_default not found```
Yep
Can you just force re-pull the volumes/images and re-build?
What are the commands for that?
Wouldn't it be.... docker-compose --build --profile 3.10 up bot
what does docker pull and then docker compose up --build get you?
docker-compose build --pull --no-cache
ooh fancy
but, it doesn't seem like a container problem to me
PS C:\Users\tizzy\bot> docker network ls
NETWORK ID NAME DRIVER SCOPE
a4b558deaf0f api_default bridge local
05bdbb8a90ea bridge bridge local
2a4da9a78b32 host host local
aca58f6a065b none null local
7488b1ce02be pydis-testing_default bridge local
cee5f28fbfdc sir-lancebot_default bridge local```
Restart docker desktop
It does weird things with networks
I found restarting the daemon fixed it
docker network create bot_default?
You may need to kill the container and then restart
So looking at similar errors, the fix is to fully restart the daemon. Possibly you need to do a full up prune and then a dead stop to start
truly a d(a)emon
FWIW this should have a line for creating the bot_default network as well
Still can't get it to work
did you do this after restarting Docker Desktop?
Did this and now it works ๐คท
The bot's starting up
It should be created automatically when doing up, I'm guessing your docker is just freaking out
Yeah lol
RE bot#2172: should I make it so that it shows new content/mentions upon edit too?
I guess content isn't sent anyway, but could maybe say how many people it'll now mention
Actually - question about Docker
With the move to Ansible, will Ansible be running the same containers we use now, or will Ansible be installing the bot on bare metal?
We'll still be containerized
Agree, but it's a 2-line change so I think it'd be nice to show the new mentions count seeing as it's easy
So still on docker
I.e. literally addingpy elif "mentions" in payload: on_success_message += f"\n\nYour reminder will now mention {len(payload['mentions'])} other(s)"
Why not list out the specific mentions?
At least the first x
Because that's not what it currently does ๐คท
We can do though
Unless it supports mentioning things other than users
Since we only have ids
It can mention roles too
Yeah, then you can't really list them since just from the id you don't know if it's a role or user (and the mention is a different syntax for each)
It's really not worth all this effort, since you can already see who you mentioned or what the content is a line above where you edited it
But I guess it's fine to add if it's just a line or two
Anymore and no
Yeah, fair enough
I'll leave the content since that's not currently included
But I'll add the mentions count
Oh right it replies to the orignal
+ on_success_message = "That reminder has been edited successfully!"
+ if "expiration" in payload:
+ new_expiry_timestamp = time.discord_timestamp(payload['expiration'], time.TimestampFormats.DAY_TIME)
+ on_success_message += f"\n\nYour reminder will now arrive {new_expiry_timestamp}."
+ elif "mentions" in payload:
+ on_success_message += f"\n\nYour reminder will now mention {len(payload['mentions'])} other(s)."
await self._send_confirmation(
ctx,
- on_success="That reminder has been edited successfully!"
+ on_success=on_success_message,
reminder_id=id_,
)
```this is the total diff (ignore funky indentation)
There's a diff language? TIL
yep lol
Maybe just one blank line so it doesn't get too big?
Or is it like Markdown where you have to put two to get the space?
@vale ibex feel like reviewing a rediscache? ๐
https://github.com/SebastiaanZ/async-rediscache/pull/20
This one turned out to be a nice walk in the park after all
Ignore the massive diff, that's locking
You got me, I was trying to sneak in an RCE into the deps ๐
(after dinner)
Can I get permission to add reply functionality to editing content (it already exists when creating)
Thank
I think this should probably be a separate PR at this point, it's starting to carry quite a bit
I'd suggest limiting the scope of PRs, otherwise it make it much harder to review.
yea this
Also there doesn't exist a one-to-one relationship between messages and reminders
How would that work
I'm rebranding it to "reminder improvements" anyway. At the moment it's snoozing & the updated edit confirmation message
I can make a new PR for "further reminder improvements" if you want
Short of full rewrites, itโs better to separate features
Yeah, they're separated by commit but that's it
Please donโt call it improvements because that is not a helpful title
Instead what the actual improvements is gives more info for reviewers, which should hopefully help get the PRs through quicker
Reviewing by commit gets messy once you start getting into having changes and what not. So you either review commit by commit, just to see code that could have been removed or edited, and wasting time, or you end up reviewing all the changes at once
Yes please
Aight. Should I create a new issue describing the changes that'll be made in it?
Ideally since Iโd like to have a clearer idea of the implementation before we start work on it
Yep, okay
Iโm not sure how itโd work
I'll create a new issue for it once I've pushed the current changes to this PR
Yup yup
Aight, pushed to bot#2089
I'll create the issue now
I've made the issue:
bot#2231
Left a comment on the issue
@static canyon I don't really follow what you're saying
What's the new behavior that new would get?
!remind 1s
Your reminder will arrive on <t:1658776820:F>!
Here's your reminder: What's the new behavior that new would get?
[Jump back to when you created the reminder](#dev-contrib message)
!remind 1s
Your reminder will arrive on <t:1658776825:F>!
Here's your reminder: See referenced message.
[Jump back to when you created the reminder](#dev-contrib message)
That ^
Yes, I think this is fine, not sure how it comes into the edit idea
Make it so that you can do that for !remind edit content
Yes, but that's not actually technically possible
It is though? Same logic?
remind new doesn't need to figure out the state
It just makes a new reminder
How do you tie a reminder to a replied message like that
!remind 10H
Your reminder will arrive on <t:1658812893:F>!
!remind 20H
Your reminder will arrive on <t:1658848900:F>!
Right, what I mean is the content will get updated to the reference message's content
If I edited it now, which would edit
So !remind edit content _id_ {reference_message_for_content_argument}
Yeah
Sorry, didn't explain that very well 
And thinking about it the API call one seems kinda redundant so considering it'd cost API calls I'm happy to leave that
Like our API calls are pretty quick, so it wouldn't matter if you think it's a good feature
It might be, I never encountered that scenario
!remind 10M hello world
Your reminder will arrive on <t:1658777665:F>!
!remind edit content 4862 hello world
That reminder has been edited successfully!
Yeah, I don't know, it just seems weird to say "edited successfully" when it wasn't actually changed
I think it'd be nice to have if we don't care about API calls
Guess I'll let someone else weigh-in and see what they think, whilst I work on the other parts
@lock_arg(LOCK_NAMESPACE, "id_", raise_error=True)
async def delete_reminder(self, ctx: Context, ids: Greedy[int]) -> None:```I have an issue whereby because I've changed the parameter name, the `lock_arg` decorator is now giving an error that `id_` parameter doesn't exist. Can I just change that to `ids`, or will that not work since it's now a list of things to lock?
It wouldn't work
Can't remember, does it support a callabale
Actually even if it does, I don't think our current lock will manage that in any way
You might need to write a custom lock for this
Well rip
I have no clue how locks works
Yes, but it won't work with multiple IDs
We could make a fairly rudimentary lock that works for this, but the lock we have now is actually pretty invovled
Might just be best to let that idea rest
Or make the wrapped function a util, and have the command iterate through them and call it with each
Do we really need a lock when we're deleting?
Yes, it could cause some nasty bugs, especially if we're considering functions which do multiple operations within a single lock
Like you were proposing ๐
Fair enough
How would this work?
@lock_arg(LOCK_NAMESPACE, "id")
async def delete_reminder_util(self, ctx, id) -> None:
...
@command()
async def delete_reminder(self, ctx, ids):
for id in ids:
await delete_reminder_util(ctx, id)
Hmm
You'd need some error handling logic here
def lock_arg(
namespace: Hashable,
name_or_pos: function.Argument,
func: Callable[[Any], _IdCallableReturn] = None,
*,
raise_error: bool = False,
wait: bool = False,
) -> Callable:
"""
Apply the `lock` decorator using the value of the arg at the given name/position as the ID.
`func` is an optional callable or awaitable which will return the ID given the argument value.
See `lock` docs for more information.
"""
decorator_func = partial(lock, namespace, raise_error=raise_error, wait=wait)
return function.get_arg_value_wrapper(decorator_func, name_or_pos, func)```this is what `lock_arg` currently looks like. Could I just do```py
@command()
async def delete_reminder(self, ctx, ids):
for id_ in ids:
decorator_func = partial(lock, LOCK_NAMESPACE, "id_" raise_error=True)
function.get_arg_value_wrapper(partial(decorator_func, name_or_pos, None))```
If I import lock and function
I feel like that would work, but maybe not
Why the partial, and what do you plan to do with this? If you want to invoke lock manually without the decorator, could just call it directly at that point
So can I do ```py
for id_ in ids:
lock_arg(LOCK_NAMESPACE, id_, raise_error=True)
lock not lock_arg
But I'm still not sure what you're proposing
What's the next step after obtaining the lock in this fashion, just run the function?
I'm basically trying to call the decorator on each id_ and hoping that'll just work
Maybe even have something like ```py
@command()
async def delete_reminder(self, ctx, ids):
for id_ in ids:
self.delete_reminder(ctx, id)
@lock_arg(LOCK_NAMESPACE, "id_", raise_error=True)
def delete_reminder(ctx, id):
# code that's the current delete_reminder command```
This feels better
But again no clue if it'll work how it's supposed to
Yes that's what I suggested, and it should in theory work
Otherwise you'd end up with something like
for id_ in ids:
try:
lock(LOCK_NAMESPACE, id_, raise_error=True)()
...
except LockedResourceError:
failed.append(id)
Which is mostly fine, the only issue is we're bypassing the lock_arg, which makes it harder to modify in the future
It's not meant to be used in this way
I'll go for this then.
The lock could in theory be modified to work with multiple resources at the same time too
It would probably be the same amount of effort
Would I need lock error handling in this?
Yeah same error handling as this, otherwise it's unclear which ones failed deletion and which didn't
Since there's also confirmation, I'd actually move the deletion into the util function, and the confirmation into the main function
That way we send one confirmation/failure
Something like this?```py
@lock_arg(LOCK_NAMESPACE, "id_", raise_error=True)
async def delete_reminder(self, ctx: Context, id: int) -> bool:
"""Acquires a lock on id_ and returns True if reminder is deleted, otherwise False"""
if not await self.can_modify(ctx, id):
return False
await self.bot.api_client.delete(f"bot/reminders/{id_}")
self.scheduler.cancel(id_)
return True
@remind_group.command("delete", aliases=("remove", "cancel"))
async def delete_reminder(self, ctx: Context, ids: Greedy[int]) -> None:
"""Delete one of your active reminders."""
deleted_ids = []
for id_ in ids:
try:
reminder_deleted = self._delete_reminder(ctx, id_)
except LockedResourceError:
continue
else:
if reminder_deleted:
deleted_ids.append(str(id_))
if not deleted_ids:
return
embed = discord.Embed(
description=f"Successfully deleted the following reminder(s): {' '.join(deleted_ids)}",
colour=discord.Colour.green(),
title=random.choice(POSITIVE_REPLIES)
)
await ctx.send(embed=embed)```
It's just more explicit as to which line you're expecting to cause the error
But fair enough
for id_ in ids:
try:
reminder_deleted = self._delete_reminder(ctx, id_)
deleted_ids.append(str(id_))
except LockedResourceError:
continue
Yeah that's true, but not always applicable
At the very least i'd remove the if, in what scenario are you not expecting it to return
And I do still need the if, since _delete_reminder() can return False
When the user doesn't have permissions to delete that reminder
Alright fair enough
So I think we should instead of having that return
Check if there are any in the deleted list which aren't in IDs
and tell the user which ones those are
If you store the failed ones instead of the deleted, it becomes easier to do that
for ...
try:
delete
except:
failed.append(id)
if failed:
send_failed_message()
else:
send_confirmation
That's not the standard behaviour for this though
For reminders when you don't have permission to edit it just fails silently
!reminder edit duration 1234 1s
There does not seem to be anything matching your query.
Eh, it needs to be a valid id but it'll fail silently
I see, that seems like weird behavior but I don't expect you to change it then
bot/exts/utils/reminders.py lines 441 to 442
if not await self._can_modify(ctx, id_):
return```
Actually
What does the can_modify function do
It takes context, so I assume that sends the failure message
Yeah it does
Huh, yeah it does
We should probably then make that optional behavior, and send them as bulk
That's an issue though
Otherwise you could have the bot spam 200 messages lol
Yeah sounds good
Aight
Does this seem a good alternative to the send_denial?py deletion_message = f"Successfully deleted the following reminder(s): {' '.join(deleted_ids)}" if len(deleted_ids) != len(ids): deletion_message += " The other reminder(s) belong to other users so you can't delete them."
The failures could also be from the lock
It might be better to say could not delete the other ones
Hmm yeah
I can store the failed ones
And do something like if len(set(ids) - set(failed)) != len(ids)
Eh still a misleading error message though
I'll just say couldn't delete
Alternatively, py deletion_message += " The other reminder(s) could not be deleted as they were either locked or belong to someone else."to be explicit
Sounds good
Is this the correct overflow syntax for stringspy deletion_message += " The other reminder(s) could not be deleted " \ "as they were either locked or belong to someone else."
I.e. using the \ to make multi-line
Use parans instead
deletion_message += (
" The other reminder(s) could not be deleted "
"as they were either locked or belong to someone else."
)
you've pinned to to ~=4.2
which will do 4.X
IE this is on 4.3.1 in the PR
is this intended?
So Iโm pretty sure the deps in the lock file donโt actually count
Since theyโre overwritten by the setup
~=4.2 is still 4.X though
I'm only mentioning as I'm not sure if there were more breaking changes in 4.3
of course downstream projects can pin to 4.2.X
The lib itself should be compat with 4.3 as far as I tested, but if theyโre introducing breaking changes on feature releases, we might have to get more specific
(In the future)
I should also add aiodns to the require shouldnโt i
Yeah
Iโll do that
afaik the only brekaing change that would affect us is the removal of using OSError in 4.3
it uses ConnectionError instead
"us" being downstream projects such as bot, it won't impact the lib
We could go to 4.3 directly in bot
will merge it and then make a new PR/beta with the rc2 changes
I droped the asyncrediscache changes, so this is just py3.10
Yeah
after I push the lock file that is lol
hmmm, yea might block work otherwise
Ye
retargeted
@gritty windpy api_response = await self.bot.api_client.get(f"bot/reminders/{reminder_id}")how can I catch a 404 on this?
Oh you know what, I'll submit it from a dummy account and approve it
lol
catch a ResponseCodeError from botcore.site_api
Or pass raise_for_status as False and check the status code
Chris did you lock on a windows machine
And what version of poetry
How would I check the status code?
api_response.status is an int
But api_client.get() returns the dict?
Only if it passes, which is why it's easier to catch
This is the code for request
async with self.session.request(method.upper(), self._url_for(endpoint), **kwargs) as resp:
await self.maybe_raise_for_status(resp, raise_for_status)
return await resp.json()
#10634: Make -P (pdb) option work better with exceptions triggered from events
If this is true, my life will improve 13-fold
@full fractal since you're here, what's your thoughts on this? (Should there be a PR to make !remind edit validate the reminder was actually edited)
Also, what's your github?
I think it's better to keep it as is. I don't think people will attempt to edit their reminders without changes much
ichard26
Yeah, fair enough. I'll leave that one then
@vale ibex the PR is minor enough I think that it's more than fine with your review
I'll write a changelog and push to pypi, feel free to bump
Cool cool
bot#2232 is now live! CC @full fractal since you said you'd like to take a look ๐
I'm so confused, the action is not showing up on the commit
.github/workflows/release.yaml lines 3 to 8
on:
release:
types: [published]
tags-ignore:
- '**dev**'
- '**rc**'```
I wonder if ** just doesn't match
Because bot-core depends on async-rediscache (1.0.0rc2) which doesn't match any versions, version solving failed.
wut
No repro :O
cleared my pypi cache and it worked
guess poetry didn't want to look at the live pypi repo to resolve
Ah
This action is archaic magic
It's locked to ubuntu 18, py3.8 setup@v1, and what's __token__ lol
Seb has so much wisdom to teach us yet ๐
if ping:
# Perform a PING to confirm the connection is valid
await self._client.ping()
self.valid = True
``` should this be ```py
if ping:
# Perform a PING to confirm the connection is valid
self.valid await self._client.ping()
else:
self.valid = True
```?
in RedisSession.connect
PING is non-returning, it'll either error or work
def ping(self, **kwargs) -> ResponseT:
"""
Ping the Redis server
For more information see https://redis.io/commands/ping
"""
return self.execute_command("PING", **kwargs)
returns PONG
True
wait I guess a ConnectionError is raised if it fails?
Yes
aioredis actually had the same implicit behavior when creating the connection pool
This is mostly to keep that same sort of behavior
I forgot to add the new return value to the changelog
Oh that too lol
No the one from connect
session = RedisCache()
await session.connect()
# can become
session = await RedisCache().connect()
It's nothing crazy
bot-core#110
wut
ok
ERROR: Could not install packages due to an OSError: [Errno 2] No such file or directory: '/home/runner/work/bot-core/bot-core/.cache/py-user-base/lib/python3.10/site-packages/packaging-20.9.dist-info'
this is new
It's amazing how you changed one line and produced 1000 LOCs diff
well, rc2 does change a bunch of sub deps
Is this CI
Atrocious
passed now anyway
Btw you don't need to explicitly specify ping, it shhhhhould have a default
Merged, tag?
yea well, can't trust libraries these days
so many are unstable
Lmfao
yea, don't want to mess with pools
Smart man
Chris this is unacceptable
there are no perma links in the changelog
You know, we're almost at 100 PRs on bot-core and with v8 on the corner, it might be nice to put out a dev-announcement to drum up some hype for it
But we should probably triage some work first
this can be fixed when we reelease lol
yea we could do
need to port sir-lance and sir-robin at some point too
Btw if you start running into typing issues while upgrading
Update types-redis
I can't find why or how it got installed, and pip can't either
But it did seem to need an update
bot#2233, bot#2232, bot#2089 and bot#2031 are all needing reviews if anyone's free ๐
Interesting, why is my bot trying to connect to prod address
for redis
Oop, I had removed my config for testing something, all good
@vale ibex Oooh we didn't remove the close from bot-core
There's session.client.quit() and session.client.close but you don't actually need to do any clean up
It was missed in the changelog for RC 1, I'll add it
Ah cool, i'll add it to bot-core
Also, bugbear added a late binding closure check
very cool
bot-core#111
not sure what is up with the PR title lol
Haha
Btw what's a good way to mark a function as deprecated
I added it in the docstring as a regular comment
There's things like sphinx syntax, but we don't really use sphinx
In java you just @Deprecated, why can't this be java ๐
Because we don't hate ourselves
๐จ
I think the normal thing is to warnings.warn and to have the notice in the docstring
I added a warning too, but deprecation warnings are hidden by default
raise BaseException whenever it's called
I'll hit you both on the top head till you like java
lmfaooooo
pycharm should be smart enough to understand the warning at least
print and os._exit?
https://github.com/darbiadev/ProductionLog/blob/main/src/net/darbia/pl/data/CalculateAverages.java
Look how verbose Java is โผ๏ธ How can you live like this โ๏ธ
Use Python - write concise code โผ๏ธ
I use my python to autogenerate my java
I wish I had been smart enough to generate that crap
I have used regex to generate Python
And you said java was a bad language
It is!
Alright, sorted bot#2229
async def _create_redis_session() -> RedisSession:
"""Create and connect to a redis session."""
redis_session = RedisSession(
host=constants.Redis.host,
port=constants.Redis.port,
password=constants.Redis.password,
max_connections=20,
use_fakeredis=constants.Redis.use_fakeredis,
global_namespace="bot",
)
try:
await redis_session.connect()
except RedisError as e:
raise StartupError(e)
return redis_session
``` vs ```py
async def _create_redis_session() -> RedisSession:
"""Create and connect to a redis session."""
try:
return await RedisSession(
host=constants.Redis.host,
port=constants.Redis.port,
password=constants.Redis.password,
max_connections=20,
use_fakeredis=constants.Redis.use_fakeredis,
global_namespace="bot",
).connect()
except RedisError as e:
raise StartupError(e)
not sure which I prefeer
ofc we could do ```py
async def _create_redis_session() -> RedisSession:
"""Create and connect to a redis session."""
redis_session = RedisSession(
host=constants.Redis.host,
port=constants.Redis.port,
password=constants.Redis.password,
max_connections=20,
use_fakeredis=constants.Redis.use_fakeredis,
global_namespace="bot",
)
try:
return await redis_session.connect()
except RedisError as e:
raise StartupError(e)
I like numero tres
same
lol yea
we already have many
I looked for any imports of aioredis / non RedisSession imports from async redis cache
Oh we should mark async_rediscache as typed
how?
ohh, it's a lib change?
Never touched packaging properly
I didn't realize there was a special flag for it
Seems only mypy reads it
Oh it's a... file?
I think
SO async-rediscache would be covered by the first point right?
since it has in-line annotations
Yeah
Cool cool
There's a bunch of other issues with mypy on bot
was ~1k last time I checked
Oh then I guess you'll be glad to hear we're down to 200 lol
oh lol
Well, I only checked the bot directory
guess bumping versions has solved a load
There's tests too
Only 60 there
Alright, I pushed typing, we'll fit into some release at some point
With that and types-redis, we get 0 mypy warnings from redis, and I'm happy with that
nice
How do you trigger a compose rebuild from docker desktop
Fair enough
We should probably rip out the noqas N802
They are all over the test suite, and they're from pep-naming for the builtin methods
But I think they have support out of the box now
Some do
tests/base.py:35:10: N802 function name 'assertNotLogs' should be lowercase
tests/base.py:85:10: N802 function name 'assertHasPermissionsCheck' should be lowercase
```these still fail
They aren't built in methods, so they are properly incorrect
But yeah if did want to remove it, we could keep it on those
Yea, they're incorrect, but consistent :P
True
I'll remove the others and leave these
It's funny, pycharm doesn't pick up N802
So it'll complain about these
I've gotten a traceback, but can't quite figure out from what
It stems from the error handler
Stack (most recent call last):
... discord.py and asyncio stuff
File "C:\Users\hassa\AppData\Local\pypoetry\Cache\virtualenvs\bot-QP3Q7ay1-py3.10\lib\site-packages\discord\client.py", line 456, in _run_event
await coro(*args, **kwargs)
File "C:\GitHub\PyDis\bot\bot\exts\backend\error_handler.py", line 74, in on_command_error
await self.handle_user_input_error(ctx, e)
File "C:\GitHub\PyDis\bot\bot\exts\backend\error_handler.py", line 276, in handle_user_input_error
await self.send_command_help(ctx)
File "C:\GitHub\PyDis\bot\bot\exts\backend\error_handler.py", line 105, in send_command_help
await ctx.send_help(ctx.command)
File "C:\Users\hassa\AppData\Local\pypoetry\Cache\virtualenvs\bot-QP3Q7ay1-py3.10\lib\site-packages\discord\ext\commands\context.py", line 541, in send_help
return await injected(entity)
File "C:\Users\hassa\AppData\Local\pypoetry\Cache\virtualenvs\bot-QP3Q7ay1-py3.10\lib\site-packages\discord\ext\commands\core.py", line 182, in wrapped
ret = await coro(*args, **kwargs)
File "C:\GitHub\PyDis\bot\bot\exts\info\help.py", line 321, in send_command_help
await wait_for_deletion(message, (self.context.author.id,))
File "C:\GitHub\PyDis\bot\bot\utils\messages.py", line 84, in wait_for_deletion
await message.add_reaction(emoji)
File "C:\Users\hassa\AppData\Local\pypoetry\Cache\virtualenvs\bot-QP3Q7ay1-py3.10\lib\site-packages\discord\message.py", line 1061, in add_reaction
await self._state.http.add_reaction(self.channel.id, self.id, emoji)
File "C:\Users\hassa\AppData\Local\pypoetry\Cache\virtualenvs\bot-QP3Q7ay1-py3.10\lib\site-packages\discord\http.py", line 475, in request
_log.warning(fmt, retry_after, bucket, stack_info=True)
I have the trashcan btw, it got added
I think I just got ratelimited, did that always produce tracebacks



