`conf.supybot.databases()` may be called without any plugin supporting
sqlite3 being loaded yet, which causes `sqlite3` to be missing from
`sys.modules`; so it wouldn't be used by plugins loaded afterward.
They are not meant to be displayed like this, so they look weird sometimes.
For example, Mastodon splits long links between spans, so the Fediverse plugin
always displayed them broken.
.getSpecific() always returned the channel-specific but non-network-specific var,
unless the channel-specific and network-specific one was manually set.
`registry.Value.__call__()` is a wrapper around access to
`registry.Value.value`, that checks if the value was set before the latest
call to `registry.open_registry`; and updates the `value` if needed.
When accessing `registry.Value.value` directly, this cache can't be
invalidated, causing the old value to still be used, until the next call
to `registry.Value.__call__()`.
Python 3.9 introduced the zoneinfo module, which provides the only
feature we used pytz for (getting a datetime.tzinfo object from
an IANA timezone id); so let's use it instead of a third-party
dependency.
This commit reverts db7ef3f02517f9f2a3c56829a22b9fad3c36e374
(though it keeps the year updates)
After discussion with several people, it seems better to mention
copyright owners explicitly. eg. https://reuse.software/faq/#vcs-copyright
explains the issue of using VCSs to track copyright.
As db7ef3f02517f9f2a3c56829a22b9fad3c36e374 only replaced mentions
of my name with 'The Limnoria Contributors', this commit only needs
to undo that + add one person who contributed to setup.py.
nickFromHostmask now (legitimately) complains when it's getting @ or !
at the beginning of a hostmask; so we need to strip them before passing
it to nickFromHostmask.
Then re-add them before calling c.addUser, because it uses them to
sort users in the right sets (ops/halfops/voices).
Additionally, this commit replaces the hardcoded set of prefix chars
(`@%+&~!`) with the one advertised in ISUPPORT when possible.
When a driver's run() method crashes, supybot.drivers.run() marks it
as dead and sets its 'irc' attribute to None.
This would be fine for "normal" independent drivers (like Socket used
to be), because this driver would never be called again.
But now that we use select(), some other thread may hold a reference
to this driver in a select() call frame, and call the dead driver's
'_read()' method when there is data to be read from the socket.
There is already a safeguard in '_read()' in the case the socket could
be read from, but this safeguard was missing from _handleSocketError.
This caused the "live" driver's select() to crash, which propagagated
to its run(), which caused the driver to be marked as dead, etc.
Eventually, all drivers could die, and we end up with the dreadful
"Schedule is the only remaining driver, why do we continue to live?"
in an infinite loop.