diff options
| author | Daniel Schadt <kingdread@gmx.de> | 2023-06-02 21:16:36 +0200 | 
|---|---|---|
| committer | Daniel Schadt <kingdread@gmx.de> | 2023-06-02 21:16:36 +0200 | 
| commit | ccb4cb27e1e44b3d43d8909c3526720ca82c397b (patch) | |
| tree | d9e3f035f0a735aa0563900a79daff1308c6fb00 | |
| parent | 296b081d6ce3781408146aab0c7959b0ba5c3845 (diff) | |
| download | fietsboek-ccb4cb27e1e44b3d43d8909c3526720ca82c397b.tar.gz fietsboek-ccb4cb27e1e44b3d43d8909c3526720ca82c397b.tar.bz2 fietsboek-ccb4cb27e1e44b3d43d8909c3526720ca82c397b.zip  | |
update dependencies (SQLAlchemy 2.0!)
The biggest change in the dependencies is of course SQLAlchemy 2. On the
good side, we didn't need to do many code changes --- in regards to
actual Code, none!
On the better side, we now have way better type checking for SQLAlchemy
models, thanks to SQLAlchemy's integration with mypy (which we now
properly enable). Yay!
That also means though that many type hints needed to be updated, or
rather, the code using the SQL objects. Especially the difference
between Optional things and existing things has been clarified in a few
places, either by using sensible defaults, or by asserting that the
value is not None. That at least gives us an AssertionError instead of
an AttributError.
| -rw-r--r-- | .mypy.ini | 1 | ||||
| -rw-r--r-- | fietsboek/actions.py | 5 | ||||
| -rw-r--r-- | fietsboek/data.py | 13 | ||||
| -rw-r--r-- | fietsboek/hittekaart.py | 7 | ||||
| -rw-r--r-- | fietsboek/models/badge.py | 11 | ||||
| -rw-r--r-- | fietsboek/models/comment.py | 12 | ||||
| -rw-r--r-- | fietsboek/models/image.py | 9 | ||||
| -rw-r--r-- | fietsboek/models/track.py | 108 | ||||
| -rw-r--r-- | fietsboek/models/user.py | 50 | ||||
| -rw-r--r-- | fietsboek/scripts/fietscron.py | 2 | ||||
| -rw-r--r-- | fietsboek/summaries.py | 13 | ||||
| -rw-r--r-- | fietsboek/util.py | 8 | ||||
| -rw-r--r-- | fietsboek/views/browse.py | 81 | ||||
| -rw-r--r-- | poetry.lock | 854 | ||||
| -rw-r--r-- | pyproject.toml | 6 | 
15 files changed, 583 insertions, 597 deletions
@@ -3,6 +3,7 @@ follow_imports = silent  check_untyped_defs = True  allow_redefinition = True  exclude = fietsboek/updater/scripts/.+\.py +plugins = sqlalchemy.ext.mypy.plugin  [mypy-brotli.*]  ignore_missing_imports = True diff --git a/fietsboek/actions.py b/fietsboek/actions.py index 395843f..0aaf2b9 100644 --- a/fietsboek/actions.py +++ b/fietsboek/actions.py @@ -85,6 +85,7 @@ def add_track(      # Save the GPX data      LOGGER.debug("Creating a new data folder for %d", track.id) +    assert track.id is not None      with data_manager.initialize(track.id) as manager:          LOGGER.debug("Saving GPX to %s", manager.gpx_path())          manager.compress_gpx(gpx_data) @@ -244,6 +245,10 @@ def send_verification_token(request: Request, user: models.User):      token = models.Token.generate(user, TokenType.VERIFY_EMAIL)      request.dbsession.add(token) +    if user.email is None: +        LOGGER.error("Trying to send an email to %r (id=%d), but no email is set", user, user.id) +        return +      message = email.prepare_message(          request.config.email_from,          user.email, diff --git a/fietsboek/data.py b/fietsboek/data.py index 9e0d45d..f632076 100644 --- a/fietsboek/data.py +++ b/fietsboek/data.py @@ -294,16 +294,19 @@ class TrackDataDir:      def engrave_metadata(          self, -        title: str, -        description: str, -        author_name: str, -        time: datetime.datetime, +        title: Optional[str], +        description: Optional[str], +        author_name: Optional[str], +        time: Optional[datetime.datetime],          *,          gpx: Optional[gpxpy.gpx.GPX] = None,      ):          """Engrave the given metadata into the GPX file. -        Note that this will erase all existing metadata in the given fields. +        Note that this will overwrite all existing metadata in the given +        fields. + +        If ``None`` is given, it will erase that specific part of the metadata.          :param title: The title of the track.          :param description: The description of the track. diff --git a/fietsboek/hittekaart.py b/fietsboek/hittekaart.py index 69b8d42..3b13042 100644 --- a/fietsboek/hittekaart.py +++ b/fietsboek/hittekaart.py @@ -97,6 +97,8 @@ def generate_for(      The output is saved in the user's data directory using the      ``data_manager``. +    :raises ValueError: If the user does not have an ID and thus the map cannot +        be saved.      :param user: The user for which to generate the map.      :param dbsession: The database session.      :param data_manager: The data manager. @@ -104,10 +106,15 @@ def generate_for(      :param exe_path: See :meth:`generate`.      :param threads: See :meth:`generate`.      """ +    if user.id is None: +        raise ValueError("User has no ID, cannot generate a heatmap yet") +      query = user.all_tracks_query()      query = select(aliased(models.Track, query)).where(query.c.type == TrackType.ORGANIC)      input_paths = []      for track in dbsession.execute(query).scalars(): +        if track.id is None: +            continue          path = data_manager.open(track.id).gpx_path()          input_paths.append(path) diff --git a/fietsboek/models/badge.py b/fietsboek/models/badge.py index 564e0d3..c47ea4b 100644 --- a/fietsboek/models/badge.py +++ b/fietsboek/models/badge.py @@ -1,10 +1,15 @@  """The Badge model.""" +from typing import TYPE_CHECKING +  from pyramid.httpexceptions import HTTPNotFound  from sqlalchemy import Column, Integer, LargeBinary, Text, select -from sqlalchemy.orm import relationship +from sqlalchemy.orm import Mapped, relationship  from .meta import Base +if TYPE_CHECKING: +    from .track import Track +  class Badge(Base):      """Represents a badge. @@ -27,7 +32,9 @@ class Badge(Base):      title = Column(Text)      image = Column(LargeBinary) -    tracks = relationship("Track", secondary="track_badge_assoc", back_populates="badges") +    tracks: Mapped[list["Track"]] = relationship( +        "Track", secondary="track_badge_assoc", back_populates="badges" +    )      @classmethod      def factory(cls, request): diff --git a/fietsboek/models/comment.py b/fietsboek/models/comment.py index 25293d2..d9f9579 100644 --- a/fietsboek/models/comment.py +++ b/fietsboek/models/comment.py @@ -1,9 +1,15 @@  """Comment model.""" +from typing import TYPE_CHECKING +  from sqlalchemy import Column, DateTime, ForeignKey, Integer, Text -from sqlalchemy.orm import relationship +from sqlalchemy.orm import Mapped, relationship  from .meta import Base +if TYPE_CHECKING: +    from .track import Track +    from .user import User +  class Comment(Base):      """Represents a comment on a track. @@ -35,5 +41,5 @@ class Comment(Base):      title = Column(Text)      text = Column(Text) -    author = relationship("User", back_populates="comments") -    track = relationship("Track", back_populates="comments") +    author: Mapped["User"] = relationship("User", back_populates="comments") +    track: Mapped["Track"] = relationship("Track", back_populates="comments") diff --git a/fietsboek/models/image.py b/fietsboek/models/image.py index 1da8aa2..1d741ec 100644 --- a/fietsboek/models/image.py +++ b/fietsboek/models/image.py @@ -3,11 +3,16 @@  The actual image data is saved on disk, we only store the metadata such as an  image description here.  """ +from typing import TYPE_CHECKING +  from sqlalchemy import Column, ForeignKey, Integer, Text, UniqueConstraint, select -from sqlalchemy.orm import relationship +from sqlalchemy.orm import Mapped, relationship  from .meta import Base +if TYPE_CHECKING: +    from .track import Track +  class ImageMetadata(Base):      """Represents metadata for an uploaded image. @@ -31,7 +36,7 @@ class ImageMetadata(Base):      image_name = Column(Text, nullable=False)      description = Column(Text) -    track = relationship("Track", back_populates="images") +    track: Mapped["Track"] = relationship("Track", back_populates="images")      __table_args__ = (UniqueConstraint("track_id", "image_name"),) diff --git a/fietsboek/models/track.py b/fietsboek/models/track.py index 4b85d11..852eb14 100644 --- a/fietsboek/models/track.py +++ b/fietsboek/models/track.py @@ -45,7 +45,7 @@ from sqlalchemy import (      Text,      select,  ) -from sqlalchemy.orm import relationship +from sqlalchemy.orm import Mapped, relationship  from .. import util  from .meta import Base @@ -73,7 +73,7 @@ class Tag(Base):      track_id = Column(Integer, ForeignKey("tracks.id"), primary_key=True)      tag = Column(Text, primary_key=True) -    track = relationship("Track", back_populates="tags") +    track: Mapped["Track"] = relationship("Track", back_populates="tags")  class Visibility(enum.Enum): @@ -204,17 +204,25 @@ class Track(Base):      type = Column(Enum(TrackType))      transformers = Column(JSON) -    owner = relationship("User", back_populates="tracks") -    cache = relationship( +    owner: Mapped["models.User"] = relationship("User", back_populates="tracks") +    cache: Mapped[Optional["TrackCache"]] = relationship(          "TrackCache", back_populates="track", uselist=False, cascade="all, delete-orphan"      ) -    tagged_people = relationship( +    tagged_people: Mapped[list["models.User"]] = relationship(          "User", secondary=track_people_assoc, back_populates="tagged_tracks"      ) -    badges = relationship("Badge", secondary=track_badge_assoc, back_populates="tracks") -    tags = relationship("Tag", back_populates="track", cascade="all, delete-orphan") -    comments = relationship("Comment", back_populates="track", cascade="all, delete-orphan") -    images = relationship("ImageMetadata", back_populates="track", cascade="all, delete-orphan") +    badges: Mapped[list["models.Badge"]] = relationship( +        "Badge", secondary=track_badge_assoc, back_populates="tracks" +    ) +    tags: Mapped[list["Tag"]] = relationship( +        "Tag", back_populates="track", cascade="all, delete-orphan" +    ) +    comments: Mapped[list["models.Comment"]] = relationship( +        "Comment", back_populates="track", cascade="all, delete-orphan" +    ) +    images: Mapped[list["models.ImageMetadata"]] = relationship( +        "ImageMetadata", back_populates="track", cascade="all, delete-orphan" +    )      @classmethod      def factory(cls, request): @@ -285,6 +293,8 @@ class Track(Base):          :return: The aware datetime.          :rtype: datetime.datetime          """ +        if self.date_raw is None: +            return datetime.datetime.utcfromtimestamp(0).replace(tzinfo=datetime.timezone.utc)          if self.date_tz is None:              timezone = datetime.timezone.utc          else: @@ -367,7 +377,7 @@ class Track(Base):          :type text: str          """          for tag in self.tags: -            if tag.tag.lower() == text.lower(): +            if tag.tag and tag.tag.lower() == text.lower():                  return          self.tags.append(Tag(tag=text)) @@ -378,7 +388,7 @@ class Track(Base):          :type text: str          """          for i, tag in enumerate(self.tags): -            if tag.tag.lower() == text.lower(): +            if tag.tag and tag.tag.lower() == text.lower():                  break          else:              return @@ -392,7 +402,7 @@ class Track(Base):          :param tags: The wanted tags.          :type tags: set[str]          """ -        my_tags = {tag.tag.lower() for tag in self.tags} +        my_tags = {tag.tag.lower() for tag in self.tags if tag.tag}          lower_tags = {tag.lower() for tag in tags}          # We cannot use the set difference methods because we want to keep the          # capitalization of the original tags when adding them, but use the @@ -403,7 +413,7 @@ class Track(Base):          to_delete = []          for i, tag in enumerate(self.tags): -            if tag.tag.lower() not in lower_tags: +            if tag.tag and tag.tag.lower() not in lower_tags:                  to_delete.append(i)          for i in to_delete[::-1]:              del self.tags[i] @@ -458,9 +468,9 @@ class TrackWithMetadata:          :return: Length of the track in meters.          """ -        if self.cache is None: +        if self.cache is None or self.cache.length is None:              return self._meta()["length"] -        return self.cache.length +        return float(self.cache.length)      @property      def downhill(self) -> float: @@ -468,9 +478,9 @@ class TrackWithMetadata:          :return: Downhill in meters.          """ -        if self.cache is None: +        if self.cache is None or self.cache.downhill is None:              return self._meta()["downhill"] -        return self.cache.downhill +        return float(self.cache.downhill)      @property      def uphill(self) -> float: @@ -478,9 +488,9 @@ class TrackWithMetadata:          :return: Uphill in meters.          """ -        if self.cache is None: +        if self.cache is None or self.cache.uphill is None:              return self._meta()["uphill"] -        return self.cache.uphill +        return float(self.cache.uphill)      @property      def moving_time(self) -> datetime.timedelta: @@ -488,7 +498,7 @@ class TrackWithMetadata:          :return: Moving time in seconds.          """ -        if self.cache is None: +        if self.cache is None or self.cache.moving_time is None:              value = self._meta()["moving_time"]          else:              value = self.cache.moving_time @@ -500,7 +510,7 @@ class TrackWithMetadata:          :return: Stopped time in seconds.          """ -        if self.cache is None: +        if self.cache is None or self.cache.stopped_time is None:              value = self._meta()["stopped_time"]          else:              value = self.cache.stopped_time @@ -512,9 +522,9 @@ class TrackWithMetadata:          :return: Maximum speed in meters/second.          """ -        if self.cache is None: +        if self.cache is None or self.cache.max_speed is None:              return self._meta()["max_speed"] -        return self.cache.max_speed +        return float(self.cache.max_speed)      @property      def avg_speed(self) -> float: @@ -522,9 +532,9 @@ class TrackWithMetadata:          :return: Average speed in meters/second.          """ -        if self.cache is None: +        if self.cache is None or self.cache.avg_speed is None:              return self._meta()["avg_speed"] -        return self.cache.avg_speed +        return float(self.cache.avg_speed)      @property      def start_time(self) -> datetime.datetime: @@ -534,7 +544,7 @@ class TrackWithMetadata:          :return: Start time.          """ -        if self.cache is None: +        if self.cache is None or self.cache.start_time is None:              return self._meta()["start_time"]          return self.cache.start_time @@ -546,7 +556,7 @@ class TrackWithMetadata:          :return: End time.          """ -        if self.cache is None: +        if self.cache is None or self.cache.end_time is None:              return self._meta()["end_time"]          return self.cache.end_time @@ -598,37 +608,37 @@ class TrackWithMetadata:      # Proxied properties      @property -    def id(self) -> int: +    def id(self) -> Optional[int]:          """ID of the underlying track."""          return self.track.id      @property -    def title(self) -> str: +    def title(self) -> Optional[str]:          """Title of the underlying track."""          return self.track.title      @property -    def description(self) -> str: +    def description(self) -> Optional[str]:          """Description of the underlying track."""          return self.track.description      @property -    def date(self) -> datetime.datetime: +    def date(self) -> Optional[datetime.datetime]:          """Date of the underlying track."""          return self.track.date      @property -    def visibility(self) -> Visibility: +    def visibility(self) -> Optional[Visibility]:          """Visibility of the underlying track."""          return self.track.visibility      @property -    def link_secret(self) -> str: +    def link_secret(self) -> Optional[str]:          """Link secret of the underlying track."""          return self.track.link_secret      @property -    def type(self) -> TrackType: +    def type(self) -> Optional[TrackType]:          """Type of the underlying track."""          return self.track.type @@ -727,15 +737,16 @@ class TrackCache(Base):      end_time_raw = Column(DateTime)      end_time_tz = Column(Integer) -    track = relationship("Track", back_populates="cache") +    track: Mapped["Track"] = relationship("Track", back_populates="cache")      @property -    def start_time(self): +    def start_time(self) -> Optional[datetime.datetime]:          """The time-zone-aware start time of this track.          :return: The aware datetime. -        :rtype: datetime.datetime          """ +        if self.start_time_raw is None: +            return None          if self.start_time_tz is None:              timezone = datetime.timezone.utc          else: @@ -743,25 +754,27 @@ class TrackCache(Base):          return self.start_time_raw.replace(tzinfo=timezone)      @start_time.setter -    def start_time(self, value): +    def start_time(self, value: datetime.datetime):          if value.tzinfo is None:              LOGGER.debug(                  "Non-aware datetime passed (cache_id=%d, value=%s), assuming offset=0", -                self.id or -1, +                self.track_id or -1,                  value,              )              self.start_time_tz = 0          else: -            self.start_time_tz = value.tzinfo.utcoffset(value).total_seconds() // 60 +            utcoffset = value.tzinfo.utcoffset(value) or datetime.timedelta() +            self.start_time_tz = int(utcoffset.total_seconds() // 60)          self.start_time_raw = value.replace(tzinfo=None)      @property -    def end_time(self): +    def end_time(self) -> Optional[datetime.datetime]:          """The time-zone-aware end time of this track.          :return: The aware datetime. -        :rtype: datetime.datetime          """ +        if self.end_time_raw is None: +            return None          if self.end_time_tz is None:              timezone = datetime.timezone.utc          else: @@ -769,16 +782,17 @@ class TrackCache(Base):          return self.end_time_raw.replace(tzinfo=timezone)      @end_time.setter -    def end_time(self, value): +    def end_time(self, value: datetime.datetime):          if value.tzinfo is None:              LOGGER.debug(                  "Non-aware datetime passed (cache_id=%d, value=%s), assuming offset=0", -                self.id or -1, +                self.track_id or -1,                  value,              )              self.end_time_tz = 0          else: -            self.end_time_tz = value.tzinfo.utcoffset(value).total_seconds() // 60 +            utcoffset = value.tzinfo.utcoffset(value) or datetime.timedelta() +            self.end_time_tz = int(utcoffset.total_seconds() // 60)          self.end_time_raw = value.replace(tzinfo=None) @@ -807,7 +821,7 @@ class Upload(Base):      owner_id = Column(Integer, ForeignKey("users.id"))      gpx = Column(LargeBinary) -    owner = relationship("User", back_populates="uploads") +    owner: Mapped["models.User"] = relationship("User", back_populates="uploads")      @classmethod      def factory(cls, request): @@ -838,7 +852,7 @@ class Upload(Base):      @property      def gpx_data(self):          """Access the decompressed gpx data.""" -        return gzip.decompress(self.gpx) +        return gzip.decompress(self.gpx or b"")      @gpx_data.setter      def gpx_data(self, value): diff --git a/fietsboek/models/user.py b/fietsboek/models/user.py index 4201d14..96a31c0 100644 --- a/fietsboek/models/user.py +++ b/fietsboek/models/user.py @@ -4,6 +4,7 @@ import enum  import secrets  import uuid  from functools import reduce +from typing import TYPE_CHECKING  from cryptography.exceptions import InvalidKey  from cryptography.hazmat.primitives.kdf.scrypt import Scrypt @@ -27,12 +28,16 @@ from sqlalchemy import (      select,      union,  ) -from sqlalchemy.orm import relationship, with_parent +from sqlalchemy.orm import Mapped, relationship, with_parent  from sqlalchemy.orm.attributes import flag_dirty  from sqlalchemy.orm.session import object_session  from .meta import Base +if TYPE_CHECKING: +    from .comment import Comment +    from .track import Track, Upload +  class PasswordMismatch(Exception):      """Exception that is raised if the passwords mismatch. @@ -105,22 +110,30 @@ class User(Base):      is_admin = Column(Boolean, default=False)      is_verified = Column(Boolean, default=False) -    tracks = relationship("Track", back_populates="owner", cascade="all, delete-orphan") -    tagged_tracks = relationship( +    tracks: Mapped[list["Track"]] = relationship( +        "Track", back_populates="owner", cascade="all, delete-orphan" +    ) +    tagged_tracks: Mapped[list["Track"]] = relationship(          "Track", secondary="track_people_assoc", back_populates="tagged_people"      ) -    uploads = relationship("Upload", back_populates="owner", cascade="all, delete-orphan") -    tokens = relationship("Token", back_populates="user", cascade="all, delete-orphan") -    comments = relationship("Comment", back_populates="author", cascade="all, delete-orphan") +    uploads: Mapped[list["Upload"]] = relationship( +        "Upload", back_populates="owner", cascade="all, delete-orphan" +    ) +    tokens: Mapped[list["Token"]] = relationship( +        "Token", back_populates="user", cascade="all, delete-orphan" +    ) +    comments: Mapped[list["Comment"]] = relationship( +        "Comment", back_populates="author", cascade="all, delete-orphan" +    )      # We don't use them, but include them to ensure our cascading works -    friends_1 = relationship( +    friends_1: Mapped[list["User"]] = relationship(          "User",          secondary="friends_assoc",          back_populates="friends_2",          foreign_keys=[friends_assoc.c.user_1_id],      ) -    friends_2 = relationship( +    friends_2: Mapped[list["User"]] = relationship(          "User",          secondary="friends_assoc",          back_populates="friends_1", @@ -193,9 +206,9 @@ class User(Base):          :type password: str          """          password = password.encode("utf-8") -        scrypt = Scrypt(salt=self.salt, **SCRYPT_PARAMETERS) +        scrypt = Scrypt(salt=self.salt or b"", **SCRYPT_PARAMETERS)          try: -            scrypt.verify(password, self.password) +            scrypt.verify(password, self.password or b"")          except InvalidKey:              raise PasswordMismatch from None @@ -325,8 +338,10 @@ class User(Base):          :return: All friends of this user.          :rtype: list[User]          """ +        session = object_session(self) +        assert session          query = select(User).from_statement(self._friend_query()) -        yield from object_session(self).execute(query).scalars() +        yield from session.execute(query).scalars()      def remove_friend(self, friend):          """Remove the friend relationship between two users. @@ -335,6 +350,7 @@ class User(Base):          :type friend: User          """          session = object_session(self) +        assert session          session.execute(delete(friends_assoc).filter_by(user_1_id=self.id, user_2_id=friend.id))          session.execute(delete(friends_assoc).filter_by(user_1_id=friend.id, user_2_id=self.id))          flag_dirty(self) @@ -345,11 +361,13 @@ class User(Base):          :param friend: The user to befriend.          :type friend: User          """ +        session = object_session(self) +        assert session          if self.id > friend.id:              friend.add_friend(self)              return          stmt = friends_assoc.insert().values(user_1_id=self.id, user_2_id=friend.id) -        object_session(self).execute(stmt) +        session.execute(stmt)      def autocomplete_tags(self):          """Returns all tags the user has ever used, suitable for autocompletion @@ -388,10 +406,10 @@ class FriendRequest(Base):      recipient_id = Column(Integer, ForeignKey("users.id"))      date = Column(DateTime) -    sender = relationship( +    sender: Mapped["User"] = relationship(          "User", primaryjoin="User.id == FriendRequest.sender_id", backref="outgoing_requests"      ) -    recipient = relationship( +    recipient: Mapped["User"] = relationship(          "User", primaryjoin="User.id == FriendRequest.recipient_id", backref="incoming_requests"      ) @@ -443,7 +461,7 @@ class Token(Base):      token_type = Column(Enum(TokenType))      date = Column(DateTime) -    user = relationship("User", back_populates="tokens") +    user: Mapped["User"] = relationship("User", back_populates="tokens")      @classmethod      def generate(cls, user, token_type): @@ -462,6 +480,8 @@ class Token(Base):      def age(self) -> datetime.timedelta:          """Returns the age of the token.""" +        if self.date is None: +            return datetime.timedelta()          return abs(datetime.datetime.utcnow() - self.date) diff --git a/fietsboek/scripts/fietscron.py b/fietsboek/scripts/fietscron.py index 417b188..e641ac7 100644 --- a/fietsboek/scripts/fietscron.py +++ b/fietsboek/scripts/fietscron.py @@ -86,6 +86,7 @@ def rebuild_cache(engine: Engine, data_manager: DataManager):      )      with session:          for track in session.execute(needed_rebuilds).scalars(): +            assert track.id is not None              LOGGER.info("Rebuilding cache for track %d", track.id)              gpx_data = data_manager.open(track.id).decompress_gpx()              track.ensure_cache(gpx_data) @@ -159,6 +160,7 @@ def refill_queue(session: Session, redis: Redis):      """Refills the low-priority hittekaart queue by adding all users to it."""      LOGGER.debug("Refilling low-priority queue")      for user in session.execute(select(models.User)).scalars(): +        assert user.id is not None          redis.sadd("hittekaart:queue:low", user.id) diff --git a/fietsboek/summaries.py b/fietsboek/summaries.py index ac94e92..126091f 100644 --- a/fietsboek/summaries.py +++ b/fietsboek/summaries.py @@ -38,9 +38,12 @@ class Summary:          This automatically inserts the track into the right yearly summary. +        :raises ValueError: If the given track has no date set.          :param track: The track to insert.          :type track: fietsboek.model.track.Track          """ +        if track.date is None: +            raise ValueError("Cannot add a track without date")          year = track.date.year          self.years.setdefault(year, YearSummary(year, self.ascending)).add(track) @@ -88,8 +91,11 @@ class YearSummary:          This automatically inserts the track into the right monthly summary. +        :raises ValueError: If the given track has no date set.          :param track: The track to insert.          """ +        if track.date is None: +            raise ValueError("Cannot add a track without date")          month = track.date.month          self.months.setdefault(month, MonthSummary(month)).add(track) @@ -115,7 +121,9 @@ class MonthSummary:      def __iter__(self):          items = self.tracks[:] -        items.sort(key=lambda t: t.date) +        # We know that sorting by date works, we even assert that all tracks +        # have a date set. +        items.sort(key=lambda t: t.date)  # type: ignore          return iter(items)      def __len__(self) -> int: @@ -131,8 +139,11 @@ class MonthSummary:      def add(self, track: TrackWithMetadata):          """Add a track to the summary. +        :raises ValueError: If the given track has no date set.          :param track: The track to insert.          """ +        if track.date is None: +            raise ValueError("Cannot add a track without date")          self.tracks.append(track)      @property diff --git a/fietsboek/util.py b/fietsboek/util.py index 04f5551..625da49 100644 --- a/fietsboek/util.py +++ b/fietsboek/util.py @@ -6,7 +6,7 @@ import os  import re  import secrets  import unicodedata -from typing import List, Optional, Union +from typing import List, Optional, TypeVar, Union  import babel  import gpxpy @@ -20,6 +20,8 @@ from pyramid.i18n import TranslationString as _  from pyramid.request import Request  from sqlalchemy import select +T = TypeVar("T") +  ALLOWED_TAGS = (      # Those were the bleach defaults, they worked fine      {"a", "abbr", "acronym", "b", "blockquote", "code", "em", "i", "li", "ol", "strong", "ul"} @@ -251,10 +253,10 @@ def random_link_secret(nbytes: int = 20) -> str:  def retrieve_multiple(      dbsession: "sqlalchemy.orm.session.Session", -    model: type, +    model: type[T],      params: "webob.multidict.NestedMultiDict",      name: str, -) -> list: +) -> list[T]:      """Parses a reply to retrieve multiple database objects.      This is usable for arrays sent by HTML forms, for example to retrieve all diff --git a/fietsboek/views/browse.py b/fietsboek/views/browse.py index 1e97187..d4f48b7 100644 --- a/fietsboek/views/browse.py +++ b/fietsboek/views/browse.py @@ -11,15 +11,16 @@ from pyramid.request import Request  from pyramid.response import Response  from pyramid.view import view_config  from sqlalchemy import func, or_, select -from sqlalchemy.orm import DeclarativeMeta, aliased -from sqlalchemy.orm.util import AliasedClass -from sqlalchemy.sql import Selectable +from sqlalchemy.orm import aliased +from sqlalchemy.sql import Select  from .. import models, util  from ..models.track import TrackType, TrackWithMetadata  T = TypeVar("T", bound=Enum) +AliasedTrack = type[models.Track] +  class Stream(RawIOBase):      """A :class:`Stream` represents an in-memory buffered FIFO. @@ -82,9 +83,7 @@ class ResultOrder(Enum):  class Filter:      """A class representing a filter that the user can apply to the track list.""" -    def compile( -        self, query: Selectable, track: AliasedClass, track_cache: type[DeclarativeMeta] -    ) -> Selectable: +    def compile(self, query: Select, track: AliasedTrack) -> Select:          """Compile the filter into the SQL query.          Returns the modified query. @@ -94,7 +93,6 @@ class Filter:          :param query: The original query to be modified, selecting over all tracks.          :param track: The track mapper. -        :param track_cache: The track cache mapper.          :return: The modified query.          """          # pylint: disable=unused-argument @@ -114,16 +112,14 @@ class LambdaFilter(Filter):      def __init__(          self, -        compiler: Callable[[Selectable, AliasedClass, type[DeclarativeMeta]], Selectable], +        compiler: Callable[[Select, AliasedTrack], Select],          matcher: Callable[[TrackWithMetadata], bool],      ):          self.compiler = compiler          self.matcher = matcher -    def compile( -        self, query: Selectable, track: AliasedClass, track_cache: type[DeclarativeMeta] -    ) -> Selectable: -        return self.compiler(query, track, track_cache) +    def compile(self, query: Select, track: AliasedTrack) -> Select: +        return self.compiler(query, track)      def apply(self, track: TrackWithMetadata) -> bool:          return self.matcher(track) @@ -135,15 +131,15 @@ class SearchFilter(Filter):      def __init__(self, search_terms: Iterable[str]):          self.search_terms = search_terms -    def compile( -        self, query: Selectable, track: AliasedClass, track_cache: type[DeclarativeMeta] -    ) -> Selectable: +    def compile(self, query: Select, track: AliasedTrack) -> Select:          for term in self.search_terms:              term = term.lower()              query = query.where(func.lower(track.title).contains(term))          return query      def apply(self, track: TrackWithMetadata) -> bool: +        if track.title is None: +            return True          return all(term.lower() in track.title.lower() for term in self.search_terms) @@ -153,9 +149,7 @@ class TagFilter(Filter):      def __init__(self, tags: Iterable[str]):          self.tags = tags -    def compile( -        self, query: Selectable, track: AliasedClass, track_cache: type[DeclarativeMeta] -    ) -> Selectable: +    def compile(self, query: Select, track: AliasedTrack) -> Select:          lower_tags = [tag.lower() for tag in self.tags]          for tag in lower_tags:              exists_query = ( @@ -179,9 +173,7 @@ class PersonFilter(Filter):      def __init__(self, names: Iterable[str]):          self.names = names -    def compile( -        self, query: Selectable, track: AliasedClass, track_cache: type[DeclarativeMeta] -    ) -> Selectable: +    def compile(self, query: Select, track: AliasedTrack) -> Select:          lower_names = [name.lower() for name in self.names]          for name in lower_names:              tpa = models.track.track_people_assoc @@ -202,8 +194,11 @@ class PersonFilter(Filter):          return query      def apply(self, track: TrackWithMetadata) -> bool: -        lower_names = {person.name.lower() for person in track.tagged_people} -        lower_names.add(track.owner.name.lower()) +        lower_names = { +            person.name.lower() for person in track.tagged_people if person.name is not None +        } +        if track.owner and track.owner.name is not None: +            lower_names.add(track.owner.name.lower())          return all(name.lower() in lower_names for name in self.names) @@ -213,9 +208,7 @@ class UserTaggedFilter(Filter):      def __init__(self, user: models.User):          self.user = user -    def compile( -        self, query: Selectable, track: AliasedClass, track_cache: type[DeclarativeMeta] -    ) -> Selectable: +    def compile(self, query: Select, track: AliasedTrack) -> Select:          tpa = models.track.track_people_assoc          return query.where(              or_( @@ -242,11 +235,9 @@ class FilterCollection(Filter):      def __bool__(self):          return bool(self._filters) -    def compile( -        self, query: Selectable, track: AliasedClass, track_cache: type[DeclarativeMeta] -    ) -> Selectable: +    def compile(self, query: Select, track: AliasedTrack) -> Select:          for filty in self._filters: -            query = filty.compile(query, track, track_cache) +            query = filty.compile(query, track)          return query      def apply(self, track: TrackWithMetadata) -> bool: @@ -281,10 +272,10 @@ class FilterCollection(Filter):              min_length = _get_int(request, "min-length") * 1000              filters.append(                  LambdaFilter( -                    lambda query, track, track_cache: query.where( +                    lambda query, track: query.where(                          or_( -                            track_cache.length >= min_length, -                            track_cache.length == None,  # noqa: E711 +                            models.TrackCache.length >= min_length, +                            models.TrackCache.length == None,  # noqa: E711                          )                      ),                      lambda track: track.length >= min_length, @@ -295,10 +286,10 @@ class FilterCollection(Filter):              max_length = _get_int(request, "max-length") * 1000              filters.append(                  LambdaFilter( -                    lambda query, track, track_cache: query.where( +                    lambda query, track: query.where(                          or_( -                            track_cache.length <= max_length, -                            track_cache.length == None,  # noqa: E711 +                            models.TrackCache.length <= max_length, +                            models.TrackCache.length == None,  # noqa: E711                          )                      ),                      lambda track: track.length <= max_length, @@ -310,8 +301,8 @@ class FilterCollection(Filter):              min_date = datetime.datetime.combine(min_date, datetime.time.min)              filters.append(                  LambdaFilter( -                    lambda query, track, track_cache: query.where(track.date_raw >= min_date), -                    lambda track: track.date.replace(tzinfo=None) >= min_date, +                    lambda query, track: query.where(track.date_raw >= min_date), +                    lambda track: track.date is None or track.date.replace(tzinfo=None) >= min_date,                  )              ) @@ -320,15 +311,15 @@ class FilterCollection(Filter):              max_date = datetime.datetime.combine(max_date, datetime.time.max)              filters.append(                  LambdaFilter( -                    lambda query, track, track_cache: query.where(track.date_raw <= max_date), -                    lambda track: track.date.replace(tzinfo=None) <= max_date, +                    lambda query, track: query.where(track.date_raw <= max_date), +                    lambda track: track.date is None or track.date.replace(tzinfo=None) <= max_date,                  )              )          if "mine" in request.params.getall("show-only[]"):              filters.append(                  LambdaFilter( -                    lambda query, track, track_cache: query.where(track.owner == request.identity), +                    lambda query, track: query.where(track.owner == request.identity),                      lambda track: track.owner == request.identity,                  )              ) @@ -337,7 +328,7 @@ class FilterCollection(Filter):              friend_ids = {friend.id for friend in request.identity.get_friends()}              filters.append(                  LambdaFilter( -                    lambda query, track, track_cache: query.where(track.owner_id.in_(friend_ids)), +                    lambda query, track: query.where(track.owner_id.in_(friend_ids)),                      lambda track: track.owner in request.identity.get_friends(),                  )              ) @@ -349,7 +340,7 @@ class FilterCollection(Filter):              types = {_get_enum(TrackType, value) for value in request.params.getall("type[]")}              filters.append(                  LambdaFilter( -                    lambda query, track, track_cache: query.where(track.type.in_(types)), +                    lambda query, track: query.where(track.type.in_(types)),                      lambda track: track.type in types,                  )              ) @@ -357,7 +348,7 @@ class FilterCollection(Filter):          return cls(filters) -def apply_order(query: Selectable, track: AliasedClass, order: ResultOrder) -> Selectable: +def apply_order(query: Select, track: AliasedTrack, order: ResultOrder) -> Select:      """Applies a ``ORDER BY`` clause to the query.      :raises ValueError: If the given order does not exist. @@ -401,7 +392,7 @@ def browse(request: Request) -> Response:      # Build our query      query = select(track).join(models.TrackCache, isouter=True) -    query = filters.compile(query, track, models.TrackCache) +    query = filters.compile(query, track)      order = ResultOrder.DATE_DESC      if request.params.get("sort"): diff --git a/poetry.lock b/poetry.lock index 2ce66c8..931e4c1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.0 and should not be changed by hand.  [[package]]  name = "alabaster"  version = "0.7.13"  description = "A configurable sidebar-enabled Sphinx theme" -category = "dev"  optional = false  python-versions = ">=3.6"  files = [ @@ -14,14 +13,13 @@ files = [  [[package]]  name = "alembic" -version = "1.10.3" +version = "1.11.1"  description = "A database migration tool for SQLAlchemy." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "alembic-1.10.3-py3-none-any.whl", hash = "sha256:b2e0a6cfd3a8ce936a1168320bcbe94aefa3f4463cd773a968a55071beb3cd37"}, -    {file = "alembic-1.10.3.tar.gz", hash = "sha256:32a69b13a613aeb7e8093f242da60eff9daed13c0df02fff279c1b06c32965d2"}, +    {file = "alembic-1.11.1-py3-none-any.whl", hash = "sha256:dc871798a601fab38332e38d6ddb38d5e734f60034baeb8e2db5b642fccd8ab8"}, +    {file = "alembic-1.11.1.tar.gz", hash = "sha256:6a810a6b012c88b33458fceb869aef09ac75d6ace5291915ba7fae44de372c01"},  ]  [package.dependencies] @@ -34,14 +32,13 @@ tz = ["python-dateutil"]  [[package]]  name = "astroid" -version = "2.15.3" +version = "2.15.5"  description = "An abstract syntax tree for Python with inference support." -category = "dev"  optional = false  python-versions = ">=3.7.2"  files = [ -    {file = "astroid-2.15.3-py3-none-any.whl", hash = "sha256:f11e74658da0f2a14a8d19776a8647900870a63de71db83713a8e77a6af52662"}, -    {file = "astroid-2.15.3.tar.gz", hash = "sha256:44224ad27c54d770233751315fa7f74c46fa3ee0fab7beef1065f99f09897efe"}, +    {file = "astroid-2.15.5-py3-none-any.whl", hash = "sha256:078e5212f9885fa85fbb0cf0101978a336190aadea6e13305409d099f71b2324"}, +    {file = "astroid-2.15.5.tar.gz", hash = "sha256:1039262575027b441137ab4a62a793a9b43defb42c32d5670f38686207cd780f"},  ]  [package.dependencies] @@ -56,7 +53,6 @@ wrapt = [  name = "async-timeout"  version = "4.0.2"  description = "Timeout context manager for asyncio programs" -category = "main"  optional = false  python-versions = ">=3.6"  files = [ @@ -68,7 +64,6 @@ files = [  name = "babel"  version = "2.12.1"  description = "Internationalization utilities" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -80,7 +75,6 @@ files = [  name = "beautifulsoup4"  version = "4.12.2"  description = "Screen-scraping library" -category = "dev"  optional = false  python-versions = ">=3.6.0"  files = [ @@ -99,7 +93,6 @@ lxml = ["lxml"]  name = "black"  version = "23.3.0"  description = "The uncompromising code formatter." -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -149,7 +142,6 @@ uvloop = ["uvloop (>=0.15.2)"]  name = "brotli"  version = "1.0.9"  description = "Python bindings for the Brotli compression library" -category = "main"  optional = false  python-versions = "*"  files = [ @@ -239,21 +231,19 @@ files = [  [[package]]  name = "certifi" -version = "2022.12.7" +version = "2023.5.7"  description = "Python package for providing Mozilla's CA Bundle." -category = "main"  optional = false  python-versions = ">=3.6"  files = [ -    {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, -    {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, +    {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, +    {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},  ]  [[package]]  name = "cffi"  version = "1.15.1"  description = "Foreign Function Interface for Python calling C code." -category = "main"  optional = false  python-versions = "*"  files = [ @@ -330,7 +320,6 @@ pycparser = "*"  name = "charset-normalizer"  version = "3.1.0"  description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main"  optional = false  python-versions = ">=3.7.0"  files = [ @@ -415,7 +404,6 @@ files = [  name = "click"  version = "8.1.3"  description = "Composable command line interface toolkit" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -430,7 +418,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}  name = "click-option-group"  version = "0.5.5"  description = "Option groups missing in Click" -category = "main"  optional = false  python-versions = ">=3.6,<4"  files = [ @@ -450,7 +437,6 @@ tests-cov = ["coverage (<6)", "coveralls", "pytest", "pytest-cov"]  name = "colorama"  version = "0.4.6"  description = "Cross-platform colored terminal text." -category = "main"  optional = false  python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"  files = [ @@ -460,63 +446,71 @@ files = [  [[package]]  name = "coverage" -version = "7.2.3" +version = "7.2.7"  description = "Code coverage measurement for Python" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "coverage-7.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e58c0d41d336569d63d1b113bd573db8363bc4146f39444125b7f8060e4e04f5"}, -    {file = "coverage-7.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:344e714bd0fe921fc72d97404ebbdbf9127bac0ca1ff66d7b79efc143cf7c0c4"}, -    {file = "coverage-7.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974bc90d6f6c1e59ceb1516ab00cf1cdfbb2e555795d49fa9571d611f449bcb2"}, -    {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0743b0035d4b0e32bc1df5de70fba3059662ace5b9a2a86a9f894cfe66569013"}, -    {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d0391fb4cfc171ce40437f67eb050a340fdbd0f9f49d6353a387f1b7f9dd4fa"}, -    {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a42e1eff0ca9a7cb7dc9ecda41dfc7cbc17cb1d02117214be0561bd1134772b"}, -    {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be19931a8dcbe6ab464f3339966856996b12a00f9fe53f346ab3be872d03e257"}, -    {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72fcae5bcac3333a4cf3b8f34eec99cea1187acd55af723bcbd559adfdcb5535"}, -    {file = "coverage-7.2.3-cp310-cp310-win32.whl", hash = "sha256:aeae2aa38395b18106e552833f2a50c27ea0000122bde421c31d11ed7e6f9c91"}, -    {file = "coverage-7.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:83957d349838a636e768251c7e9979e899a569794b44c3728eaebd11d848e58e"}, -    {file = "coverage-7.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfd393094cd82ceb9b40df4c77976015a314b267d498268a076e940fe7be6b79"}, -    {file = "coverage-7.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:182eb9ac3f2b4874a1f41b78b87db20b66da6b9cdc32737fbbf4fea0c35b23fc"}, -    {file = "coverage-7.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bb1e77a9a311346294621be905ea8a2c30d3ad371fc15bb72e98bfcfae532df"}, -    {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca0f34363e2634deffd390a0fef1aa99168ae9ed2af01af4a1f5865e362f8623"}, -    {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55416d7385774285b6e2a5feca0af9652f7f444a4fa3d29d8ab052fafef9d00d"}, -    {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:06ddd9c0249a0546997fdda5a30fbcb40f23926df0a874a60a8a185bc3a87d93"}, -    {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fff5aaa6becf2c6a1699ae6a39e2e6fb0672c2d42eca8eb0cafa91cf2e9bd312"}, -    {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ea53151d87c52e98133eb8ac78f1206498c015849662ca8dc246255265d9c3c4"}, -    {file = "coverage-7.2.3-cp311-cp311-win32.whl", hash = "sha256:8f6c930fd70d91ddee53194e93029e3ef2aabe26725aa3c2753df057e296b925"}, -    {file = "coverage-7.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:fa546d66639d69aa967bf08156eb8c9d0cd6f6de84be9e8c9819f52ad499c910"}, -    {file = "coverage-7.2.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2317d5ed777bf5a033e83d4f1389fd4ef045763141d8f10eb09a7035cee774c"}, -    {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be9824c1c874b73b96288c6d3de793bf7f3a597770205068c6163ea1f326e8b9"}, -    {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3b2803e730dc2797a017335827e9da6da0e84c745ce0f552e66400abdfb9a1"}, -    {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f69770f5ca1994cb32c38965e95f57504d3aea96b6c024624fdd5bb1aa494a1"}, -    {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1127b16220f7bfb3f1049ed4a62d26d81970a723544e8252db0efde853268e21"}, -    {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa784405f0c640940595fa0f14064d8e84aff0b0f762fa18393e2760a2cf5841"}, -    {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3146b8e16fa60427e03884301bf8209221f5761ac754ee6b267642a2fd354c48"}, -    {file = "coverage-7.2.3-cp37-cp37m-win32.whl", hash = "sha256:1fd78b911aea9cec3b7e1e2622c8018d51c0d2bbcf8faaf53c2497eb114911c1"}, -    {file = "coverage-7.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f3736a5d34e091b0a611964c6262fd68ca4363df56185902528f0b75dbb9c1f"}, -    {file = "coverage-7.2.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:981b4df72c93e3bc04478153df516d385317628bd9c10be699c93c26ddcca8ab"}, -    {file = "coverage-7.2.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0045f8f23a5fb30b2eb3b8a83664d8dc4fb58faddf8155d7109166adb9f2040"}, -    {file = "coverage-7.2.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f760073fcf8f3d6933178d67754f4f2d4e924e321f4bb0dcef0424ca0215eba1"}, -    {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c86bd45d1659b1ae3d0ba1909326b03598affbc9ed71520e0ff8c31a993ad911"}, -    {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:172db976ae6327ed4728e2507daf8a4de73c7cc89796483e0a9198fd2e47b462"}, -    {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d2a3a6146fe9319926e1d477842ca2a63fe99af5ae690b1f5c11e6af074a6b5c"}, -    {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f649dd53833b495c3ebd04d6eec58479454a1784987af8afb77540d6c1767abd"}, -    {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c4ed4e9f3b123aa403ab424430b426a1992e6f4c8fd3cb56ea520446e04d152"}, -    {file = "coverage-7.2.3-cp38-cp38-win32.whl", hash = "sha256:eb0edc3ce9760d2f21637766c3aa04822030e7451981ce569a1b3456b7053f22"}, -    {file = "coverage-7.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:63cdeaac4ae85a179a8d6bc09b77b564c096250d759eed343a89d91bce8b6367"}, -    {file = "coverage-7.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:20d1a2a76bb4eb00e4d36b9699f9b7aba93271c9c29220ad4c6a9581a0320235"}, -    {file = "coverage-7.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ea748802cc0de4de92ef8244dd84ffd793bd2e7be784cd8394d557a3c751e21"}, -    {file = "coverage-7.2.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21b154aba06df42e4b96fc915512ab39595105f6c483991287021ed95776d934"}, -    {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd214917cabdd6f673a29d708574e9fbdb892cb77eb426d0eae3490d95ca7859"}, -    {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2e58e45fe53fab81f85474e5d4d226eeab0f27b45aa062856c89389da2f0d9"}, -    {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:87ecc7c9a1a9f912e306997ffee020297ccb5ea388421fe62a2a02747e4d5539"}, -    {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:387065e420aed3c71b61af7e82c7b6bc1c592f7e3c7a66e9f78dd178699da4fe"}, -    {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ea3f5bc91d7d457da7d48c7a732beaf79d0c8131df3ab278e6bba6297e23c6c4"}, -    {file = "coverage-7.2.3-cp39-cp39-win32.whl", hash = "sha256:ae7863a1d8db6a014b6f2ff9c1582ab1aad55a6d25bac19710a8df68921b6e30"}, -    {file = "coverage-7.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:3f04becd4fcda03c0160d0da9c8f0c246bc78f2f7af0feea1ec0930e7c93fa4a"}, -    {file = "coverage-7.2.3-pp37.pp38.pp39-none-any.whl", hash = "sha256:965ee3e782c7892befc25575fa171b521d33798132692df428a09efacaffe8d0"}, -    {file = "coverage-7.2.3.tar.gz", hash = "sha256:d298c2815fa4891edd9abe5ad6e6cb4207104c7dd9fd13aea3fdebf6f9b91259"}, +    {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"}, +    {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"}, +    {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"}, +    {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"}, +    {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"}, +    {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"}, +    {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"}, +    {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"}, +    {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"}, +    {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"}, +    {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"}, +    {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"}, +    {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"}, +    {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"}, +    {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"}, +    {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"}, +    {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"}, +    {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"}, +    {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"}, +    {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"}, +    {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"}, +    {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"}, +    {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"}, +    {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"}, +    {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"}, +    {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"}, +    {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"}, +    {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"}, +    {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"}, +    {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"}, +    {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"}, +    {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"}, +    {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"}, +    {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"}, +    {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"}, +    {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"}, +    {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"}, +    {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"}, +    {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"}, +    {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"}, +    {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"}, +    {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"}, +    {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"}, +    {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"}, +    {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"}, +    {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"}, +    {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"}, +    {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"}, +    {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"}, +    {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"}, +    {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"}, +    {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"}, +    {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"}, +    {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"}, +    {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"}, +    {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"}, +    {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"}, +    {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"}, +    {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"}, +    {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"},  ]  [package.dependencies] @@ -527,31 +521,30 @@ toml = ["tomli"]  [[package]]  name = "cryptography" -version = "40.0.2" +version = "41.0.1"  description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main"  optional = false -python-versions = ">=3.6" +python-versions = ">=3.7"  files = [ -    {file = "cryptography-40.0.2-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:8f79b5ff5ad9d3218afb1e7e20ea74da5f76943ee5edb7f76e56ec5161ec782b"}, -    {file = "cryptography-40.0.2-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:05dc219433b14046c476f6f09d7636b92a1c3e5808b9a6536adf4932b3b2c440"}, -    {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4df2af28d7bedc84fe45bd49bc35d710aede676e2a4cb7fc6d103a2adc8afe4d"}, -    {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dcca15d3a19a66e63662dc8d30f8036b07be851a8680eda92d079868f106288"}, -    {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a04386fb7bc85fab9cd51b6308633a3c271e3d0d3eae917eebab2fac6219b6d2"}, -    {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:adc0d980fd2760c9e5de537c28935cc32b9353baaf28e0814df417619c6c8c3b"}, -    {file = "cryptography-40.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d5a1bd0e9e2031465761dfa920c16b0065ad77321d8a8c1f5ee331021fda65e9"}, -    {file = "cryptography-40.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a95f4802d49faa6a674242e25bfeea6fc2acd915b5e5e29ac90a32b1139cae1c"}, -    {file = "cryptography-40.0.2-cp36-abi3-win32.whl", hash = "sha256:aecbb1592b0188e030cb01f82d12556cf72e218280f621deed7d806afd2113f9"}, -    {file = "cryptography-40.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:b12794f01d4cacfbd3177b9042198f3af1c856eedd0a98f10f141385c809a14b"}, -    {file = "cryptography-40.0.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:142bae539ef28a1c76794cca7f49729e7c54423f615cfd9b0b1fa90ebe53244b"}, -    {file = "cryptography-40.0.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:956ba8701b4ffe91ba59665ed170a2ebbdc6fc0e40de5f6059195d9f2b33ca0e"}, -    {file = "cryptography-40.0.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f01c9863da784558165f5d4d916093737a75203a5c5286fde60e503e4276c7a"}, -    {file = "cryptography-40.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3daf9b114213f8ba460b829a02896789751626a2a4e7a43a28ee77c04b5e4958"}, -    {file = "cryptography-40.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48f388d0d153350f378c7f7b41497a54ff1513c816bcbbcafe5b829e59b9ce5b"}, -    {file = "cryptography-40.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c0764e72b36a3dc065c155e5b22f93df465da9c39af65516fe04ed3c68c92636"}, -    {file = "cryptography-40.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:cbaba590180cba88cb99a5f76f90808a624f18b169b90a4abb40c1fd8c19420e"}, -    {file = "cryptography-40.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7a38250f433cd41df7fcb763caa3ee9362777fdb4dc642b9a349721d2bf47404"}, -    {file = "cryptography-40.0.2.tar.gz", hash = "sha256:c33c0d32b8594fa647d2e01dbccc303478e16fdd7cf98652d5b3ed11aa5e5c99"}, +    {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:f73bff05db2a3e5974a6fd248af2566134d8981fd7ab012e5dd4ddb1d9a70699"}, +    {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:1a5472d40c8f8e91ff7a3d8ac6dfa363d8e3138b961529c996f3e2df0c7a411a"}, +    {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fa01527046ca5facdf973eef2535a27fec4cb651e4daec4d043ef63f6ecd4ca"}, +    {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b46e37db3cc267b4dea1f56da7346c9727e1209aa98487179ee8ebed09d21e43"}, +    {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d198820aba55660b4d74f7b5fd1f17db3aa5eb3e6893b0a41b75e84e4f9e0e4b"}, +    {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:948224d76c4b6457349d47c0c98657557f429b4e93057cf5a2f71d603e2fc3a3"}, +    {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db"}, +    {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b4ceb5324b998ce2003bc17d519080b4ec8d5b7b70794cbd2836101406a9be31"}, +    {file = "cryptography-41.0.1-cp37-abi3-win32.whl", hash = "sha256:8f4ab7021127a9b4323537300a2acfb450124b2def3756f64dc3a3d2160ee4b5"}, +    {file = "cryptography-41.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:1fee5aacc7367487b4e22484d3c7e547992ed726d14864ee33c0176ae43b0d7c"}, +    {file = "cryptography-41.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9a6c7a3c87d595608a39980ebaa04d5a37f94024c9f24eb7d10262b92f739ddb"}, +    {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5d092fdfedaec4cbbffbf98cddc915ba145313a6fdaab83c6e67f4e6c218e6f3"}, +    {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a8e6c2de6fbbcc5e14fd27fb24414507cb3333198ea9ab1258d916f00bc3039"}, +    {file = "cryptography-41.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb33ccf15e89f7ed89b235cff9d49e2e62c6c981a6061c9c8bb47ed7951190bc"}, +    {file = "cryptography-41.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f0ff6e18d13a3de56f609dd1fd11470918f770c6bd5d00d632076c727d35485"}, +    {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7bfc55a5eae8b86a287747053140ba221afc65eb06207bedf6e019b8934b477c"}, +    {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eb8163f5e549a22888c18b0d53d6bb62a20510060a22fd5a995ec8a05268df8a"}, +    {file = "cryptography-41.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8dde71c4169ec5ccc1087bb7521d54251c016f126f922ab2dfe6649170a3b8c5"}, +    {file = "cryptography-41.0.1.tar.gz", hash = "sha256:d34579085401d3f49762d2f7d6634d6b6c2ae1242202e860f4d26b046e3a1006"},  ]  [package.dependencies] @@ -560,18 +553,17 @@ cffi = ">=1.12"  [package.extras]  docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]  docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] -pep8test = ["black", "check-manifest", "mypy", "ruff"] -sdist = ["setuptools-rust (>=0.11.4)"] +nox = ["nox"] +pep8test = ["black", "check-sdist", "mypy", "ruff"] +sdist = ["build"]  ssh = ["bcrypt (>=3.1.5)"] -test = ["iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-shard (>=0.1.2)", "pytest-subtests", "pytest-xdist"] +test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]  test-randomorder = ["pytest-randomly"] -tox = ["tox"]  [[package]]  name = "dill"  version = "0.3.6"  description = "serialize all of python" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -586,7 +578,6 @@ graph = ["objgraph (>=1.7.2)"]  name = "docutils"  version = "0.19"  description = "Docutils -- Python Documentation Utilities" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -598,7 +589,6 @@ files = [  name = "exceptiongroup"  version = "1.1.1"  description = "Backport of PEP 654 (exception groups)" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -613,7 +603,6 @@ test = ["pytest (>=6)"]  name = "filelock"  version = "3.12.0"  description = "A platform independent file lock." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -629,7 +618,6 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "p  name = "fitparse"  version = "1.2.0"  description = "Python library to parse ANT/Garmin .FIT files" -category = "main"  optional = false  python-versions = "*"  files = [ @@ -640,7 +628,6 @@ files = [  name = "gpxpy"  version = "1.5.0"  description = "GPX file parser and GPS track manipulation library" -category = "main"  optional = false  python-versions = ">=3.6"  files = [ @@ -649,83 +636,81 @@ files = [  [[package]]  name = "greenlet" -version = "2.0.1" +version = "2.0.2"  description = "Lightweight in-process concurrent programming" -category = "main"  optional = false  python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"  files = [ -    {file = "greenlet-2.0.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c"}, -    {file = "greenlet-2.0.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515"}, -    {file = "greenlet-2.0.1-cp27-cp27m-win32.whl", hash = "sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a"}, -    {file = "greenlet-2.0.1-cp27-cp27m-win_amd64.whl", hash = "sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524"}, -    {file = "greenlet-2.0.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243"}, -    {file = "greenlet-2.0.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26"}, -    {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd"}, -    {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45"}, -    {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da"}, -    {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d"}, -    {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd"}, -    {file = "greenlet-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617"}, -    {file = "greenlet-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9"}, -    {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94"}, -    {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a"}, -    {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce"}, -    {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72"}, -    {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82"}, -    {file = "greenlet-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd"}, -    {file = "greenlet-2.0.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f"}, -    {file = "greenlet-2.0.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f"}, -    {file = "greenlet-2.0.1-cp35-cp35m-win32.whl", hash = "sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955"}, -    {file = "greenlet-2.0.1-cp35-cp35m-win_amd64.whl", hash = "sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77"}, -    {file = "greenlet-2.0.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581"}, -    {file = "greenlet-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9"}, -    {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51"}, -    {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148"}, -    {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2"}, -    {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39"}, -    {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92"}, -    {file = "greenlet-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928"}, -    {file = "greenlet-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd"}, -    {file = "greenlet-2.0.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963"}, -    {file = "greenlet-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5"}, -    {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce"}, -    {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000"}, -    {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2"}, -    {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9"}, -    {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1"}, -    {file = "greenlet-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1"}, -    {file = "greenlet-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23"}, -    {file = "greenlet-2.0.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d"}, -    {file = "greenlet-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68"}, -    {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e"}, -    {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48"}, -    {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764"}, -    {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0"}, -    {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9"}, -    {file = "greenlet-2.0.1-cp38-cp38-win32.whl", hash = "sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608"}, -    {file = "greenlet-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6"}, -    {file = "greenlet-2.0.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb"}, -    {file = "greenlet-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19"}, -    {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5"}, -    {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7"}, -    {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d"}, -    {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726"}, -    {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e"}, -    {file = "greenlet-2.0.1-cp39-cp39-win32.whl", hash = "sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a"}, -    {file = "greenlet-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6"}, -    {file = "greenlet-2.0.1.tar.gz", hash = "sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67"}, +    {file = "greenlet-2.0.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d"}, +    {file = "greenlet-2.0.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9"}, +    {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"}, +    {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"}, +    {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"}, +    {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"}, +    {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"}, +    {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"}, +    {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470"}, +    {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a"}, +    {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"}, +    {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"}, +    {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"}, +    {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"}, +    {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"}, +    {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"}, +    {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19"}, +    {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3"}, +    {file = "greenlet-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5"}, +    {file = "greenlet-2.0.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6"}, +    {file = "greenlet-2.0.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43"}, +    {file = "greenlet-2.0.2-cp35-cp35m-win32.whl", hash = "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a"}, +    {file = "greenlet-2.0.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394"}, +    {file = "greenlet-2.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0"}, +    {file = "greenlet-2.0.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3"}, +    {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db"}, +    {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099"}, +    {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75"}, +    {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf"}, +    {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292"}, +    {file = "greenlet-2.0.2-cp36-cp36m-win32.whl", hash = "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9"}, +    {file = "greenlet-2.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f"}, +    {file = "greenlet-2.0.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b"}, +    {file = "greenlet-2.0.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1"}, +    {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7"}, +    {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca"}, +    {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73"}, +    {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86"}, +    {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33"}, +    {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"}, +    {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"}, +    {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"}, +    {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"}, +    {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"}, +    {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"}, +    {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857"}, +    {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a"}, +    {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"}, +    {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"}, +    {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"}, +    {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"}, +    {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"}, +    {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"}, +    {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b"}, +    {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b"}, +    {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8"}, +    {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9"}, +    {file = "greenlet-2.0.2-cp39-cp39-win32.whl", hash = "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5"}, +    {file = "greenlet-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564"}, +    {file = "greenlet-2.0.2.tar.gz", hash = "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0"},  ]  [package.extras]  docs = ["Sphinx", "docutils (<0.18)"] -test = ["faulthandler", "objgraph", "psutil"] +test = ["objgraph", "psutil"]  [[package]]  name = "hupper"  version = "1.12"  description = "Integrated process monitor for developing and reloading daemons." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -741,7 +726,6 @@ testing = ["mock", "pytest", "pytest-cov", "watchdog"]  name = "idna"  version = "3.4"  description = "Internationalized Domain Names in Applications (IDNA)" -category = "main"  optional = false  python-versions = ">=3.5"  files = [ @@ -753,7 +737,6 @@ files = [  name = "imagesize"  version = "1.4.1"  description = "Getting image size from png/jpeg/jpeg2000/gif file" -category = "dev"  optional = false  python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"  files = [ @@ -765,7 +748,6 @@ files = [  name = "importlib-metadata"  version = "6.6.0"  description = "Read metadata from Python packages" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -785,7 +767,6 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag  name = "iniconfig"  version = "2.0.0"  description = "brain-dead simple config-ini parsing" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -797,7 +778,6 @@ files = [  name = "isort"  version = "5.12.0"  description = "A Python utility / library to sort Python imports." -category = "dev"  optional = false  python-versions = ">=3.8.0"  files = [ @@ -815,7 +795,6 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"]  name = "jinja2"  version = "3.1.2"  description = "A very fast and expressive template engine." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -833,7 +812,6 @@ i18n = ["Babel (>=2.7)"]  name = "lazy-object-proxy"  version = "1.9.0"  description = "A fast and thorough lazy object proxy." -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -879,7 +857,6 @@ files = [  name = "mako"  version = "1.2.4"  description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -899,7 +876,6 @@ testing = ["pytest"]  name = "markdown"  version = "3.4.3"  description = "Python implementation of John Gruber's Markdown." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -917,7 +893,6 @@ testing = ["coverage", "pyyaml"]  name = "markupsafe"  version = "2.1.2"  description = "Safely add untrusted strings to HTML/XML markup." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -977,7 +952,6 @@ files = [  name = "mccabe"  version = "0.7.0"  description = "McCabe checker, plugin for flake8" -category = "dev"  optional = false  python-versions = ">=3.6"  files = [ @@ -987,38 +961,37 @@ files = [  [[package]]  name = "mypy" -version = "1.2.0" +version = "1.3.0"  description = "Optional static typing for Python" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "mypy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:701189408b460a2ff42b984e6bd45c3f41f0ac9f5f58b8873bbedc511900086d"}, -    {file = "mypy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fe91be1c51c90e2afe6827601ca14353bbf3953f343c2129fa1e247d55fd95ba"}, -    {file = "mypy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d26b513225ffd3eacece727f4387bdce6469192ef029ca9dd469940158bc89e"}, -    {file = "mypy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a2d219775a120581a0ae8ca392b31f238d452729adbcb6892fa89688cb8306a"}, -    {file = "mypy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:2e93a8a553e0394b26c4ca683923b85a69f7ccdc0139e6acd1354cc884fe0128"}, -    {file = "mypy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3efde4af6f2d3ccf58ae825495dbb8d74abd6d176ee686ce2ab19bd025273f41"}, -    {file = "mypy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:695c45cea7e8abb6f088a34a6034b1d273122e5530aeebb9c09626cea6dca4cb"}, -    {file = "mypy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0e9464a0af6715852267bf29c9553e4555b61f5904a4fc538547a4d67617937"}, -    {file = "mypy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8293a216e902ac12779eb7a08f2bc39ec6c878d7c6025aa59464e0c4c16f7eb9"}, -    {file = "mypy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:f46af8d162f3d470d8ffc997aaf7a269996d205f9d746124a179d3abe05ac602"}, -    {file = "mypy-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:031fc69c9a7e12bcc5660b74122ed84b3f1c505e762cc4296884096c6d8ee140"}, -    {file = "mypy-1.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:390bc685ec209ada4e9d35068ac6988c60160b2b703072d2850457b62499e336"}, -    {file = "mypy-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4b41412df69ec06ab141808d12e0bf2823717b1c363bd77b4c0820feaa37249e"}, -    {file = "mypy-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4e4a682b3f2489d218751981639cffc4e281d548f9d517addfd5a2917ac78119"}, -    {file = "mypy-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a197ad3a774f8e74f21e428f0de7f60ad26a8d23437b69638aac2764d1e06a6a"}, -    {file = "mypy-1.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9a084bce1061e55cdc0493a2ad890375af359c766b8ac311ac8120d3a472950"}, -    {file = "mypy-1.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaeaa0888b7f3ccb7bcd40b50497ca30923dba14f385bde4af78fac713d6d6f6"}, -    {file = "mypy-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bea55fc25b96c53affab852ad94bf111a3083bc1d8b0c76a61dd101d8a388cf5"}, -    {file = "mypy-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:4c8d8c6b80aa4a1689f2a179d31d86ae1367ea4a12855cc13aa3ba24bb36b2d8"}, -    {file = "mypy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70894c5345bea98321a2fe84df35f43ee7bb0feec117a71420c60459fc3e1eed"}, -    {file = "mypy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4a99fe1768925e4a139aace8f3fb66db3576ee1c30b9c0f70f744ead7e329c9f"}, -    {file = "mypy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023fe9e618182ca6317ae89833ba422c411469156b690fde6a315ad10695a521"}, -    {file = "mypy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d19f1a239d59f10fdc31263d48b7937c585810288376671eaf75380b074f238"}, -    {file = "mypy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:2de7babe398cb7a85ac7f1fd5c42f396c215ab3eff731b4d761d68d0f6a80f48"}, -    {file = "mypy-1.2.0-py3-none-any.whl", hash = "sha256:d8e9187bfcd5ffedbe87403195e1fc340189a68463903c39e2b63307c9fa0394"}, -    {file = "mypy-1.2.0.tar.gz", hash = "sha256:f70a40410d774ae23fcb4afbbeca652905a04de7948eaf0b1789c8d1426b72d1"}, +    {file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"}, +    {file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"}, +    {file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"}, +    {file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"}, +    {file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"}, +    {file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"}, +    {file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"}, +    {file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"}, +    {file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"}, +    {file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"}, +    {file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"}, +    {file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"}, +    {file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"}, +    {file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"}, +    {file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"}, +    {file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"}, +    {file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"}, +    {file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"}, +    {file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"}, +    {file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"}, +    {file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"}, +    {file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"}, +    {file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"}, +    {file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"}, +    {file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"}, +    {file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"},  ]  [package.dependencies] @@ -1036,7 +1009,6 @@ reports = ["lxml"]  name = "mypy-extensions"  version = "1.0.0"  description = "Type system extensions for programs checked with the mypy type checker." -category = "dev"  optional = false  python-versions = ">=3.5"  files = [ @@ -1046,35 +1018,30 @@ files = [  [[package]]  name = "nh3" -version = "0.2.11" +version = "0.2.12"  description = "Ammonia HTML sanitizer Python binding" -category = "main"  optional = false  python-versions = "*"  files = [ -    {file = "nh3-0.2.11-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:dec7807f3a5661678c8694475a477657323d43e69829193593e58d66ed1be0bb"}, -    {file = "nh3-0.2.11-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:69073d7dd59e5e7a6dd2ae4e2b32846e8ab493afb0510d45e5d3935188dafa6f"}, -    {file = "nh3-0.2.11-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e57b4be56a4551aa79b7c1ebfb381468c1014d29dcff65bf329504786ba062b"}, -    {file = "nh3-0.2.11-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e885b4504ac9c17582556a3c5a33b9289bd71d75e70887b3c70125cdd60c638e"}, -    {file = "nh3-0.2.11-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:46798bced886ff382bdb2e6de2a52cc487d4c49ac058ae0701a2bf9e62155859"}, -    {file = "nh3-0.2.11-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5b8f5f7e126415873ca8d38e7c1be7369ec543d6d97ec89263495b24b95a30a"}, -    {file = "nh3-0.2.11-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d396fc3438fb41871be44fbf12307ef3955b7ed7c82a87fccd325daf4122c31"}, -    {file = "nh3-0.2.11-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c3b5788bb5035627547c27c6090f76f5157f6d79f13117241fe62cbed6f5eb"}, -    {file = "nh3-0.2.11-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bff3b85abc0b34793190bc275bf52c496ee3d1710dc2388aaf8feadb63551af5"}, -    {file = "nh3-0.2.11-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5ce060ed5ee7783d2774c1939ac6285e3bce967598d8575042ba57fd7beded5e"}, -    {file = "nh3-0.2.11-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:38321feba65a840714df332f5c6266a72ed50af2fbd5c03bf57d429acea2c07f"}, -    {file = "nh3-0.2.11-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:0773f08a9cb41aafa458ec5b45195b476fd4eff50aec6162c1ea368ca9bd07d1"}, -    {file = "nh3-0.2.11-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:864bd3a69a64e273983bd54f3eb4e232fdc30526be08691d070b518d650854ea"}, -    {file = "nh3-0.2.11-cp37-abi3-win32.whl", hash = "sha256:b6f40f836ecfa74f831d0c38c6ad62975d71c73fc00542f53a9df405186698fc"}, -    {file = "nh3-0.2.11-cp37-abi3-win_amd64.whl", hash = "sha256:0109585b316979073ab67d8ee951c976758216a75b9b43f3a6929db54c2cb1c3"}, -    {file = "nh3-0.2.11.tar.gz", hash = "sha256:3ed2624ca0a1cec3128e8f915e9954dbf6d0e71e76b29813c699fb2d46d01b8f"}, +    {file = "nh3-0.2.12-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:41d63a4ae3aad599340260e34e4c4c3c894c6ed3bd35a9c2a5f301e9115f51ba"}, +    {file = "nh3-0.2.12-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:bf9610da79da367e01cc3d30ea9f12b40df98740e053afa4b51add93d014e513"}, +    {file = "nh3-0.2.12-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f7afab764112d47b2ff09d40116f3bba0a2f3d6a1fcecc8cf8955a0469ef55b"}, +    {file = "nh3-0.2.12-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dcf95c5814b432240134f95ff043d3ecd0d2b31b8a8b68b6328d6e2a13c6ee1c"}, +    {file = "nh3-0.2.12-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:900aa20f8ce4f20c22d145a20727e6051dafec72327a79a36acce2ce51f3ca8d"}, +    {file = "nh3-0.2.12-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d861cead45d7c0d18aba90cc1bf10d894aa0873609cf72d875026eca5cbf7a8d"}, +    {file = "nh3-0.2.12-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:495c27ebeea97581a3cef9c3d012fd26ae1bb208c4aafe31b3f5af2d4b29e2d1"}, +    {file = "nh3-0.2.12-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ee28e4188e774749e7d5feb0fea08c88264a53ab55543bbf451b0da30f15ed5"}, +    {file = "nh3-0.2.12-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:470fd7a440129833c0cb8927fa2d8efffd56992c522ca349cbaa9deca14a11b1"}, +    {file = "nh3-0.2.12-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:2733732a3c654a9ded9a674a19b5ff6e7281adf2cd4c77f6e02bff7a4232740f"}, +    {file = "nh3-0.2.12-cp37-abi3-win32.whl", hash = "sha256:fce6c2096fb2f70708bba4a7713b17e8577122ce1d953f14647816706b03a648"}, +    {file = "nh3-0.2.12-cp37-abi3-win_amd64.whl", hash = "sha256:0f2fe22e2f249866bd13dbe4a130b11c210a9f706a68fc12b537ffc711164432"}, +    {file = "nh3-0.2.12.tar.gz", hash = "sha256:8107c0dd534b635d76f004bfe940b3ec0d8ae4a44fcf1b77084a09d3351dbdf6"},  ]  [[package]]  name = "packaging"  version = "23.1"  description = "Core utilities for Python packages" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -1086,7 +1053,6 @@ files = [  name = "pastedeploy"  version = "3.0.1"  description = "Load, configure, and compose WSGI applications and servers" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -1103,7 +1069,6 @@ testing = ["Paste", "pytest", "pytest-cov"]  name = "pathspec"  version = "0.11.1"  description = "Utility library for gitignore style pattern matching of file paths." -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -1115,7 +1080,6 @@ files = [  name = "plaster"  version = "1.1.2"  description = "A loader interface around multiple config file formats." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -1131,7 +1095,6 @@ testing = ["pytest", "pytest-cov"]  name = "plaster-pastedeploy"  version = "1.0.1"  description = "A loader implementing the PasteDeploy syntax to be used by plaster." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -1148,46 +1111,43 @@ testing = ["pytest", "pytest-cov"]  [[package]]  name = "platformdirs" -version = "3.2.0" +version = "3.5.1"  description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"}, -    {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"}, +    {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, +    {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"},  ]  [package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]  [[package]]  name = "playwright" -version = "1.32.1" +version = "1.34.0"  description = "A high-level API to automate web browsers" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "playwright-1.32.1-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:e2f919e8611f598d6e81bd12ab24c5987955b05fc663c98b862034a955387300"}, -    {file = "playwright-1.32.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5dbf28b8256c2f570a66d6a7c04cd0bfb5225e696e01f85cf5aa49e29ea95b42"}, -    {file = "playwright-1.32.1-py3-none-macosx_11_0_universal2.whl", hash = "sha256:42473495f8af0279d868cc541d0c6d3733a8adb117253499dae85203104b0824"}, -    {file = "playwright-1.32.1-py3-none-manylinux1_x86_64.whl", hash = "sha256:83123330e2913a28d11bb8846f7c81a4736553c80f3e9748d213bcaa24fafe91"}, -    {file = "playwright-1.32.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d56a743f7d88a313b25a88422779c64e5d5a95baa805b9dfd1c5785aa01d217d"}, -    {file = "playwright-1.32.1-py3-none-win32.whl", hash = "sha256:274bfdd413a979346ce66e99c993c105a123e48da591a65638e5cdf518c90172"}, -    {file = "playwright-1.32.1-py3-none-win_amd64.whl", hash = "sha256:32bb5645904b5ba3096a4696c70ce3213eb2310c77273140dc5de14498a84134"}, +    {file = "playwright-1.34.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:69bb9b3296e366a23a99277b4c7673cb54ce71a3f5d630f114f7701b61f98f25"}, +    {file = "playwright-1.34.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:402d946631c8458436e099d7731bbf54cf79c9e62e3acae0ea8421e72616926b"}, +    {file = "playwright-1.34.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:462251cda0fcbb273497d357dbe14b11e43ebceb0bac9b892beda041ff209aa9"}, +    {file = "playwright-1.34.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:a8ba124ea302596a03a66993cd500484fb255cbc10fe0757fa4d49f974267a80"}, +    {file = "playwright-1.34.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf0cb6aac49d24335fe361868aea72b11f276a95e7809f1a5d1c69b4120c46ac"}, +    {file = "playwright-1.34.0-py3-none-win32.whl", hash = "sha256:c50fef189d87243cc09ae0feb8e417fbe434359ccbcc863fb19ba06d46d31c33"}, +    {file = "playwright-1.34.0-py3-none-win_amd64.whl", hash = "sha256:42e16c930e1e910461f4c551a72fc1b900f37124431bf2b6a6d9ddae70042db4"},  ]  [package.dependencies] -greenlet = "2.0.1" +greenlet = "2.0.2"  pyee = "9.0.4"  [[package]]  name = "pluggy"  version = "1.0.0"  description = "plugin and hook calling mechanisms for python" -category = "dev"  optional = false  python-versions = ">=3.6"  files = [ @@ -1203,7 +1163,6 @@ testing = ["pytest", "pytest-benchmark"]  name = "pycparser"  version = "2.21"  description = "C parser in Python" -category = "main"  optional = false  python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"  files = [ @@ -1213,48 +1172,47 @@ files = [  [[package]]  name = "pydantic" -version = "1.10.7" +version = "1.10.8"  description = "Data validation and settings management using python type hints" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"}, -    {file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"}, -    {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"}, -    {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"}, -    {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"}, -    {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"}, -    {file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"}, -    {file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"}, -    {file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"}, -    {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"}, -    {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"}, -    {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"}, -    {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"}, -    {file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"}, -    {file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"}, -    {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"}, -    {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"}, -    {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"}, -    {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"}, -    {file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"}, -    {file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"}, -    {file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"}, -    {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"}, -    {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"}, -    {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"}, -    {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"}, -    {file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"}, -    {file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"}, -    {file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"}, -    {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"}, -    {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"}, -    {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"}, -    {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"}, -    {file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"}, -    {file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"}, -    {file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"}, +    {file = "pydantic-1.10.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1243d28e9b05003a89d72e7915fdb26ffd1d39bdd39b00b7dbe4afae4b557f9d"}, +    {file = "pydantic-1.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0ab53b609c11dfc0c060d94335993cc2b95b2150e25583bec37a49b2d6c6c3f"}, +    {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9613fadad06b4f3bc5db2653ce2f22e0de84a7c6c293909b48f6ed37b83c61f"}, +    {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df7800cb1984d8f6e249351139667a8c50a379009271ee6236138a22a0c0f319"}, +    {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0c6fafa0965b539d7aab0a673a046466d23b86e4b0e8019d25fd53f4df62c277"}, +    {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e82d4566fcd527eae8b244fa952d99f2ca3172b7e97add0b43e2d97ee77f81ab"}, +    {file = "pydantic-1.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:ab523c31e22943713d80d8d342d23b6f6ac4b792a1e54064a8d0cf78fd64e800"}, +    {file = "pydantic-1.10.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:666bdf6066bf6dbc107b30d034615d2627e2121506c555f73f90b54a463d1f33"}, +    {file = "pydantic-1.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:35db5301b82e8661fa9c505c800d0990bc14e9f36f98932bb1d248c0ac5cada5"}, +    {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90c1e29f447557e9e26afb1c4dbf8768a10cc676e3781b6a577841ade126b85"}, +    {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93e766b4a8226e0708ef243e843105bf124e21331694367f95f4e3b4a92bbb3f"}, +    {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:88f195f582851e8db960b4a94c3e3ad25692c1c1539e2552f3df7a9e972ef60e"}, +    {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:34d327c81e68a1ecb52fe9c8d50c8a9b3e90d3c8ad991bfc8f953fb477d42fb4"}, +    {file = "pydantic-1.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:d532bf00f381bd6bc62cabc7d1372096b75a33bc197a312b03f5838b4fb84edd"}, +    {file = "pydantic-1.10.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7d5b8641c24886d764a74ec541d2fc2c7fb19f6da2a4001e6d580ba4a38f7878"}, +    {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f6cb446470b7ddf86c2e57cd119a24959af2b01e552f60705910663af09a4"}, +    {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c33b60054b2136aef8cf190cd4c52a3daa20b2263917c49adad20eaf381e823b"}, +    {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1952526ba40b220b912cdc43c1c32bcf4a58e3f192fa313ee665916b26befb68"}, +    {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bb14388ec45a7a0dc429e87def6396f9e73c8c77818c927b6a60706603d5f2ea"}, +    {file = "pydantic-1.10.8-cp37-cp37m-win_amd64.whl", hash = "sha256:16f8c3e33af1e9bb16c7a91fc7d5fa9fe27298e9f299cff6cb744d89d573d62c"}, +    {file = "pydantic-1.10.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ced8375969673929809d7f36ad322934c35de4af3b5e5b09ec967c21f9f7887"}, +    {file = "pydantic-1.10.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93e6bcfccbd831894a6a434b0aeb1947f9e70b7468f274154d03d71fabb1d7c6"}, +    {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:191ba419b605f897ede9892f6c56fb182f40a15d309ef0142212200a10af4c18"}, +    {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:052d8654cb65174d6f9490cc9b9a200083a82cf5c3c5d3985db765757eb3b375"}, +    {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ceb6a23bf1ba4b837d0cfe378329ad3f351b5897c8d4914ce95b85fba96da5a1"}, +    {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f2e754d5566f050954727c77f094e01793bcb5725b663bf628fa6743a5a9108"}, +    {file = "pydantic-1.10.8-cp38-cp38-win_amd64.whl", hash = "sha256:6a82d6cda82258efca32b40040228ecf43a548671cb174a1e81477195ed3ed56"}, +    {file = "pydantic-1.10.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e59417ba8a17265e632af99cc5f35ec309de5980c440c255ab1ca3ae96a3e0e"}, +    {file = "pydantic-1.10.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:84d80219c3f8d4cad44575e18404099c76851bc924ce5ab1c4c8bb5e2a2227d0"}, +    {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e4148e635994d57d834be1182a44bdb07dd867fa3c2d1b37002000646cc5459"}, +    {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12f7b0bf8553e310e530e9f3a2f5734c68699f42218bf3568ef49cd9b0e44df4"}, +    {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42aa0c4b5c3025483240a25b09f3c09a189481ddda2ea3a831a9d25f444e03c1"}, +    {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17aef11cc1b997f9d574b91909fed40761e13fac438d72b81f902226a69dac01"}, +    {file = "pydantic-1.10.8-cp39-cp39-win_amd64.whl", hash = "sha256:66a703d1983c675a6e0fed8953b0971c44dba48a929a2000a493c3772eb61a5a"}, +    {file = "pydantic-1.10.8-py3-none-any.whl", hash = "sha256:7456eb22ed9aaa24ff3e7b4757da20d9e5ce2a81018c1b3ebd81a0b88a18f3b2"}, +    {file = "pydantic-1.10.8.tar.gz", hash = "sha256:1410275520dfa70effadf4c21811d755e7ef9bb1f1d077a21958153a92c8d9ca"},  ]  [package.dependencies] @@ -1268,7 +1226,6 @@ email = ["email-validator (>=1.0.3)"]  name = "pyee"  version = "9.0.4"  description = "A port of node.js's EventEmitter to python." -category = "dev"  optional = false  python-versions = "*"  files = [ @@ -1283,7 +1240,6 @@ typing-extensions = "*"  name = "pygments"  version = "2.15.1"  description = "Pygments is a syntax highlighting package written in Python." -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -1296,18 +1252,17 @@ plugins = ["importlib-metadata"]  [[package]]  name = "pylint" -version = "2.17.2" +version = "2.17.4"  description = "python code static checker" -category = "dev"  optional = false  python-versions = ">=3.7.2"  files = [ -    {file = "pylint-2.17.2-py3-none-any.whl", hash = "sha256:001cc91366a7df2970941d7e6bbefcbf98694e00102c1f121c531a814ddc2ea8"}, -    {file = "pylint-2.17.2.tar.gz", hash = "sha256:1b647da5249e7c279118f657ca28b6aaebb299f86bf92affc632acf199f7adbb"}, +    {file = "pylint-2.17.4-py3-none-any.whl", hash = "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c"}, +    {file = "pylint-2.17.4.tar.gz", hash = "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1"},  ]  [package.dependencies] -astroid = ">=2.15.2,<=2.17.0-dev0" +astroid = ">=2.15.4,<=2.17.0-dev0"  colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}  dill = [      {version = ">=0.2", markers = "python_version < \"3.11\""}, @@ -1328,7 +1283,6 @@ testutils = ["gitpython (>3)"]  name = "pyramid"  version = "2.0.1"  description = "The Pyramid Web Framework, a Pylons project" -category = "main"  optional = false  python-versions = ">=3.6"  files = [ @@ -1355,7 +1309,6 @@ testing = ["coverage", "pytest (>=5.4.2)", "pytest-cov", "webtest (>=1.3.1)", "z  name = "pyramid-debugtoolbar"  version = "4.10"  description = "A package which provides an interactive HTML debugger for Pyramid application development" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -1376,7 +1329,6 @@ testing = ["WebTest", "pytest", "pytest-cov", "sqlalchemy", "webob"]  name = "pyramid-jinja2"  version = "2.10"  description = "Jinja2 template bindings for the Pyramid web framework" -category = "main"  optional = false  python-versions = ">=3.7.0"  files = [ @@ -1398,7 +1350,6 @@ testing = ["coverage", "pytest (>=5.4.2)", "pytest-cov", "webtest"]  name = "pyramid-mako"  version = "1.1.0"  description = "Mako template bindings for the Pyramid web framework" -category = "main"  optional = false  python-versions = "*"  files = [ @@ -1418,7 +1369,6 @@ testing = ["WebTest (>=1.3.1)", "coverage", "nose"]  name = "pyramid-retry"  version = "2.1.1"  description = "An execution policy for Pyramid that supports retrying requests after certain failure exceptions." -category = "main"  optional = false  python-versions = "*"  files = [ @@ -1438,7 +1388,6 @@ testing = ["WebTest", "pytest", "pytest-cov"]  name = "pyramid-tm"  version = "2.5"  description = "A package which allows Pyramid requests to join the active transaction" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -1458,7 +1407,6 @@ testing = ["WebTest", "coverage (>=5.0)", "pytest", "pytest-cov"]  name = "pytest"  version = "7.3.1"  description = "pytest: simple powerful testing with Python" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -1481,7 +1429,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no  name = "pytest-base-url"  version = "2.0.0"  description = "pytest plugin for URL based testing" -category = "dev"  optional = false  python-versions = ">=3.7,<4.0"  files = [ @@ -1495,14 +1442,13 @@ requests = ">=2.9"  [[package]]  name = "pytest-cov" -version = "4.0.0" +version = "4.1.0"  description = "Pytest plugin for measuring coverage." -category = "dev"  optional = false -python-versions = ">=3.6" +python-versions = ">=3.7"  files = [ -    {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, -    {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, +    {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, +    {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},  ]  [package.dependencies] @@ -1514,32 +1460,30 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale  [[package]]  name = "pytest-playwright" -version = "0.3.2" +version = "0.3.3"  description = "A pytest wrapper with fixtures for Playwright to automate web browsers" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "pytest-playwright-0.3.2.tar.gz", hash = "sha256:8e91e00c9c7558f909302ebd2ec440e7c1147a72ead8805dc58b6a0eee9b161b"}, -    {file = "pytest_playwright-0.3.2-py3-none-any.whl", hash = "sha256:2ffb27226739425a713363bab391d26e4a4c5b2f5ba4b83496b66cffc2223bab"}, +    {file = "pytest-playwright-0.3.3.tar.gz", hash = "sha256:9bf79c633c97dd1405308b8d3600e6c8c2a200a733e2f36c5a150ba4701936f8"}, +    {file = "pytest_playwright-0.3.3-py3-none-any.whl", hash = "sha256:83a896b1b28bfaa081ca9ea27229a06a114e106e2e62fb3d5f06544748fbc1fe"},  ]  [package.dependencies]  playwright = ">=1.18"  pytest = ">=6.2.4,<8.0.0"  pytest-base-url = ">=1.0.0,<3.0.0" -python-slugify = ">=6.0.0,<7.0.0" +python-slugify = ">=6.0.0,<9.0.0"  [[package]]  name = "python-slugify" -version = "6.1.2" +version = "8.0.1"  description = "A Python slugify application that also handles Unicode" -category = "dev"  optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7"  files = [ -    {file = "python-slugify-6.1.2.tar.gz", hash = "sha256:272d106cb31ab99b3496ba085e3fea0e9e76dcde967b5e9992500d1f785ce4e1"}, -    {file = "python_slugify-6.1.2-py2.py3-none-any.whl", hash = "sha256:7b2c274c308b62f4269a9ba701aa69a797e9bca41aeee5b3a9e79e36b6656927"}, +    {file = "python-slugify-8.0.1.tar.gz", hash = "sha256:ce0d46ddb668b3be82f4ed5e503dbc33dd815d83e2eb6824211310d3fb172a27"}, +    {file = "python_slugify-8.0.1-py2.py3-none-any.whl", hash = "sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395"},  ]  [package.dependencies] @@ -1550,18 +1494,17 @@ unidecode = ["Unidecode (>=1.1.1)"]  [[package]]  name = "redis" -version = "4.5.4" +version = "4.5.5"  description = "Python client for Redis database and key-value store" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "redis-4.5.4-py3-none-any.whl", hash = "sha256:2c19e6767c474f2e85167909061d525ed65bea9301c0770bb151e041b7ac89a2"}, -    {file = "redis-4.5.4.tar.gz", hash = "sha256:73ec35da4da267d6847e47f68730fdd5f62e2ca69e3ef5885c6a78a9374c3893"}, +    {file = "redis-4.5.5-py3-none-any.whl", hash = "sha256:77929bc7f5dab9adf3acba2d3bb7d7658f1e0c2f1cafe7eb36434e751c471119"}, +    {file = "redis-4.5.5.tar.gz", hash = "sha256:dc87a0bdef6c8bfe1ef1e1c40be7034390c2ae02d92dcd0c7ca1729443899880"},  ]  [package.dependencies] -async-timeout = {version = ">=4.0.2", markers = "python_version <= \"3.11.2\""} +async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""}  [package.extras]  hiredis = ["hiredis (>=1.0.0)"] @@ -1569,21 +1512,20 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"  [[package]]  name = "requests" -version = "2.28.2" +version = "2.31.0"  description = "Python HTTP for Humans." -category = "main"  optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.7"  files = [ -    {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, -    {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, +    {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, +    {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},  ]  [package.dependencies]  certifi = ">=2017.4.17"  charset-normalizer = ">=2,<4"  idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3"  [package.extras]  socks = ["PySocks (>=1.5.6,!=1.5.7)"] @@ -1591,26 +1533,24 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]  [[package]]  name = "setuptools" -version = "67.7.1" +version = "67.8.0"  description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "setuptools-67.7.1-py3-none-any.whl", hash = "sha256:6f0839fbdb7e3cfef1fc38d7954f5c1c26bf4eebb155a55c9bf8faf997b9fb67"}, -    {file = "setuptools-67.7.1.tar.gz", hash = "sha256:bb16732e8eb928922eabaa022f881ae2b7cdcfaf9993ef1f5e841a96d32b8e0c"}, +    {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, +    {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"},  ]  [package.extras]  docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]  testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]  [[package]]  name = "snowballstemmer"  version = "2.2.0"  description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev"  optional = false  python-versions = "*"  files = [ @@ -1622,7 +1562,6 @@ files = [  name = "soupsieve"  version = "2.4.1"  description = "A modern CSS selector implementation for Beautiful Soup." -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -1632,21 +1571,20 @@ files = [  [[package]]  name = "sphinx" -version = "6.1.3" +version = "6.2.1"  description = "Python documentation generator" -category = "dev"  optional = false  python-versions = ">=3.8"  files = [ -    {file = "Sphinx-6.1.3.tar.gz", hash = "sha256:0dac3b698538ffef41716cf97ba26c1c7788dba73ce6f150c1ff5b4720786dd2"}, -    {file = "sphinx-6.1.3-py3-none-any.whl", hash = "sha256:807d1cb3d6be87eb78a381c3e70ebd8d346b9a25f3753e9947e866b2786865fc"}, +    {file = "Sphinx-6.2.1.tar.gz", hash = "sha256:6d56a34697bb749ffa0152feafc4b19836c755d90a7c59b72bc7dfd371b9cc6b"}, +    {file = "sphinx-6.2.1-py3-none-any.whl", hash = "sha256:97787ff1fa3256a3eef9eda523a63dbf299f7b47e053cfcf684a1c2a8380c912"},  ]  [package.dependencies]  alabaster = ">=0.7,<0.8"  babel = ">=2.9"  colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.18,<0.20" +docutils = ">=0.18.1,<0.20"  imagesize = ">=1.3"  importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""}  Jinja2 = ">=3.0" @@ -1664,13 +1602,12 @@ sphinxcontrib-serializinghtml = ">=1.1.5"  [package.extras]  docs = ["sphinxcontrib-websupport"]  lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] -test = ["cython", "html5lib", "pytest (>=4.6)"] +test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"]  [[package]]  name = "sphinx-autodoc-typehints"  version = "1.23.0"  description = "Type hints (PEP 484) support for the Sphinx autodoc extension" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -1690,7 +1627,6 @@ type-comment = ["typed-ast (>=1.5.4)"]  name = "sphinxcontrib-applehelp"  version = "1.0.4"  description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -category = "dev"  optional = false  python-versions = ">=3.8"  files = [ @@ -1706,7 +1642,6 @@ test = ["pytest"]  name = "sphinxcontrib-devhelp"  version = "1.0.2"  description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -category = "dev"  optional = false  python-versions = ">=3.5"  files = [ @@ -1722,7 +1657,6 @@ test = ["pytest"]  name = "sphinxcontrib-htmlhelp"  version = "2.0.1"  description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -category = "dev"  optional = false  python-versions = ">=3.8"  files = [ @@ -1738,7 +1672,6 @@ test = ["html5lib", "pytest"]  name = "sphinxcontrib-jsmath"  version = "1.0.1"  description = "A sphinx extension which renders display math in HTML via JavaScript" -category = "dev"  optional = false  python-versions = ">=3.5"  files = [ @@ -1753,7 +1686,6 @@ test = ["flake8", "mypy", "pytest"]  name = "sphinxcontrib-qthelp"  version = "1.0.3"  description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -category = "dev"  optional = false  python-versions = ">=3.5"  files = [ @@ -1769,7 +1701,6 @@ test = ["pytest"]  name = "sphinxcontrib-serializinghtml"  version = "1.1.5"  description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -category = "dev"  optional = false  python-versions = ">=3.5"  files = [ @@ -1783,89 +1714,91 @@ test = ["pytest"]  [[package]]  name = "sqlalchemy" -version = "1.4.47" +version = "2.0.15"  description = "Database Abstraction Library" -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -files = [ -    {file = "SQLAlchemy-1.4.47-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:dcfb480bfc9e1fab726003ae00a6bfc67a29bad275b63a4e36d17fe7f13a624e"}, -    {file = "SQLAlchemy-1.4.47-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:28fda5a69d6182589892422c5a9b02a8fd1125787aab1d83f1392aa955bf8d0a"}, -    {file = "SQLAlchemy-1.4.47-cp27-cp27m-win32.whl", hash = "sha256:45e799c1a41822eba6bee4e59b0e38764e1a1ee69873ab2889079865e9ea0e23"}, -    {file = "SQLAlchemy-1.4.47-cp27-cp27m-win_amd64.whl", hash = "sha256:10edbb92a9ef611f01b086e271a9f6c1c3e5157c3b0c5ff62310fb2187acbd4a"}, -    {file = "SQLAlchemy-1.4.47-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7a4df53472c9030a8ddb1cce517757ba38a7a25699bbcabd57dcc8a5d53f324e"}, -    {file = "SQLAlchemy-1.4.47-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:511d4abc823152dec49461209607bbfb2df60033c8c88a3f7c93293b8ecbb13d"}, -    {file = "SQLAlchemy-1.4.47-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbe57f39f531c5d68d5594ea4613daa60aba33bb51a8cc42f96f17bbd6305e8d"}, -    {file = "SQLAlchemy-1.4.47-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca8ab6748e3ec66afccd8b23ec2f92787a58d5353ce9624dccd770427ee67c82"}, -    {file = "SQLAlchemy-1.4.47-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:299b5c5c060b9fbe51808d0d40d8475f7b3873317640b9b7617c7f988cf59fda"}, -    {file = "SQLAlchemy-1.4.47-cp310-cp310-win32.whl", hash = "sha256:684e5c773222781775c7f77231f412633d8af22493bf35b7fa1029fdf8066d10"}, -    {file = "SQLAlchemy-1.4.47-cp310-cp310-win_amd64.whl", hash = "sha256:2bba39b12b879c7b35cde18b6e14119c5f1a16bd064a48dd2ac62d21366a5e17"}, -    {file = "SQLAlchemy-1.4.47-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:795b5b9db573d3ed61fae74285d57d396829e3157642794d3a8f72ec2a5c719b"}, -    {file = "SQLAlchemy-1.4.47-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:989c62b96596b7938cbc032e39431e6c2d81b635034571d6a43a13920852fb65"}, -    {file = "SQLAlchemy-1.4.47-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3b67bda733da1dcdccaf354e71ef01b46db483a4f6236450d3f9a61efdba35a"}, -    {file = "SQLAlchemy-1.4.47-cp311-cp311-win32.whl", hash = "sha256:9a198f690ac12a3a807e03a5a45df6a30cd215935f237a46f4248faed62e69c8"}, -    {file = "SQLAlchemy-1.4.47-cp311-cp311-win_amd64.whl", hash = "sha256:03be6f3cb66e69fb3a09b5ea89d77e4bc942f3bf84b207dba84666a26799c166"}, -    {file = "SQLAlchemy-1.4.47-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:16ee6fea316790980779268da47a9260d5dd665c96f225d28e7750b0bb2e2a04"}, -    {file = "SQLAlchemy-1.4.47-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:557675e0befafa08d36d7a9284e8761c97490a248474d778373fb96b0d7fd8de"}, -    {file = "SQLAlchemy-1.4.47-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb2797fee8a7914fb2c3dc7de404d3f96eb77f20fc60e9ee38dc6b0ca720f2c2"}, -    {file = "SQLAlchemy-1.4.47-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28297aa29e035f29cba6b16aacd3680fbc6a9db682258d5f2e7b49ec215dbe40"}, -    {file = "SQLAlchemy-1.4.47-cp36-cp36m-win32.whl", hash = "sha256:998e782c8d9fd57fa8704d149ccd52acf03db30d7dd76f467fd21c1c21b414fa"}, -    {file = "SQLAlchemy-1.4.47-cp36-cp36m-win_amd64.whl", hash = "sha256:dde4d02213f1deb49eaaf8be8a6425948963a7af84983b3f22772c63826944de"}, -    {file = "SQLAlchemy-1.4.47-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:e98ef1babe34f37f443b7211cd3ee004d9577a19766e2dbacf62fce73c76245a"}, -    {file = "SQLAlchemy-1.4.47-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14a3879853208a242b5913f3a17c6ac0eae9dc210ff99c8f10b19d4a1ed8ed9b"}, -    {file = "SQLAlchemy-1.4.47-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7120a2f72599d4fed7c001fa1cbbc5b4d14929436135768050e284f53e9fbe5e"}, -    {file = "SQLAlchemy-1.4.47-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:048509d7f3ac27b83ad82fd96a1ab90a34c8e906e4e09c8d677fc531d12c23c5"}, -    {file = "SQLAlchemy-1.4.47-cp37-cp37m-win32.whl", hash = "sha256:6572d7c96c2e3e126d0bb27bfb1d7e2a195b68d951fcc64c146b94f088e5421a"}, -    {file = "SQLAlchemy-1.4.47-cp37-cp37m-win_amd64.whl", hash = "sha256:a6c3929df5eeaf3867724003d5c19fed3f0c290f3edc7911616616684f200ecf"}, -    {file = "SQLAlchemy-1.4.47-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:71d4bf7768169c4502f6c2b0709a02a33703544f611810fb0c75406a9c576ee1"}, -    {file = "SQLAlchemy-1.4.47-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd45c60cc4f6d68c30d5179e2c2c8098f7112983532897566bb69c47d87127d3"}, -    {file = "SQLAlchemy-1.4.47-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0fdbb8e9d4e9003f332a93d6a37bca48ba8095086c97a89826a136d8eddfc455"}, -    {file = "SQLAlchemy-1.4.47-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f216a51451a0a0466e082e163591f6dcb2f9ec182adb3f1f4b1fd3688c7582c"}, -    {file = "SQLAlchemy-1.4.47-cp38-cp38-win32.whl", hash = "sha256:bd988b3362d7e586ef581eb14771bbb48793a4edb6fcf62da75d3f0f3447060b"}, -    {file = "SQLAlchemy-1.4.47-cp38-cp38-win_amd64.whl", hash = "sha256:32ab09f2863e3de51529aa84ff0e4fe89a2cb1bfbc11e225b6dbc60814e44c94"}, -    {file = "SQLAlchemy-1.4.47-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:07764b240645627bc3e82596435bd1a1884646bfc0721642d24c26b12f1df194"}, -    {file = "SQLAlchemy-1.4.47-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e2a42017984099ef6f56438a6b898ce0538f6fadddaa902870c5aa3e1d82583"}, -    {file = "SQLAlchemy-1.4.47-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6b6d807c76c20b4bc143a49ad47782228a2ac98bdcdcb069da54280e138847fc"}, -    {file = "SQLAlchemy-1.4.47-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a94632ba26a666e7be0a7d7cc3f7acab622a04259a3aa0ee50ff6d44ba9df0d"}, -    {file = "SQLAlchemy-1.4.47-cp39-cp39-win32.whl", hash = "sha256:f80915681ea9001f19b65aee715115f2ad310730c8043127cf3e19b3009892dd"}, -    {file = "SQLAlchemy-1.4.47-cp39-cp39-win_amd64.whl", hash = "sha256:fc700b862e0a859a37faf85367e205e7acaecae5a098794aff52fdd8aea77b12"}, -    {file = "SQLAlchemy-1.4.47.tar.gz", hash = "sha256:95fc02f7fc1f3199aaa47a8a757437134cf618e9d994c84effd53f530c38586f"}, +optional = false +python-versions = ">=3.7" +files = [ +    {file = "SQLAlchemy-2.0.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78303719c6f72af97814b0072ad18bee72e70adca8d95cf8fecd59c5e1ddb040"}, +    {file = "SQLAlchemy-2.0.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9d810b4aacd5ef4e293aa4ea01f19fca53999e9edcfc4a8ef1146238b30bdc28"}, +    {file = "SQLAlchemy-2.0.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fb5d09f1d51480f711b69fe28ad42e4f8b08600a85ab2473baee669e1257800"}, +    {file = "SQLAlchemy-2.0.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51b19887c96d405599880da6a7cbdf8545a7e78ec5683e46a43bac8885e32d0f"}, +    {file = "SQLAlchemy-2.0.15-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d6b17cb86908e7f88be14007d6afe7d2ab11966e373044137f96a6a4d83eb21c"}, +    {file = "SQLAlchemy-2.0.15-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df25052b92bd514357a9b370d74f240db890ea79aaa428fb893520e10ee5bc18"}, +    {file = "SQLAlchemy-2.0.15-cp310-cp310-win32.whl", hash = "sha256:55ec62ddc0200b4fee94d11abbec7aa25948d5d21cb8df8807f4bdd3c51ba44b"}, +    {file = "SQLAlchemy-2.0.15-cp310-cp310-win_amd64.whl", hash = "sha256:ae1d8deb391ab39cc8f0d5844e588a115ae3717e607d91482023917f920f777f"}, +    {file = "SQLAlchemy-2.0.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4670ce853cb25f72115a1bbe366ae13cf3f28fc5c87222df14f8d3d55d51816e"}, +    {file = "SQLAlchemy-2.0.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cea7c4a3dfc2ca61f88a2b1ddd6b0bfbd116c9b1a361b3b66fd826034b833142"}, +    {file = "SQLAlchemy-2.0.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f5784dfb2d45c19cde03c45c04a54bf47428610106197ed6e6fa79f33bc63d3"}, +    {file = "SQLAlchemy-2.0.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b31ebde27575b3b0708673ec14f0c305c4564d995b545148ab7ac0f4d9b847a"}, +    {file = "SQLAlchemy-2.0.15-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b42913a0259267e9ee335da0c36498077799e59c5e332d506e72b4f32de781d"}, +    {file = "SQLAlchemy-2.0.15-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a3f8020e013e9b3b7941dcf20b0fc8f7429daaf7158760846731cbd8caa5e45"}, +    {file = "SQLAlchemy-2.0.15-cp311-cp311-win32.whl", hash = "sha256:88ab245ed2c96265441ed2818977be28c840cfa5204ba167425d6c26eb67b7e7"}, +    {file = "SQLAlchemy-2.0.15-cp311-cp311-win_amd64.whl", hash = "sha256:5cc48a7fda2b5c5b8860494d6c575db3a101a68416492105fed6591dc8a2728a"}, +    {file = "SQLAlchemy-2.0.15-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f6fd3c88ea4b170d13527e93be1945e69facd917661d3725a63470eb683fbffe"}, +    {file = "SQLAlchemy-2.0.15-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e885dacb167077df15af2f9ccdacbd7f5dd0d538a6d74b94074f2cefc7bb589"}, +    {file = "SQLAlchemy-2.0.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:201a99f922ac8c780b3929128fbd9df901418877c70e160e19adb05665e51c31"}, +    {file = "SQLAlchemy-2.0.15-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e17fdcb8971e77c439113642ca8861f9465e21fc693bd3916654ceef3ac26883"}, +    {file = "SQLAlchemy-2.0.15-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db269f67ed17b07e80aaa8fba1f650c0d84aa0bdd9d5352e4ac38d5bf47ac568"}, +    {file = "SQLAlchemy-2.0.15-cp37-cp37m-win32.whl", hash = "sha256:994a75b197662e0608b6a76935d7c345f7fd874eac0b7093d561033db61b0e8c"}, +    {file = "SQLAlchemy-2.0.15-cp37-cp37m-win_amd64.whl", hash = "sha256:4d61731a35eddb0f667774fe15e5a4831e444d066081d1e809e1b8a0e3f97cae"}, +    {file = "SQLAlchemy-2.0.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f7f994a53c0e6b44a2966fd6bfc53e37d34b7dca34e75b6be295de6db598255e"}, +    {file = "SQLAlchemy-2.0.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:79bfe728219239bdc493950ea4a4d15b02138ecb304771f9024d0d6f5f4e3706"}, +    {file = "SQLAlchemy-2.0.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6320a1d175447dce63618ec997a53836de48ed3b44bbe952f0b4b399b19941"}, +    {file = "SQLAlchemy-2.0.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f80a9c9a9af0e4bd5080cc0955ce70274c28e9b931ad7e0fb07021afcd32af6"}, +    {file = "SQLAlchemy-2.0.15-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4a75fdb9a84072521bb2ebd31eefe1165d4dccea3039dda701a864f4b5daa17f"}, +    {file = "SQLAlchemy-2.0.15-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:21c89044fc48a25c2184eba332edeffbbf9367913bb065cd31538235d828f06f"}, +    {file = "SQLAlchemy-2.0.15-cp38-cp38-win32.whl", hash = "sha256:1a0754c2d9f0c7982bec0a31138e495ed1f6b8435d7e677c45be60ec18370acf"}, +    {file = "SQLAlchemy-2.0.15-cp38-cp38-win_amd64.whl", hash = "sha256:bc5c2b0da46c26c5f73f700834f871d0723e1e882641932468d56833bab09775"}, +    {file = "SQLAlchemy-2.0.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:670ecf74ee2e70b917028a06446ad26ff9b1195e84b09c3139c215123d57dc30"}, +    {file = "SQLAlchemy-2.0.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d14282bf5b4de87f922db3c70858953fd081ef4f05dba6cca3dd705daffe1cc9"}, +    {file = "SQLAlchemy-2.0.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:256b2b9660e51ad7055a9835b12717416cf7288afcf465107413917b6bb2316f"}, +    {file = "SQLAlchemy-2.0.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:810199d1c5b43603a9e815ae9487aef3ab1ade7ed9c0c485e12519358929fbfe"}, +    {file = "SQLAlchemy-2.0.15-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:536c86ec81ca89291d533ff41a3a05f9e4e88e01906dcee0751fc7082f3e8d6c"}, +    {file = "SQLAlchemy-2.0.15-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:435f6807fa6a0597d84741470f19db204a7d34625ea121abd63e8d95f673f0c4"}, +    {file = "SQLAlchemy-2.0.15-cp39-cp39-win32.whl", hash = "sha256:da7381a883aee20b7d2ffda17d909b38134b6a625920e65239a1c681881df800"}, +    {file = "SQLAlchemy-2.0.15-cp39-cp39-win_amd64.whl", hash = "sha256:788d1772fb8dcd12091ca82809eef504ce0f2c423e45284bc351b872966ff554"}, +    {file = "SQLAlchemy-2.0.15-py3-none-any.whl", hash = "sha256:933d30273861fe61f014ce2a7e3c364915f5efe9ed250ec1066ca6ea5942c0bd"}, +    {file = "SQLAlchemy-2.0.15.tar.gz", hash = "sha256:2e940a8659ef870ae10e0d9e2a6d5aaddf0ff6e91f7d0d7732afc9e8c4be9bbc"},  ]  [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and platform_machine == \"aarch64\" or python_version >= \"3\" and platform_machine == \"ppc64le\" or python_version >= \"3\" and platform_machine == \"x86_64\" or python_version >= \"3\" and platform_machine == \"amd64\" or python_version >= \"3\" and platform_machine == \"AMD64\" or python_version >= \"3\" and platform_machine == \"win32\" or python_version >= \"3\" and platform_machine == \"WIN32\""} +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} +mypy = {version = ">=0.910", optional = true, markers = "extra == \"mypy\""} +typing-extensions = ">=4.2.0"  [package.extras]  aiomysql = ["aiomysql", "greenlet (!=0.4.17)"]  aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"]  asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2)"] +asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"]  mssql = ["pyodbc"]  mssql-pymssql = ["pymssql"]  mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"] -mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"] +mypy = ["mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0)"]  mysql-connector = ["mysql-connector-python"] -oracle = ["cx-oracle (>=7)", "cx-oracle (>=7,<8)"] +oracle = ["cx-oracle (>=7)"] +oracle-oracledb = ["oracledb (>=1.0.1)"]  postgresql = ["psycopg2 (>=2.7)"]  postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"] +postgresql-pg8000 = ["pg8000 (>=1.29.1)"] +postgresql-psycopg = ["psycopg (>=3.0.7)"]  postgresql-psycopg2binary = ["psycopg2-binary"]  postgresql-psycopg2cffi = ["psycopg2cffi"] -pymysql = ["pymysql", "pymysql (<1)"] +pymysql = ["pymysql"]  sqlcipher = ["sqlcipher3-binary"]  [[package]]  name = "termcolor" -version = "2.2.0" +version = "2.3.0"  description = "ANSI color formatting for output in terminal" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "termcolor-2.2.0-py3-none-any.whl", hash = "sha256:91ddd848e7251200eac969846cbae2dacd7d71c2871e92733289e7e3666f48e7"}, -    {file = "termcolor-2.2.0.tar.gz", hash = "sha256:dfc8ac3f350788f23b2947b3e6cfa5a53b630b612e6cd8965a015a776020b99a"}, +    {file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"}, +    {file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"},  ]  [package.extras] @@ -1875,7 +1808,6 @@ tests = ["pytest", "pytest-cov"]  name = "text-unidecode"  version = "1.3"  description = "The most basic Text::Unidecode port" -category = "dev"  optional = false  python-versions = "*"  files = [ @@ -1887,7 +1819,6 @@ files = [  name = "tomli"  version = "2.0.1"  description = "A lil' TOML parser" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ @@ -1897,21 +1828,19 @@ files = [  [[package]]  name = "tomlkit" -version = "0.11.7" +version = "0.11.8"  description = "Style preserving TOML library" -category = "dev"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "tomlkit-0.11.7-py3-none-any.whl", hash = "sha256:5325463a7da2ef0c6bbfefb62a3dc883aebe679984709aee32a317907d0a8d3c"}, -    {file = "tomlkit-0.11.7.tar.gz", hash = "sha256:f392ef70ad87a672f02519f99967d28a4d3047133e2d1df936511465fbb3791d"}, +    {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, +    {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"},  ]  [[package]]  name = "transaction"  version = "3.1.0"  description = "Transaction management for Python" -category = "main"  optional = false  python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"  files = [ @@ -1931,7 +1860,6 @@ testing = ["coverage", "mock", "nose"]  name = "translationstring"  version = "1.4"  description = "Utility library for i18n relied on by various Repoze and Pyramid packages" -category = "main"  optional = false  python-versions = "*"  files = [ @@ -1944,14 +1872,13 @@ docs = ["Sphinx (>=1.3.1)", "docutils", "pylons-sphinx-themes"]  [[package]]  name = "types-babel" -version = "2.11.0.12" +version = "2.11.0.13"  description = "Typing stubs for babel" -category = "dev"  optional = false  python-versions = "*"  files = [ -    {file = "types-babel-2.11.0.12.tar.gz", hash = "sha256:ab490b5e41714c90745bfe6a668ebbded22c22ba6ea9747768b4d4d4b194248f"}, -    {file = "types_babel-2.11.0.12-py3-none-any.whl", hash = "sha256:ce562b53ac3be1a32494e05031a565cab352625aefc38db392e236ff5eeb5f1b"}, +    {file = "types-babel-2.11.0.13.tar.gz", hash = "sha256:c6bfd394f3d39ac6fd0d414b86686626014ddab5b470d26476784a7500b639f1"}, +    {file = "types_babel-2.11.0.13-py3-none-any.whl", hash = "sha256:1fa0d6fcae656a58f6de1cb85a5efb0babbaf80ca8cbffdf02212ba2e441d945"},  ]  [package.dependencies] @@ -1959,26 +1886,24 @@ types-pytz = "*"  [[package]]  name = "types-markdown" -version = "3.4.2.7" +version = "3.4.2.9"  description = "Typing stubs for Markdown" -category = "dev"  optional = false  python-versions = "*"  files = [ -    {file = "types-Markdown-3.4.2.7.tar.gz", hash = "sha256:ecea668b1e5aaa8fb4f7067622af3c3341cb9145baa4d939b7c75d3e1eb26f7f"}, -    {file = "types_Markdown-3.4.2.7-py3-none-any.whl", hash = "sha256:7fd3ecb487f1d41c043fa24c00258ab7e1fe37585ee6ad016a1a3c03bca34f73"}, +    {file = "types-Markdown-3.4.2.9.tar.gz", hash = "sha256:0930057bea0a534e06bbc021d57520720ad2a65b363612614ab0599cc7f606a9"}, +    {file = "types_Markdown-3.4.2.9-py3-none-any.whl", hash = "sha256:c23a8a4dd9313539a446ba3dc673a6a920d79580c406de10a5c85a16733890a7"},  ]  [[package]]  name = "types-pyopenssl" -version = "23.1.0.2" +version = "23.2.0.0"  description = "Typing stubs for pyOpenSSL" -category = "dev"  optional = false  python-versions = "*"  files = [ -    {file = "types-pyOpenSSL-23.1.0.2.tar.gz", hash = "sha256:20b80971b86240e8432a1832bd8124cea49c3088c7bfc77dfd23be27ffe4a517"}, -    {file = "types_pyOpenSSL-23.1.0.2-py3-none-any.whl", hash = "sha256:b050641aeff6dfebf231ad719bdac12d53b8ee818d4afb67b886333484629957"}, +    {file = "types-pyOpenSSL-23.2.0.0.tar.gz", hash = "sha256:43e307e8dfb3a7a8208a19874ca060305f460c529d4eaca8a2669ea89499f244"}, +    {file = "types_pyOpenSSL-23.2.0.0-py3-none-any.whl", hash = "sha256:ba803a99440b0c2e9ab4e197084aeefc55bdfe8a580d367b2aa4210810a21240"},  ]  [package.dependencies] @@ -1988,7 +1913,6 @@ cryptography = ">=35.0.0"  name = "types-pytz"  version = "2023.3.0.0"  description = "Typing stubs for pytz" -category = "dev"  optional = false  python-versions = "*"  files = [ @@ -1998,14 +1922,13 @@ files = [  [[package]]  name = "types-redis" -version = "4.5.4.1" +version = "4.5.5.2"  description = "Typing stubs for redis" -category = "dev"  optional = false  python-versions = "*"  files = [ -    {file = "types-redis-4.5.4.1.tar.gz", hash = "sha256:bf04192f415b2b42ecefd70bb4b91eb0352e48f2716a213e038e35c096a639c2"}, -    {file = "types_redis-4.5.4.1-py3-none-any.whl", hash = "sha256:2db530f54facec3149147bfe61d5ac24f5fe4e871823d95a601cd2c1d775d8a0"}, +    {file = "types-redis-4.5.5.2.tar.gz", hash = "sha256:2fe82f374d9dddf007deaf23d81fddcfd9523d9522bf11523c5c43bc5b27099e"}, +    {file = "types_redis-4.5.5.2-py3-none-any.whl", hash = "sha256:bf8692252038dbe03b007ca4fde87d3ae8e10610854a6858e3bf5d01721a7c4b"},  ]  [package.dependencies] @@ -2014,65 +1937,61 @@ types-pyOpenSSL = "*"  [[package]]  name = "types-requests" -version = "2.28.11.17" +version = "2.31.0.1"  description = "Typing stubs for requests" -category = "dev"  optional = false  python-versions = "*"  files = [ -    {file = "types-requests-2.28.11.17.tar.gz", hash = "sha256:0d580652ce903f643f8c3b494dd01d29367ea57cea0c7ad7f65cf3169092edb0"}, -    {file = "types_requests-2.28.11.17-py3-none-any.whl", hash = "sha256:cc1aba862575019306b2ed134eb1ea994cab1c887a22e18d3383e6dd42e9789b"}, +    {file = "types-requests-2.31.0.1.tar.gz", hash = "sha256:3de667cffa123ce698591de0ad7db034a5317457a596eb0b4944e5a9d9e8d1ac"}, +    {file = "types_requests-2.31.0.1-py3-none-any.whl", hash = "sha256:afb06ef8f25ba83d59a1d424bd7a5a939082f94b94e90ab5e6116bd2559deaa3"},  ]  [package.dependencies] -types-urllib3 = "<1.27" +types-urllib3 = "*"  [[package]]  name = "types-urllib3" -version = "1.26.25.10" +version = "1.26.25.13"  description = "Typing stubs for urllib3" -category = "dev"  optional = false  python-versions = "*"  files = [ -    {file = "types-urllib3-1.26.25.10.tar.gz", hash = "sha256:c44881cde9fc8256d05ad6b21f50c4681eb20092552351570ab0a8a0653286d6"}, -    {file = "types_urllib3-1.26.25.10-py3-none-any.whl", hash = "sha256:12c744609d588340a07e45d333bf870069fc8793bcf96bae7a96d4712a42591d"}, +    {file = "types-urllib3-1.26.25.13.tar.gz", hash = "sha256:3300538c9dc11dad32eae4827ac313f5d986b8b21494801f1bf97a1ac6c03ae5"}, +    {file = "types_urllib3-1.26.25.13-py3-none-any.whl", hash = "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c"},  ]  [[package]]  name = "typing-extensions" -version = "4.5.0" +version = "4.6.3"  description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, -    {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, +    {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"}, +    {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"},  ]  [[package]]  name = "urllib3" -version = "1.26.15" +version = "2.0.2"  description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main"  optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7"  files = [ -    {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, -    {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, +    {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, +    {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"},  ]  [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"]  [[package]]  name = "venusian"  version = "3.0.0"  description = "A library for deferring decorator actions" -category = "main"  optional = false  python-versions = ">=3.5"  files = [ @@ -2088,7 +2007,6 @@ testing = ["coverage", "pytest", "pytest-cov"]  name = "waitress"  version = "2.1.2"  description = "Waitress WSGI server" -category = "main"  optional = false  python-versions = ">=3.7.0"  files = [ @@ -2104,7 +2022,6 @@ testing = ["coverage (>=5.0)", "pytest", "pytest-cover"]  name = "webob"  version = "1.8.7"  description = "WSGI request and response object" -category = "main"  optional = false  python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*"  files = [ @@ -2120,7 +2037,6 @@ testing = ["coverage", "pytest (>=3.1.0)", "pytest-cov", "pytest-xdist"]  name = "webtest"  version = "3.0.0"  description = "Helper to test WSGI applications" -category = "dev"  optional = false  python-versions = ">=3.6, <4"  files = [ @@ -2141,7 +2057,6 @@ tests = ["PasteDeploy", "WSGIProxy2", "coverage", "pyquery", "pytest", "pytest-c  name = "wrapt"  version = "1.15.0"  description = "Module for decorators, wrappers and monkey patching." -category = "dev"  optional = false  python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"  files = [ @@ -2226,7 +2141,6 @@ files = [  name = "zipp"  version = "3.15.0"  description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -2242,7 +2156,6 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more  name = "zope-deprecation"  version = "5.0"  description = "Zope Deprecation Infrastructure" -category = "main"  optional = false  python-versions = ">= 3.7"  files = [ @@ -2261,7 +2174,6 @@ test = ["zope.testrunner"]  name = "zope-interface"  version = "6.0"  description = "Interfaces for Python" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ @@ -2307,19 +2219,19 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]  [[package]]  name = "zope-sqlalchemy" -version = "2.0" +version = "3.0"  description = "Minimal Zope/SQLAlchemy transaction integration" -category = "main"  optional = false  python-versions = ">=3.7"  files = [ -    {file = "zope.sqlalchemy-2.0-py3-none-any.whl", hash = "sha256:39e13e982faeb9494d4e89f301a765bb1ea91093244de821b192ddcab70ca15b"}, -    {file = "zope.sqlalchemy-2.0.tar.gz", hash = "sha256:cdf70cd57b8beb0ca9a81754abbf5c80ef0b53e8d8b2d894ac20bfc73870df12"}, +    {file = "zope.sqlalchemy-3.0-py3-none-any.whl", hash = "sha256:1b8f2d1fbb792577026a384969ef7e172944d0cd39b5d1a04d1e6288ba490b0b"}, +    {file = "zope.sqlalchemy-3.0.tar.gz", hash = "sha256:332ddcb71851ab3081b765a4dc659d1f8f822f870265b7add390fba5aceb5411"},  ]  [package.dependencies] +packaging = "*"  setuptools = "*" -SQLAlchemy = ">=1.1,<1.4.0 || >1.4.0,<1.4.1 || >1.4.1,<1.4.2 || >1.4.2,<1.4.3 || >1.4.3,<1.4.4 || >1.4.4,<1.4.5 || >1.4.5,<1.4.6 || >1.4.6,<2" +SQLAlchemy = ">=1.1,<1.4.0 || >1.4.0,<1.4.1 || >1.4.1,<1.4.2 || >1.4.2,<1.4.3 || >1.4.3,<1.4.4 || >1.4.4,<1.4.5 || >1.4.5,<1.4.6 || >1.4.6"  transaction = ">=1.6.0"  "zope.interface" = ">=3.6.0" @@ -2329,4 +2241,4 @@ test = ["zope.testing"]  [metadata]  lock-version = "2.0"  python-versions = "^3.9" -content-hash = "fbb50a44304a40cbcd0a59a5e908dd547b3619db66329b8b17a44d56f069f633" +content-hash = "283b9e3c547efddcd5e6ed7892f70a0a976847ea42e3c7da3c358eae325cf6c5" diff --git a/pyproject.toml b/pyproject.toml index 9ce137c..74b9bb3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,14 +34,14 @@ pyramid_retry = "^2.1"  pyramid_tm = "^2.5"  waitress = "^2.1" -SQLAlchemy = "^1.4" +SQLAlchemy = { version = "^2.0.15", extras = ["mypy"] }  alembic = "^1.8"  transaction = "^3" -"zope.sqlalchemy" = "^2.0" +"zope.sqlalchemy" = "^3.0"  redis = "^4.3.4"  Babel = "^2.11" -cryptography = "^40.0.2" +cryptography = "^41.0.1"  gpxpy = "^1.5"  markdown = "^3.4"  nh3 = "^0.2.9"  | 
