Skip to content

Commit

Permalink
Merge pull request #2558 from sopel-irc/docs-toc-maxdepth
Browse files Browse the repository at this point in the history
docs: set `maxdepth` or `titlesonly` on overly-long TOCs
  • Loading branch information
dgw authored Nov 21, 2023
2 parents 179ab82 + 8151acd commit 3ff58c1
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 31 deletions.
1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
'ModeDetails': 'sopel.irc.modes.ModeDetails',
'PrivilegeDetails': 'sopel.irc.modes.PrivilegeDetails',
}
autodoc_preserve_defaults = True


# -- Options for HTML output ---------------------------------------------------
Expand Down
6 changes: 3 additions & 3 deletions docs/source/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,13 @@ In that case:

.. seealso::

Sopel uses the built-in :func:`ssl.wrap_socket` function to wrap the socket
used for the IRC connection.
Sopel uses the built-in :meth:`ssl.SSLContext.wrap_socket` function to wrap
the socket used for the IRC connection.

.. note::

Sopel will try to look at one of these files for the CA certs pem file
required by :func:`ssl.wrap_socket`:
required by :meth:`ssl.SSLContext.wrap_socket`:

* ``/etc/pki/tls/cert.pem``
* ``/etc/ssl/certs/ca-certificates.crt`` (Debian)
Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Documentation

.. toctree::
:maxdepth: 2
:titlesonly:

run
plugin
Expand Down
7 changes: 7 additions & 0 deletions docs/source/package/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
Configuration functionality
===========================

The description of :mod:`.config` below is a quick guide to the basic structure
of configuration settings in Sopel. Consult the :mod:`.config.types` module for
more specific information about the available kinds of options, and
:mod:`.config.core_section` for examples of how the different setting types are
practically used.

.. toctree::
:titlesonly:

config/types
config/core_section
Expand Down
6 changes: 3 additions & 3 deletions docs/source/package/config/core_section.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
============
Core Section
============
===================
Core Config Section
===================

.. automodule:: sopel.config.core_section
:members:
Expand Down
7 changes: 7 additions & 0 deletions docs/source/package/irc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@
IRC Core Implementation
=======================

Operation of the :mod:`sopel.irc` core is supported by these utility submodules:

.. toctree::
:titlesonly:

irc/backends
irc/modes
irc/isupport
irc/capabilities
irc/utils


sopel.irc
=========

.. automodule:: sopel.irc
:members:
:undoc-members:
Expand Down
1 change: 1 addition & 0 deletions docs/source/package/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Plugin Internal Machinery
section exists primarily for the aid of Sopel’s core development.

.. toctree::
:maxdepth: 2

loader
plugins/plugins
Expand Down
6 changes: 6 additions & 0 deletions docs/source/package/tools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
Additional Tools
================

Sopel provides utilities for some commonly used plugin functionality. Most of
these utility features have been collected into submodules for convenience:

.. toctree::
:titlesonly:

tools/calculation
tools/events
Expand All @@ -13,6 +17,8 @@ Additional Tools
tools/time
tools/web

Miscellaneous tools that don't fit any particular category appear below.


sopel.tools
===========
Expand Down
9 changes: 9 additions & 0 deletions docs/source/tests.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@
Testing tools
=============

The best code comes with unit tests. Sopel provides a :doc:`pytest plugin
<tests/pytest>` with standard fixtures; :doc:`factories <tests/factories>` and
:doc:`mocks <tests/mocks>` to support writing tests; and the
:func:`~.tests.rawlist` function to help analyze the mocked-up bot's output.

.. toctree::
:titlesonly:

tests/pytest
tests/factories
tests/mocks

sopel.tests
===========

.. automodule:: sopel.tests
:members:
50 changes: 25 additions & 25 deletions sopel/plugins/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from __future__ import annotations

import abc
from datetime import datetime, timedelta, timezone
import datetime
import functools
import inspect
import itertools
Expand Down Expand Up @@ -466,24 +466,24 @@ def check_url_callback(self, bot, url):
class RuleMetrics:
"""Tracker of a rule's usage."""
def __init__(self) -> None:
self.started_at: Optional[datetime] = None
self.ended_at: Optional[datetime] = None
self.started_at: Optional[datetime.datetime] = None
self.ended_at: Optional[datetime.datetime] = None
self.last_return_value: Any = None

def start(self) -> None:
"""Record a starting time (before execution)."""
self.started_at = datetime.now(timezone.utc)
self.started_at = datetime.datetime.now(datetime.timezone.utc)

def end(self) -> None:
"""Record a ending time (after execution)."""
self.ended_at = datetime.now(timezone.utc)
self.ended_at = datetime.datetime.now(datetime.timezone.utc)

def set_return_value(self, value: Any) -> None:
"""Set the last return value of a rule."""
self.last_return_value = value

@property
def last_time(self) -> Optional[datetime]:
def last_time(self) -> Optional[datetime.datetime]:
"""Last recorded start/end time for the associated rule."""
# detect if we just started something or if it ended
if (self.started_at and self.ended_at) and (self.started_at < self.ended_at):
Expand All @@ -493,7 +493,7 @@ def last_time(self) -> Optional[datetime]:

def is_limited(
self,
time_limit: datetime,
time_limit: datetime.datetime,
) -> bool:
"""Determine if the rule hits the time limit."""
if not self.started_at:
Expand Down Expand Up @@ -758,24 +758,24 @@ def get_global_metrics(self) -> RuleMetrics:

@property
@abc.abstractmethod
def user_rate_limit(self) -> timedelta:
def user_rate_limit(self) -> datetime.timedelta:
"""The rule's user rate limit."""

@property
@abc.abstractmethod
def channel_rate_limit(self) -> timedelta:
def channel_rate_limit(self) -> datetime.timedelta:
"""The rule's channel rate limit."""

@property
@abc.abstractmethod
def global_rate_limit(self) -> timedelta:
def global_rate_limit(self) -> datetime.timedelta:
"""The rule's global rate limit."""

@abc.abstractmethod
def is_user_rate_limited(
self,
nick: Identifier,
at_time: Optional[datetime] = None,
at_time: Optional[datetime.datetime] = None,
) -> bool:
"""Tell when the rule reached the ``nick``'s rate limit.
Expand All @@ -789,7 +789,7 @@ def is_user_rate_limited(
def is_channel_rate_limited(
self,
channel: Identifier,
at_time: Optional[datetime] = None,
at_time: Optional[datetime.datetime] = None,
) -> bool:
"""Tell when the rule reached the ``channel``'s rate limit.
Expand All @@ -802,7 +802,7 @@ def is_channel_rate_limited(
@abc.abstractmethod
def is_global_rate_limited(
self,
at_time: Optional[datetime] = None,
at_time: Optional[datetime.datetime] = None,
) -> bool:
"""Tell when the rule reached the global rate limit.
Expand Down Expand Up @@ -1205,43 +1205,43 @@ def get_global_metrics(self) -> RuleMetrics:
return self._metrics_global

@property
def user_rate_limit(self) -> timedelta:
return timedelta(seconds=self._user_rate_limit)
def user_rate_limit(self) -> datetime.timedelta:
return datetime.timedelta(seconds=self._user_rate_limit)

@property
def channel_rate_limit(self) -> timedelta:
return timedelta(seconds=self._channel_rate_limit)
def channel_rate_limit(self) -> datetime.timedelta:
return datetime.timedelta(seconds=self._channel_rate_limit)

@property
def global_rate_limit(self) -> timedelta:
return timedelta(seconds=self._global_rate_limit)
def global_rate_limit(self) -> datetime.timedelta:
return datetime.timedelta(seconds=self._global_rate_limit)

def is_user_rate_limited(
self,
nick: Identifier,
at_time: Optional[datetime] = None,
at_time: Optional[datetime.datetime] = None,
) -> bool:
if at_time is None:
at_time = datetime.now(timezone.utc)
at_time = datetime.datetime.now(datetime.timezone.utc)
metrics = self.get_user_metrics(nick)
return metrics.is_limited(at_time - self.user_rate_limit)

def is_channel_rate_limited(
self,
channel: Identifier,
at_time: Optional[datetime] = None,
at_time: Optional[datetime.datetime] = None,
) -> bool:
if at_time is None:
at_time = datetime.now(timezone.utc)
at_time = datetime.datetime.now(datetime.timezone.utc)
metrics = self.get_channel_metrics(channel)
return metrics.is_limited(at_time - self.channel_rate_limit)

def is_global_rate_limited(
self,
at_time: Optional[datetime] = None,
at_time: Optional[datetime.datetime] = None,
) -> bool:
if at_time is None:
at_time = datetime.now(timezone.utc)
at_time = datetime.datetime.now(datetime.timezone.utc)
metrics = self.get_global_metrics()
return metrics.is_limited(at_time - self.global_rate_limit)

Expand Down
11 changes: 11 additions & 0 deletions sopel/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ def get_sendable_message(text, max_length=400):
care of multibyte UTF-8 characters by working on the Unicode string,
then making sure the bytes version is smaller than the max length.
.. note::
In most cases, letting the bot gracefully handle message truncation
using optional arguments to :meth:`bot.say() <.bot.Sopel.say>` is
preferable. However, this function is part of the public API to provide
for more advanced use-cases.
See also the :meth:`bot.safe_text_length() <.bot.Sopel.safe_text_length>`
method, whose return value can be passed as this function's
``max_length`` argument.
.. versionadded:: 6.6.2
"""
unicode_max_length = max_length
Expand Down
16 changes: 16 additions & 0 deletions sopel/tools/memories.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,19 +235,35 @@ def __delitem__(self, key: str):
super().__delitem__(self._make_key(key))

def copy(self):
"""Get a shallow copy of this ``SopelIdentifierMemory``.
See :meth:`dict.copy`.
"""
return type(self)(self, identifier_factory=self.make_identifier)

def get(self, key: str, default=_NO_DEFAULT):
"""Get the value of ``key`` from this ``SopelIdentifierMemory``.
Takes an optional ``default`` value, just like :meth:`dict.get`.
"""
if default is _NO_DEFAULT:
return super().get(self._make_key(key))
return super().get(self._make_key(key), default)

def pop(self, key: str, default=_NO_DEFAULT):
"""Pop the value of ``key`` from this ``SopelIdentifierMemory``.
Takes an optional ``default`` value, just like :meth:`dict.pop`.
"""
if default is _NO_DEFAULT:
return super().pop(self._make_key(key))
return super().pop(self._make_key(key), default)

def update(self, maybe_mapping=tuple()):
"""Update this ``SopelIdentifierMemory`` with key-value pairs.
See :meth:`dict.update`.
"""
super().update(self._convert_keys(maybe_mapping))

def __or__(self, other):
Expand Down

0 comments on commit 3ff58c1

Please sign in to comment.