8.0.0
Re-published due to broken automation. Do not adjust your television set; there is no cause for alarm.
Changes between 7.1.9 and 8.0.0
Highlights
Detailed coverage of the major changes can be found in the dedicated
Sopel 8 upgrade guide.
For users:
- Python 3.8+ is now required
- IRC connections are made with TLS on port 6697 if not configured
- SASL EXTERNAL authentication is now supported
- Plugins in
~/.sopel/modules
are no longer loaded by default- Use the
core.extra
setting to add this directory back if needed
- Use the
- Database options can be configured all at once in new
db_url
setting (useful
for managed cloud hosting such as Heroku) .blocks
command accepts "nick" and "host" types now, and no longer lies
about supporting "hostmasks" (further improvements to come)- Sopel no longer supports loading (very!) old Phenny/Jenni plugins
- Several built-in plugins have been converted to external packages, to simplify
maintenance and release-management going forward
For developers:
Identifier
was moved tosopel.tools.identifiers
and now supports dynamic
casemapping; an optionalcasemapping
oridentifier_factory
kwarg has been
added to many object types to help manage this at runtime- You can usually just pass
bot.make_identifier
as the factory function and
things will Just Work™ - Feel free to use
bot.make_identifier()
yourself to get anIdentifier
representing any nick or channel name you get, e.g. as input to a command
- You can usually just pass
- The
core.nick
setting value is now returned as astr
, not anIdentifier
- Capability negotiation is a first-class plugin API feature (see
plugin.capability
and the related documentation chapter) trigger.sender
attribute as passed to plugin callables is nowNone
in
cases where its value is meaningless (events with no channel/query context)- Numerous deprecated API features were removed:
bot.privileges
(usebot.channels
)bot.msg()
(usebot.say()
)sopel.web
submodule (usesopel.tools.web
)
- Messages from other bots are ignored by default on supported networks, but
plugins can opt back in with the@plugin.allow_bots
decorator STATUSMSG
prefix is removed fromtrigger.sender
if present and stored in a
separatetrigger.status_prefix
attribute- See documentation for
bot.SopelWrapper.default_destination
- See documentation for
bot.connection_registered
is now the way to check whether the bot is
connected to IRC, registered with the network, and ready for your plugin to
send commands
Plugin changes
- admin:
- Added
.raw
command to make Sopel send a raw IRC line [#2104]
- Added
- adminchannel:
- bugzilla:
- Extracted to its own package [#2481]
- calc:
- clock:
- Added
unset
commands for user & channel time zone/format [#2181]
- Added
- coretasks:
- currency:
- dice:
- Refactoring, bugfixes, and improved test coverage [#2532]
- emoticons:
- find:
- help:
- Now updatable independently from its own package, but still
installs with Sopel as a dependency [#2332]
- Now updatable independently from its own package, but still
- ip:
- Miscellaneous code-style improvements [#2393]
- Extracted to its own package [#2523]
- meetbot:
- Extracted to its own package [#2477]
- pronouns:
- Accept abbreviated pronoun sets [#2070]
- Added
.clearpronouns
command [#2154] - Fetch pronoun list dynamically at startup [#2130]
- Support configurable pronoun backend [#2437, #2438]
- The old backend at
pronoun.is
went down and never came back, so now you
can use our replacement or host your own
- The old backend at
- py:
- Extracted to its own package [#2411, #2415]
- reddit:
- Newer
praw
library allowed [#2319] - Added configuration setting to turn off inline slash-references [#2418]
- Extracted to its own package [#2444]
- Newer
- reload:
- remind:
- Avoid trying to use IRC connection if it's not ready [#2351, #2374]
- Extracted to its own package [#2478]
- safety:
- search:
- seen:
- tell:
- Fixed edge cases in cleanup of tellee argument [#2584]
- translate:
- Improved help output [#2453]
- unicode_info:
- url:
- Improved interaction between
.title
command and link handlers [#2282] - Removed traceback from debug log when URL fetch fails [#2280]
- Made channel-privilege-based access to
.urlexclude
command and friends
configurable [#2352] - Cleaned up code [#2304, #2307, #2433]
- Added better error handling for DNS lookups [#2428]
- Ignore invalid hostnames [#2472]
- Improved interaction between
- version:
- Support retrieving plugin versions with
.version pluginname
[#2133]
- Support retrieving plugin versions with
- wikipedia:
- Commands are now
.wp
,.wikipedia
; old commands (.w
,.wik
, &.wiki
)
were removed [#1966] - Remove deprecated
lang_per_channel
setting [#2142] - Work around excessive whitespace in math formulas [#2286]
- Don't ping the user who posted a URL that fails to load [#2315]
- Output image description if URL has an image viewer fragment [#2388]
- Handle query strings in article links [#2414]
- Fail gracefully on
Special:
namespace links [#2575]
- Commands are now
- xkcd:
Core changes
- Removed support for EOL Python versions (2.7, 3.3, 3.4, 3.5, 3.6, & 3.7),
added testing on newer Python versions (up to 3.12), and modernized coding
standards [#2062, #2073, #2123, #2124, #2134, #2136,
#2138, #2205, #2213, #2227, #2298, #2326, #2327,
#2342, #2384, #2464, #2500, #2516] - Modified default settings:
- IRC backend refactored to use
asyncio
[#2256]- Just in time, too: The
asynchat
module was removed in Python 3.12
- Just in time, too: The
- Improved IRC connection error handling [#2430, #2431]
SopelDB
adapted to SQLAlchemy 2.x style [#2243]- Database can be configured all at once with a new
db_url
setting [#2087] - Replaced
pkg_resources
withimportlib.metadata
[#2261, #2268] - Added support for several new IRC features and IRCv3 specifications:
- Improved SASL handling when auth fails [#2187, #2191]
- Added automatic
CASEMAPPING
handling based onRPL_ISUPPORT
[#2231] - Plugins in
~/.sopel/modules
are no longer loaded by default [#2119] - Removed support for Phenny/Jenni plugin style [#2126]
- Ignore
bot
-tagged messages by default [#2089, #2272] - Privilege tracking (MODE event handling) refactored [#2131]
- Maintain ordering of
ISupport.PREFIX
property [#2200] - Added
__slots__
toChannel
andUser
objects [#2233] - Improved handling of the bot's nick getting changed [#2240]
- Improved tracking and enforcement of rate limits [#2297]
- Prevent infinite loop on connection failure [#2306]
- Added
ssl_ciphers
andssl_minimum_version
settings [#2246, #2306] - Added
antiloop_repeat_text
,antiloop_silent_after
,antiloop_threshold
,
andantiloop_window
settings to control command-loop prevention [#2320] - Using
,
inListAttribute
values logs a warning [#2252]- Write lists with newlines instead; Sopel 9 will remove splitting on
,
- Write lists with newlines instead; Sopel 9 will remove splitting on
- IRC connections use TLS on port 6697 by default [#2277]
- Potentially a breaking change, but the configuration wizard has long
written these settings to the final config file even if they were left at
the default values
- Potentially a breaking change, but the configuration wizard has long
- Fixed
UHNAMES
race condition caused by joining channels too soon [#2321] - Removed hunting for CA root store [#2278, #2303]
- Sopel will simply use the system TLS library's default trust store unless
theca_certs
setting is specified
- Sopel will simply use the system TLS library's default trust store unless
- Improved truncation/splitting of over-length messages in e.g.
bot.say()
[#2310, #2450] - Gracefully handle missing
userhost-in-names
data, e.g. with ZNC [#2312]- See ZNC issue #1224
- Override
get_version()
method forEntryPointPlugin
[#2313] - Take advantage of
LINELEN
token if advertised in ISUPPORT [#2346] - Unescape ISUPPORT parameter values [#2429]
- Keep track of user realnames via WHO/WHOX [#2383, #2396]
- Raise error on receiving non-UTF-8 data if server advertises
UTF8ONLY
[#2365, #2369, #2372] - Make all arguments
safe()
when preparing IRC commands [#2368] - Ignore disabling
coretasks
handlers in per-channel settings [#2400] - Add guardrails to channel logging [#2419]
- Default is now always WARNING, regardless of file logging level
- DEBUG level is no longer available for channel logs; it is far too noisy
- Handle
core.modes
setting beingNone
[#2510] - Handle broken symlinks to plugin files [#2545]
- Fixed auto-saving changes to Sopel's ignore list with
.blocks
[#2550]
API changes
- Importing
sopel.module
now emits a deprecation warning [#2170] - Removed support for Phenny/Jenni plugin style [#2126]
- Stopped searching
bot.memory['url_callbacks']
for link handlers [#2121] - Deprecated
bot.search_url_callbacks()
[#2121, #2156, #2581] - Deprecated
db.execute()
[#2243] - Cleaned up parts of
sopel.tools
namespace- Deprecated
tools.web.entity()
and itsr_entity
constant, to be removed
in Sopel 9.0 [#2205] - Deprecated the
iteritems
,iterkeys
,itervalues
, andraw_input
2to3-style shims, to be removed in Sopel 8.1 [#2228] - Moved
Identifier
to its own submodule,tools.identifiers
[#2231]tools.Identifier
remains for now as a compatibility shortcut
- Moved
check_pid()
andstderr()
functions tocli.utils
[#2385] - Deprecated
tools.OutputRedirect
class left over from the days before
modern logging, to be removed in Sopel 8.1 [#2385]
- Deprecated
- Moved channel privilege constants into their own
sopel.privileges
submodule
[#2179, #2352, #2540]- The new
sopel.privileges.AccessLevel
type encapsulates all levels in a
single object, which can support dynamic features in the future - The original, individual constants in
sopel.plugin
are still available for
now, mapped to their correspondingAccessLevel
values
- The new
- Sopel's API now uses enumerated types where suitable:
bot
-tagged messages are ignored by default [#2089]trigger.time
is offset-aware [#2099]tools.time
improvements & changes:- Added
plugin.allow_bots
decorator [#2244] - Added more rate-limit controls [#2290, #2434]
- New
message
keyword-only argument toplugin.rate
decorator, an optional
string sent via NOTICE when a command is rate-limited - New
plugin.rate_user
,plugin.rate_channel
, andplugin.rate_global
decorators provide simpler control over a single rate-limit type, with the
rate
andmessage
(optional) as positional parameters - Messages support various placeholders that will be replaced with runtime
data about the triggering user, the rate limit in effect, and the
plugin/command that was limited; seeplugin.rate
decorator documentation for details
- New
- Added
bot.safe_text_length()
method [#2136] - Added
RPL_WHOISBOT
totools.events
list [#2145] - Added
bot.plugins
property [#2199] - Added
db.forget_channel()
anddb.forget_plugin()
methods [#2224] - Renamed
db.delete_nick_group()
todb.forget_nick_group()
[#2224] - Added CASEMAPPING support to
Identifier
[#2231]- Static
Identifier._lower()
method now obeys RFC 1459 casing rules Identifier
constructor now takes optionalcasemapping
andchantypes
kwargs; see documentation for details, or use thebot.make_identifier()
helper method to automatically use the bot's knowledge about the current
server's configuration
- Static
- Added CHANTYPES support to
Identifier
[#2236] - Added
bot.make_identifier_memory()
helper to easily take advantage of the
bot's CASEMAPPING and CHANTYPES knowledge [#2552] - Changed reading
core.nick
from the bot's settings to return astr
instead
ofIdentifier
[#2231]- Depending on what your plugin does, you might need to use the result of
bot.make_identifier(bot.settings.core.nick)
instead of the raw value
- Depending on what your plugin does, you might need to use the result of
- Moved memory classes to
sopel.tools.memories
[#2237] - Moved
deprecated()
fromsopel.tools
tosopel.lifecycle
[#2232] db.get_nick_id()
no longer creates a new nick ID by default [#2234]- Standardized on
ctcp
instead ofintent
[#2253]- The old
module.intent()
decorator was deprecated in Sopel 7.1; use the
plugin.ctcp()
decorator instead - Sopel 8.0 removes
intent
fromtrigger.tags
; usetrigger.ctcp
instead
- The old
- Updated invite-related event names in
tools.events
[#2270] - Fixed checking if
None
exists in aSopelIdentifierMemory
[#2306] - Fixed and tested
SopelIdentifierMemory
interactions with plainer-vanilla
dictionary types [#2525] - Reworked capability negotiation [#2341]
- See Managing Capability Negotiation documentation chapter
- This replaces the
irc.utils.CapReq
interface, which is now deprecated
- Changed
trigger.sender
property to beNone
for events not associated with
a channel or query [#2359] - Fixed
trigger.text
erroneously containing command name for events with empty
args
[#2360] - Removed
STATUSMSG
prefix fromtrigger.sender
[#2370, #2441]- Status prefix is now stored in a new
trigger.status_prefix
attribute - The
bot
passed to plugin callables will use thestatus_prefix
and
sender
attributes to build itsdefault_destination
, meaning no change to
plugins' most common usages ofbot.say()
,bot.reply()
, etc.
- Status prefix is now stored in a new
- Fixed
formatting.color
result when passing0
asfg
orbg
[[#2366][]] config.types.FilenameAttribute
strips quotes from its value [#2371]- Made
bot.connection_registered
more robust [#2375, #2406, #2410] - The bot initializes with an
UninitializedBackend
instead ofNone
, to
intercept actions that don't work prior to connecting [#2394]- Prohibited actions raise
RuntimeError
instead of falling through to a more
esoteric error type or—worse—silently failing
- Prohibited actions raise
- Added
realname
&is_bot
fields toUser
objects [#2383, #2448] - Use of
plugin.require_privilege()
orplugin.require_bot_privilege()
decorators now impliesrequire_chanmsg()
[#2405, #2580] - Fixed an inconsistency between behavior and documentation for
tools.calculation.pow_complexity()
[#2543] - Soft-deprecated
SopelWrapper
type [#2521]- Long-term, we will phase out this subclass in favor of using
contextvars
;
see #2460 for the full timeline
- Long-term, we will phase out this subclass in favor of using
- Moved
sopel.plugins
tosopel.builtins
[#2504]- We don't technically consider these to be part of the API, but if this
isn't mentioned we just know someone will complain that the move broke
some custom plugin code
- We don't technically consider these to be part of the API, but if this
- Removed previously-deprecated API features [#2128, #2129, #2141,
#2144, #2146, #2147, #2148, #2150, #2329]
Housekeeping changes
- Many, many additions & improvements to documentation [#1990, #2169,
#2178, #2182, #2226, #2238, #2239, #2257, #2275,
#2276, #2323, #2379, #2386, #2409, #2424, #2426,
#2442, #2489, #2494, #2495, #2496, #2533, #2539,
#2543, #2550, #2558, #2574, #2600, #2606] - Switched from Travis CI to GitHub Actions and incrementally improved tests
[#2075, #2078, #2123, #2188, #2262, #2335, #2342,
#2381, #2452, #2453, #2458, #2505, #2519, #2543] - Improved tooling for contributors, e.g.
Makefile
targets [#2502] - Modernized packaging [#2328]
- Cleanup on aisle
contrib/
[#2085, #2520] - Cleanup of deprecated feature usage in core & built-in plugins [#2117,
#2464, #2468, #2470] - Import reorganization [#2179]
- Various code smell/style issues fixed [#2186, #2220, #2231,
#2382, #2393, #2514] - Various logging improvements [#2309, #2354, #2473, #2569]
- Deprecation warnings for the corresponding stable release now begin to emit
logs in prerelease versions [#2522] - Removed legacy CLI run mode [#2118]
- Removed obsolete, nonfunctional CLI argument
--quiet
[#2404] - Removed old
sopel.test_tools
[#2139, #2177] - Raw logs improved both output and decode failure handling [#2095]
- Started our journey into the wonderful world of type checking [#2185,
#2462, #2471, #2480, #2491, #2535, #2555]- Many many PRs added or updated type hints in the course of adding/fixing
something else, so we won't also list all of them here
- Many many PRs added or updated type hints in the course of adding/fixing