Compare commits
10 Commits
e94bb778c0
...
35cf66d403
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35cf66d403 | ||
|
|
86ba071b6c | ||
|
|
7532c960f2 | ||
|
|
a9a2bb5646 | ||
|
|
f2c4316e29 | ||
|
|
bc6f8e8f5c | ||
|
|
4041d28b03 | ||
|
|
4c4ce64025 | ||
|
|
82a3e729f1 | ||
|
|
97a740417b |
44
.github/workflows/docker.yml
vendored
Normal file
44
.github/workflows/docker.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository and submodules
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Set up QEMU
|
||||||
|
if: ${{ inputs.platforms != 'linux/amd64' }}
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: ${{ format('ghcr.io/{0}', github.repository) }}
|
||||||
|
tags: |
|
||||||
|
type=semver,pattern=v{{major}}
|
||||||
|
type=semver,pattern=v{{major}}.{{minor}}
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=tag
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}}
|
||||||
|
platforms: linux/amd64
|
||||||
19
Dockerfile
Normal file
19
Dockerfile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
FROM python:3.10-slim
|
||||||
|
|
||||||
|
COPY src /src
|
||||||
|
RUN cd /src \
|
||||||
|
&& pip install -r requirements.txt \
|
||||||
|
&& pip install -e .
|
||||||
|
|
||||||
|
COPY src/ankisyncd /ankisyncd
|
||||||
|
COPY src/ankisyncd_cli /ankisyncd_cli
|
||||||
|
COPY src/ankisyncd.conf /ankisyncd.conf
|
||||||
|
RUN sed -i -e '/data_root =/ s/= .*/= \/data\/collections/' /ankisyncd.conf \
|
||||||
|
&& sed -i -e '/auth_db_path =/ s/= .*/= \/data\/auth\.db/' /ankisyncd.conf \
|
||||||
|
&& sed -i -e '/session_db_path =/ s/= .*/= \/data\/session.db/' /ankisyncd.conf \
|
||||||
|
&& cat /ankisyncd.conf
|
||||||
|
|
||||||
|
#see https://github.com/ankicommunity/anki-sync-server/issues/139
|
||||||
|
ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
|
||||||
|
|
||||||
|
CMD ["python", "-m", "ankisyncd"]
|
||||||
17
README.md
17
README.md
@ -31,15 +31,10 @@ Linux and macOS) which can sync to a web version (AnkiWeb) and mobile
|
|||||||
versions for Android and iOS.
|
versions for Android and iOS.
|
||||||
|
|
||||||
This is a personal Anki server, which you can sync against instead of
|
This is a personal Anki server, which you can sync against instead of
|
||||||
AnkiWeb. It was originally developed by [David Snopek](https://github.com/dsnopek)
|
AnkiWeb.
|
||||||
to support the flashcard functionality on Bibliobird, a web application for
|
|
||||||
language learning.
|
|
||||||
|
|
||||||
This version is a fork of [jdoe0/ankisyncd](https://github.com/jdoe0/ankisyncd).
|
|
||||||
It supports Python 3 and Anki 2.1.
|
|
||||||
|
|
||||||
[Anki]: https://apps.ankiweb.net/
|
[Anki]: https://apps.ankiweb.net/
|
||||||
[dsnopek's Anki Sync Server]: https://github.com/dsnopek/anki-sync-server
|
|
||||||
|
|
||||||
<details open><summary>Contents</summary>
|
<details open><summary>Contents</summary>
|
||||||
|
|
||||||
@ -254,3 +249,11 @@ sqlite3 is used by default for user data, authentication and session persistence
|
|||||||
persistence requirements (the media DB and files are being worked on). All that is
|
persistence requirements (the media DB and files are being worked on). All that is
|
||||||
required is to extend one of the existing manager classes and then reference those
|
required is to extend one of the existing manager classes and then reference those
|
||||||
classes in the config file. See ankisyncd.conf for example config.
|
classes in the config file. See ankisyncd.conf for example config.
|
||||||
|
|
||||||
|
## Acknowledgment
|
||||||
|
|
||||||
|
- This server was originally developed by [David Snopek](https://github.com/dsnopek)
|
||||||
|
to support the flashcard functionality on Bibliobird, a web application for
|
||||||
|
language learning.
|
||||||
|
- It was then forked by `jdoe0` to add supports Python 3 and Anki 2.1.
|
||||||
|
- It was then forked by [tsudoko](https://github.com/tsudoko) which was the base for this repo.
|
||||||
|
|||||||
4526
poetry.lock
generated
4526
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@ def load_from_env(conf):
|
|||||||
|
|
||||||
def load_from_file(path=None):
|
def load_from_file(path=None):
|
||||||
# backwards compat
|
# backwards compat
|
||||||
if len(path) > 1:
|
if path is not None and len(path) > 1:
|
||||||
path = path[1]
|
path = path[1]
|
||||||
else:
|
else:
|
||||||
path = None
|
path = None
|
||||||
|
|||||||
1
src/ankisyncd/exceptions.py
Normal file
1
src/ankisyncd/exceptions.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from webob.exc import HTTPBadRequest as BadRequestException
|
||||||
@ -1,10 +1,11 @@
|
|||||||
import shutil
|
import shutil
|
||||||
from sqlite3 import dbapi2 as sqlite
|
from sqlite3 import dbapi2 as sqlite
|
||||||
from webob.exc import HTTPBadRequest
|
|
||||||
|
|
||||||
from anki.db import DB
|
from anki.db import DB
|
||||||
from anki.collection import Collection
|
from anki.collection import Collection
|
||||||
|
|
||||||
|
from ankisyncd.exceptions import BadRequestException
|
||||||
|
|
||||||
|
|
||||||
class FullSyncManager:
|
class FullSyncManager:
|
||||||
def test_db(self, db: DB):
|
def test_db(self, db: DB):
|
||||||
@ -12,7 +13,7 @@ class FullSyncManager:
|
|||||||
:param anki.db.DB db: the database uploaded from the client.
|
:param anki.db.DB db: the database uploaded from the client.
|
||||||
"""
|
"""
|
||||||
if db.scalar("pragma integrity_check") != "ok":
|
if db.scalar("pragma integrity_check") != "ok":
|
||||||
raise HTTPBadRequest(
|
raise BadRequestException(
|
||||||
"Integrity check failed for uploaded collection database file."
|
"Integrity check failed for uploaded collection database file."
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,7 +35,9 @@ class FullSyncManager:
|
|||||||
with DB(temp_db_path) as test_db:
|
with DB(temp_db_path) as test_db:
|
||||||
self.test_db(test_db)
|
self.test_db(test_db)
|
||||||
except sqlite.Error as e:
|
except sqlite.Error as e:
|
||||||
raise HTTPBadRequest("Uploaded collection database file is " "corrupt.")
|
raise BadRequestException(
|
||||||
|
"Uploaded collection database file is " "corrupt."
|
||||||
|
)
|
||||||
|
|
||||||
# Overwrite existing db.
|
# Overwrite existing db.
|
||||||
col.close()
|
col.close()
|
||||||
|
|||||||
40
src/ankisyncd/sessions/__init__.py
Normal file
40
src/ankisyncd/sessions/__init__.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import inspect
|
||||||
|
from ankisyncd import logging
|
||||||
|
from ankisyncd.sessions.simple_manager import SimpleSessionManager
|
||||||
|
from ankisyncd.sessions.sqlite_manager import SqliteSessionManager
|
||||||
|
|
||||||
|
logger = logging.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def get_session_manager(config):
|
||||||
|
if "session_db_path" in config and config["session_db_path"]:
|
||||||
|
logger.info(
|
||||||
|
"Found session_db_path in config, using SqliteSessionManager for auth"
|
||||||
|
)
|
||||||
|
return SqliteSessionManager(config["session_db_path"])
|
||||||
|
elif "session_manager" in config and config["session_manager"]: # load from config
|
||||||
|
logger.info(
|
||||||
|
"Found session_manager in config, using {} for persisting sessions".format(
|
||||||
|
config["session_manager"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
module_name, class_name = config["session_manager"].rsplit(".", 1)
|
||||||
|
module = importlib.import_module(module_name.strip())
|
||||||
|
class_ = getattr(module, class_name.strip())
|
||||||
|
|
||||||
|
if not SimpleSessionManager in inspect.getmro(class_):
|
||||||
|
raise TypeError(
|
||||||
|
""""session_manager" found in the conf file but it doesn''t
|
||||||
|
inherit from SimpleSessionManager"""
|
||||||
|
)
|
||||||
|
return class_(config)
|
||||||
|
else:
|
||||||
|
logger.warning(
|
||||||
|
"Neither session_db_path nor session_manager set, "
|
||||||
|
"ankisyncd will lose sessions on application restart"
|
||||||
|
)
|
||||||
|
return SimpleSessionManager()
|
||||||
19
src/ankisyncd/sessions/simple_manager.py
Normal file
19
src/ankisyncd/sessions/simple_manager.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
class SimpleSessionManager:
|
||||||
|
"""A simple session manager that keeps the sessions in memory."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.sessions = {}
|
||||||
|
|
||||||
|
def load(self, hkey, session_factory=None):
|
||||||
|
return self.sessions.get(hkey)
|
||||||
|
|
||||||
|
def load_from_skey(self, skey, session_factory=None):
|
||||||
|
for i in self.sessions:
|
||||||
|
if self.sessions[i].skey == skey:
|
||||||
|
return self.sessions[i]
|
||||||
|
|
||||||
|
def save(self, hkey, session):
|
||||||
|
self.sessions[hkey] = session
|
||||||
|
|
||||||
|
def delete(self, hkey):
|
||||||
|
del self.sessions[hkey]
|
||||||
@ -1,30 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
import os
|
import os
|
||||||
import logging
|
|
||||||
from sqlite3 import dbapi2 as sqlite
|
from sqlite3 import dbapi2 as sqlite
|
||||||
|
from ankisyncd.sessions.simple_manager import SimpleSessionManager
|
||||||
logger = logging.getLogger("ankisyncd.sessions")
|
|
||||||
|
|
||||||
|
|
||||||
class SimpleSessionManager:
|
|
||||||
"""A simple session manager that keeps the sessions in memory."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.sessions = {}
|
|
||||||
|
|
||||||
def load(self, hkey, session_factory=None):
|
|
||||||
return self.sessions.get(hkey)
|
|
||||||
|
|
||||||
def load_from_skey(self, skey, session_factory=None):
|
|
||||||
for i in self.sessions:
|
|
||||||
if self.sessions[i].skey == skey:
|
|
||||||
return self.sessions[i]
|
|
||||||
|
|
||||||
def save(self, hkey, session):
|
|
||||||
self.sessions[hkey] = session
|
|
||||||
|
|
||||||
def delete(self, hkey):
|
|
||||||
del self.sessions[hkey]
|
|
||||||
|
|
||||||
|
|
||||||
class SqliteSessionManager(SimpleSessionManager):
|
class SqliteSessionManager(SimpleSessionManager):
|
||||||
@ -128,36 +104,3 @@ class SqliteSessionManager(SimpleSessionManager):
|
|||||||
|
|
||||||
cursor.execute(self.fs("DELETE FROM session WHERE hkey=?"), (hkey,))
|
cursor.execute(self.fs("DELETE FROM session WHERE hkey=?"), (hkey,))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
|
||||||
def get_session_manager(config):
|
|
||||||
if "session_db_path" in config and config["session_db_path"]:
|
|
||||||
logger.info(
|
|
||||||
"Found session_db_path in config, using SqliteSessionManager for auth"
|
|
||||||
)
|
|
||||||
return SqliteSessionManager(config["session_db_path"])
|
|
||||||
elif "session_manager" in config and config["session_manager"]: # load from config
|
|
||||||
logger.info(
|
|
||||||
"Found session_manager in config, using {} for persisting sessions".format(
|
|
||||||
config["session_manager"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
import importlib
|
|
||||||
import inspect
|
|
||||||
|
|
||||||
module_name, class_name = config["session_manager"].rsplit(".", 1)
|
|
||||||
module = importlib.import_module(module_name.strip())
|
|
||||||
class_ = getattr(module, class_name.strip())
|
|
||||||
|
|
||||||
if not SimpleSessionManager in inspect.getmro(class_):
|
|
||||||
raise TypeError(
|
|
||||||
""""session_manager" found in the conf file but it doesn''t
|
|
||||||
inherit from SimpleSessionManager"""
|
|
||||||
)
|
|
||||||
return class_(config)
|
|
||||||
else:
|
|
||||||
logger.warning(
|
|
||||||
"Neither session_db_path nor session_manager set, "
|
|
||||||
"ankisyncd will lose sessions on application restart"
|
|
||||||
)
|
|
||||||
return SimpleSessionManager()
|
|
||||||
38
src/ankisyncd/users/__init__.py
Normal file
38
src/ankisyncd/users/__init__.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
from ankisyncd import logging
|
||||||
|
from ankisyncd.users.simple_manager import SimpleUserManager
|
||||||
|
from ankisyncd.users.sqlite_manager import SqliteUserManager
|
||||||
|
|
||||||
|
logger = logging.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_manager(config):
|
||||||
|
if "auth_db_path" in config and config["auth_db_path"]:
|
||||||
|
logger.info("Found auth_db_path in config, using SqliteUserManager for auth")
|
||||||
|
return SqliteUserManager(config["auth_db_path"], config["data_root"])
|
||||||
|
elif "user_manager" in config and config["user_manager"]: # load from config
|
||||||
|
logger.info(
|
||||||
|
"Found user_manager in config, using {} for auth".format(
|
||||||
|
config["user_manager"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
module_name, class_name = config["user_manager"].rsplit(".", 1)
|
||||||
|
module = importlib.import_module(module_name.strip())
|
||||||
|
class_ = getattr(module, class_name.strip())
|
||||||
|
|
||||||
|
if not SimpleUserManager in inspect.getmro(class_):
|
||||||
|
raise TypeError(
|
||||||
|
""""user_manager" found in the conf file but it doesn''t
|
||||||
|
inherit from SimpleUserManager"""
|
||||||
|
)
|
||||||
|
return class_(config)
|
||||||
|
else:
|
||||||
|
logger.warning(
|
||||||
|
"neither auth_db_path nor user_manager set, ankisyncd will accept any password"
|
||||||
|
)
|
||||||
|
return SimpleUserManager()
|
||||||
38
src/ankisyncd/users/simple_manager.py
Normal file
38
src/ankisyncd/users/simple_manager.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import os
|
||||||
|
from ankisyncd import logging
|
||||||
|
|
||||||
|
logger = logging.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleUserManager:
|
||||||
|
"""A simple user manager that always allows any user."""
|
||||||
|
|
||||||
|
def __init__(self, collection_path=""):
|
||||||
|
self.collection_path = collection_path
|
||||||
|
|
||||||
|
def authenticate(self, username, password):
|
||||||
|
"""
|
||||||
|
Returns True if this username is allowed to connect with this password.
|
||||||
|
False otherwise. Override this to change how users are authenticated.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def userdir(self, username):
|
||||||
|
"""
|
||||||
|
Returns the directory name for the given user. By default, this is just
|
||||||
|
the username. Override this to adjust the mapping between users and
|
||||||
|
their directory.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return username
|
||||||
|
|
||||||
|
def _create_user_dir(self, username):
|
||||||
|
user_dir_path = os.path.join(self.collection_path, username)
|
||||||
|
if not os.path.isdir(user_dir_path):
|
||||||
|
logger.info(
|
||||||
|
"Creating collection directory for user '{}' at {}".format(
|
||||||
|
username, user_dir_path
|
||||||
|
)
|
||||||
|
)
|
||||||
|
os.makedirs(user_dir_path)
|
||||||
@ -1,45 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
import binascii
|
import binascii
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
import sqlite3 as sqlite
|
import sqlite3 as sqlite
|
||||||
|
from ankisyncd import logging
|
||||||
|
from ankisyncd.users.simple_manager import SimpleUserManager
|
||||||
|
|
||||||
logger = logging.getLogger("ankisyncd.users")
|
logger = logging.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SimpleUserManager:
|
|
||||||
"""A simple user manager that always allows any user."""
|
|
||||||
|
|
||||||
def __init__(self, collection_path=""):
|
|
||||||
self.collection_path = collection_path
|
|
||||||
|
|
||||||
def authenticate(self, username, password):
|
|
||||||
"""
|
|
||||||
Returns True if this username is allowed to connect with this password.
|
|
||||||
False otherwise. Override this to change how users are authenticated.
|
|
||||||
"""
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def userdir(self, username):
|
|
||||||
"""
|
|
||||||
Returns the directory name for the given user. By default, this is just
|
|
||||||
the username. Override this to adjust the mapping between users and
|
|
||||||
their directory.
|
|
||||||
"""
|
|
||||||
|
|
||||||
return username
|
|
||||||
|
|
||||||
def _create_user_dir(self, username):
|
|
||||||
user_dir_path = os.path.join(self.collection_path, username)
|
|
||||||
if not os.path.isdir(user_dir_path):
|
|
||||||
logger.info(
|
|
||||||
"Creating collection directory for user '{}' at {}".format(
|
|
||||||
username, user_dir_path
|
|
||||||
)
|
|
||||||
)
|
|
||||||
os.makedirs(user_dir_path)
|
|
||||||
|
|
||||||
|
|
||||||
class SqliteUserManager(SimpleUserManager):
|
class SqliteUserManager(SimpleUserManager):
|
||||||
@ -208,33 +174,3 @@ class SqliteUserManager(SimpleUserManager):
|
|||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
def get_user_manager(config):
|
|
||||||
if "auth_db_path" in config and config["auth_db_path"]:
|
|
||||||
logger.info("Found auth_db_path in config, using SqliteUserManager for auth")
|
|
||||||
return SqliteUserManager(config["auth_db_path"], config["data_root"])
|
|
||||||
elif "user_manager" in config and config["user_manager"]: # load from config
|
|
||||||
logger.info(
|
|
||||||
"Found user_manager in config, using {} for auth".format(
|
|
||||||
config["user_manager"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
import importlib
|
|
||||||
import inspect
|
|
||||||
|
|
||||||
module_name, class_name = config["user_manager"].rsplit(".", 1)
|
|
||||||
module = importlib.import_module(module_name.strip())
|
|
||||||
class_ = getattr(module, class_name.strip())
|
|
||||||
|
|
||||||
if not SimpleUserManager in inspect.getmro(class_):
|
|
||||||
raise TypeError(
|
|
||||||
""""user_manager" found in the conf file but it doesn''t
|
|
||||||
inherit from SimpleUserManager"""
|
|
||||||
)
|
|
||||||
return class_(config)
|
|
||||||
else:
|
|
||||||
logger.warning(
|
|
||||||
"neither auth_db_path nor user_manager set, ankisyncd will accept any password"
|
|
||||||
)
|
|
||||||
return SimpleUserManager()
|
|
||||||
@ -3,11 +3,12 @@
|
|||||||
import sys
|
import sys
|
||||||
import getpass
|
import getpass
|
||||||
|
|
||||||
from ankisyncd import config
|
from ankisyncd import config as config_provider
|
||||||
from ankisyncd.users import get_user_manager
|
from ankisyncd.users import get_user_manager
|
||||||
|
|
||||||
|
|
||||||
config = config.load()
|
config = config_provider.load_from_file()
|
||||||
|
config_provider.load_from_env(config)
|
||||||
|
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
|
|||||||
@ -2,124 +2,139 @@
|
|||||||
|
|
||||||
|
|
||||||
anki==2.1.49 ; python_version >= "3.8" and python_version < "4.0"
|
anki==2.1.49 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
anyio==3.6.1 ; python_version >= "3.8" and python_version < "4.0"
|
anyio==3.7.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
appnope==0.1.3 ; python_version >= "3.8" and python_version < "4.0" and platform_system == "Darwin" or python_version >= "3.8" and python_version < "4.0" and sys_platform == "darwin"
|
appnope==0.1.3 ; python_version >= "3.8" and python_version < "4.0" and (platform_system == "Darwin" or sys_platform == "darwin")
|
||||||
argon2-cffi-bindings==21.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
argon2-cffi-bindings==21.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
argon2-cffi==21.3.0 ; python_version >= "3.8" and python_version < "4.0"
|
argon2-cffi==21.3.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
asttokens==2.0.8 ; python_version >= "3.8" and python_version < "4.0"
|
arrow==1.2.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
attrs==22.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
asttokens==2.2.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
attrs==23.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
backcall==0.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
backcall==0.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
beautifulsoup4==4.11.1 ; python_version >= "3.8" and python_version < "4.0"
|
beautifulsoup4==4.12.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
black==22.10.0 ; python_version >= "3.8" and python_version < "4.0"
|
black==22.12.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
bleach==5.0.1 ; python_version >= "3.8" and python_version < "4.0"
|
bleach==6.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
certifi==2022.9.24 ; python_version >= "3.8" and python_version < "4"
|
certifi==2023.5.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
cffi==1.15.1 ; python_version >= "3.8" and python_version < "4.0"
|
cffi==1.15.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
charset-normalizer==2.1.1 ; python_version >= "3.8" and python_version < "4"
|
charset-normalizer==3.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
click==8.1.3 ; python_version >= "3.8" and python_version < "4.0"
|
click==8.1.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
colorama==0.4.5 ; python_version >= "3.8" and python_version < "4.0" and platform_system == "Windows" or python_version >= "3.8" and python_version < "4.0" and sys_platform == "win32"
|
colorama==0.4.6 ; python_version >= "3.8" and python_version < "4.0" and (platform_system == "Windows" or sys_platform == "win32")
|
||||||
debugpy==1.6.3 ; python_version >= "3.8" and python_version < "4.0"
|
comm==0.1.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
debugpy==1.6.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
decorator==4.4.2 ; python_version >= "3.8" and python_version < "4.0"
|
decorator==4.4.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
defusedxml==0.7.1 ; python_version >= "3.8" and python_version < "4.0"
|
defusedxml==0.7.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
distro==1.8.0 ; python_version >= "3.8" and python_version < "4.0"
|
distro==1.8.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
entrypoints==0.4 ; python_version >= "3.8" and python_version < "4.0"
|
entrypoints==0.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
executing==1.1.1 ; python_version >= "3.8" and python_version < "4.0"
|
exceptiongroup==1.1.2 ; python_version >= "3.8" and python_version < "3.11"
|
||||||
fastjsonschema==2.16.2 ; python_version >= "3.8" and python_version < "4.0"
|
executing==1.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
fastjsonschema==2.17.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
fqdn==1.5.1 ; python_version >= "3.8" and python_version < "4"
|
||||||
ghp-import==2.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
ghp-import==2.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
idna==3.4 ; python_version >= "3.8" and python_version < "4"
|
idna==3.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
importlib-metadata==5.0.0 ; python_version >= "3.8" and python_version < "3.10"
|
importlib-metadata==6.8.0 ; python_version >= "3.8" and python_version < "3.10"
|
||||||
importlib-resources==5.10.0 ; python_version >= "3.8" and python_version < "3.9"
|
importlib-resources==6.0.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||||
ipykernel==6.16.0 ; python_version >= "3.8" and python_version < "4.0"
|
ipykernel==6.24.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
ipython-genutils==0.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
ipython-genutils==0.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
ipython==8.5.0 ; python_version >= "3.8" and python_version < "4.0"
|
ipython==8.12.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
ipywidgets==8.0.2 ; python_version >= "3.8" and python_version < "4.0"
|
ipywidgets==8.0.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jedi==0.18.1 ; python_version >= "3.8" and python_version < "4.0"
|
isoduration==20.11.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
jedi==0.18.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jinja2==3.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
jinja2==3.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
json5==0.9.10 ; python_version >= "3.8" and python_version < "4.0"
|
json5==0.9.14 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jsonschema==4.16.0 ; python_version >= "3.8" and python_version < "4.0"
|
jsonpointer==2.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupyter-client==7.4.2 ; python_version >= "3.8" and python_version < "4.0"
|
jsonschema-specifications==2023.6.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupyter-console==6.4.4 ; python_version >= "3.8" and python_version < "4.0"
|
jsonschema==4.18.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupyter-core==4.11.1 ; python_version >= "3.8" and python_version < "4.0"
|
jsonschema[format-nongpl]==4.18.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupyter-server==1.21.0 ; python_version >= "3.8" and python_version < "4.0"
|
jupyter-client==8.3.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
jupyter-console==6.6.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
jupyter-core==5.3.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
jupyter-events==0.6.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
jupyter-server-terminals==0.4.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
jupyter-server==2.7.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupyter==1.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
jupyter==1.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupyterlab-pygments==0.2.2 ; python_version >= "3.8" and python_version < "4.0"
|
jupyterlab-pygments==0.2.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupyterlab-server==1.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
jupyterlab-server==1.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupyterlab-widgets==3.0.3 ; python_version >= "3.8" and python_version < "4.0"
|
jupyterlab-widgets==3.0.8 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupyterlab==2.3.2 ; python_version >= "3.8" and python_version < "4.0"
|
jupyterlab==2.3.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
jupytext==1.14.1 ; python_version >= "3.8" and python_version < "4.0"
|
jupytext==1.14.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
lxml==4.9.1 ; python_version >= "3.8" and python_version < "4.0"
|
lxml==4.9.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
markdown-it-py==2.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
markdown-it-py==3.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
markdown==3.3.7 ; python_version >= "3.8" and python_version < "4.0"
|
markdown==3.3.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
markupsafe==2.1.1 ; python_version >= "3.8" and python_version < "4.0"
|
markupsafe==2.1.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
matplotlib-inline==0.1.6 ; python_version >= "3.8" and python_version < "4.0"
|
matplotlib-inline==0.1.6 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
mdit-py-plugins==0.3.1 ; python_version >= "3.8" and python_version < "4.0"
|
mdit-py-plugins==0.4.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
mdurl==0.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
mdurl==0.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
mergedeep==1.3.4 ; python_version >= "3.8" and python_version < "4.0"
|
mergedeep==1.3.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
mistune==0.8.4 ; python_version >= "3.8" and python_version < "4.0"
|
mistune==0.8.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
mkdocs-jupyter==0.19.0 ; python_version >= "3.8" and python_version < "4"
|
mkdocs-jupyter==0.19.0 ; python_version >= "3.8" and python_version < "4"
|
||||||
mkdocs-material-extensions==1.0.3 ; python_version >= "3.8" and python_version < "4"
|
mkdocs-material-extensions==1.1.1 ; python_version >= "3.8" and python_version < "4"
|
||||||
mkdocs-material==8.5.6 ; python_version >= "3.8" and python_version < "4"
|
mkdocs-material==8.5.11 ; python_version >= "3.8" and python_version < "4"
|
||||||
mkdocs==1.4.0 ; python_version >= "3.8" and python_version < "4.0"
|
mkdocs==1.4.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
mypy-extensions==0.4.3 ; python_version >= "3.8" and python_version < "4.0"
|
mypy-extensions==1.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
nbclassic==0.4.5 ; python_version >= "3.8" and python_version < "4.0"
|
nbclassic==1.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
nbclient==0.7.0 ; python_version >= "3.8" and python_version < "4.0"
|
nbclient==0.8.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
nbconvert==6.5.4 ; python_version >= "3.8" and python_version < "4.0"
|
nbconvert==6.5.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
nbformat==5.7.0 ; python_version >= "3.8" and python_version < "4.0"
|
nbformat==5.9.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
nest-asyncio==1.5.6 ; python_version >= "3.8" and python_version < "4.0"
|
nest-asyncio==1.5.6 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
notebook-shim==0.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
notebook-shim==0.2.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
notebook==6.5.1 ; python_version >= "3.8" and python_version < "4.0"
|
notebook==6.5.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
orjson==3.8.0 ; python_version >= "3.8" and python_version < "4.0" and platform_machine == "x86_64"
|
orjson==3.9.2 ; python_version >= "3.8" and python_version < "4.0" and platform_machine == "x86_64"
|
||||||
packaging==21.3 ; python_version >= "3.8" and python_version < "4.0"
|
overrides==7.3.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
packaging==23.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pandocfilters==1.5.0 ; python_version >= "3.8" and python_version < "4.0"
|
pandocfilters==1.5.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
parso==0.8.3 ; python_version >= "3.8" and python_version < "4.0"
|
parso==0.8.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pathspec==0.10.1 ; python_version >= "3.8" and python_version < "4.0"
|
pathspec==0.11.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pexpect==4.8.0 ; python_version >= "3.8" and python_version < "4.0" and sys_platform != "win32"
|
pexpect==4.8.0 ; python_version >= "3.8" and python_version < "4.0" and sys_platform != "win32"
|
||||||
pickleshare==0.7.5 ; python_version >= "3.8" and python_version < "4.0"
|
pickleshare==0.7.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pkgutil-resolve-name==1.3.10 ; python_version >= "3.8" and python_version < "3.9"
|
pkgutil-resolve-name==1.3.10 ; python_version >= "3.8" and python_version < "3.9"
|
||||||
platformdirs==2.5.2 ; python_version >= "3.8" and python_version < "4.0"
|
platformdirs==3.8.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
prometheus-client==0.15.0 ; python_version >= "3.8" and python_version < "4.0"
|
prometheus-client==0.17.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
prompt-toolkit==3.0.31 ; python_version >= "3.8" and python_version < "4.0"
|
prompt-toolkit==3.0.39 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
protobuf==3.20.2 ; python_version >= "3.8" and python_version < "4.0"
|
protobuf==3.20.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
psutil==5.9.2 ; python_version >= "3.8" and python_version < "4.0"
|
psutil==5.9.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
ptyprocess==0.7.0 ; python_version >= "3.8" and python_version < "4.0" and os_name != "nt" or python_version >= "3.8" and python_version < "4.0" and sys_platform != "win32"
|
ptyprocess==0.7.0 ; python_version >= "3.8" and python_version < "4.0" and (os_name != "nt" or sys_platform != "win32")
|
||||||
pure-eval==0.2.2 ; python_version >= "3.8" and python_version < "4.0"
|
pure-eval==0.2.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
py==1.11.0 ; python_version >= "3.8" and python_version < "4.0" and implementation_name == "pypy"
|
|
||||||
pycparser==2.21 ; python_version >= "3.8" and python_version < "4.0"
|
pycparser==2.21 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pygments==2.13.0 ; python_version >= "3.8" and python_version < "4.0"
|
pygments==2.15.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pymdown-extensions==9.6 ; python_version >= "3.8" and python_version < "4"
|
pymdown-extensions==10.1 ; python_version >= "3.8" and python_version < "4"
|
||||||
pyparsing==3.0.9 ; python_version >= "3.8" and python_version < "4.0"
|
pysocks==1.7.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pyrsistent==0.18.1 ; python_version >= "3.8" and python_version < "4.0"
|
|
||||||
pysocks==1.7.1 ; python_version >= "3.8" and python_version < "4"
|
|
||||||
python-dateutil==2.8.2 ; python_version >= "3.8" and python_version < "4.0"
|
python-dateutil==2.8.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pywin32==304 ; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.8" and python_version < "4.0"
|
python-json-logger==2.0.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pywinpty==2.0.8 ; python_version >= "3.8" and python_version < "4.0" and os_name == "nt"
|
pywin32==306 ; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.8" and python_version < "4.0"
|
||||||
|
pywinpty==2.0.10 ; python_version >= "3.8" and python_version < "4.0" and os_name == "nt"
|
||||||
pyyaml-env-tag==0.1 ; python_version >= "3.8" and python_version < "4.0"
|
pyyaml-env-tag==0.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pyyaml==6.0 ; python_version >= "3.8" and python_version < "4.0"
|
pyyaml==6.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pyzmq==24.0.1 ; python_version >= "3.8" and python_version < "4.0"
|
pyzmq==25.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
qtconsole==5.3.2 ; python_version >= "3.8" and python_version < "4.0"
|
qtconsole==5.4.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
qtpy==2.2.1 ; python_version >= "3.8" and python_version < "4.0"
|
qtpy==2.3.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
requests==2.28.1 ; python_version >= "3.8" and python_version < "4"
|
referencing==0.29.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
requests[socks]==2.28.1 ; python_version >= "3.8" and python_version < "4"
|
requests==2.31.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
send2trash==1.8.0 ; python_version >= "3.8" and python_version < "4.0"
|
requests[socks]==2.31.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
rfc3339-validator==0.1.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
rfc3986-validator==0.1.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
rpds-py==0.8.10 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
send2trash==1.8.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
six==1.16.0 ; python_version >= "3.8" and python_version < "4.0"
|
six==1.16.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
sniffio==1.3.0 ; python_version >= "3.8" and python_version < "4.0"
|
sniffio==1.3.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
soupsieve==2.3.2.post1 ; python_version >= "3.8" and python_version < "4.0"
|
soupsieve==2.4.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
stack-data==0.5.1 ; python_version >= "3.8" and python_version < "4.0"
|
stack-data==0.6.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
stringcase==1.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
stringcase==1.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
terminado==0.16.0 ; python_version >= "3.8" and python_version < "4.0"
|
terminado==0.17.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
tinycss2==1.1.1 ; python_version >= "3.8" and python_version < "4.0"
|
tinycss2==1.2.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
toml==0.10.2 ; python_version >= "3.8" and python_version < "4.0"
|
toml==0.10.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
tomli==2.0.1 ; python_version >= "3.8" and python_full_version < "3.11.0a7"
|
tomli==2.0.1 ; python_version >= "3.8" and python_full_version < "3.11.0a7"
|
||||||
tornado==6.2 ; python_version >= "3.8" and python_version < "4.0"
|
tornado==6.3.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
traitlets==5.4.0 ; python_version >= "3.8" and python_version < "4.0"
|
traitlets==5.9.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
typing-extensions==4.4.0 ; python_version >= "3.8" and python_version < "3.10"
|
typing-extensions==4.7.1 ; python_version >= "3.8" and python_version < "3.10"
|
||||||
urllib3==1.26.12 ; python_version >= "3.8" and python_version < "4"
|
uri-template==1.3.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
urllib3==2.0.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
waitress==2.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
waitress==2.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
watchdog==2.1.9 ; python_version >= "3.8" and python_version < "4.0"
|
watchdog==3.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
wcwidth==0.2.5 ; python_version >= "3.8" and python_version < "4.0"
|
wcwidth==0.2.6 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
|
webcolors==1.13 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
webencodings==0.5.1 ; python_version >= "3.8" and python_version < "4.0"
|
webencodings==0.5.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
webob==1.8.7 ; python_version >= "3.8" and python_version < "4.0"
|
webob==1.8.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
websocket-client==1.4.1 ; python_version >= "3.8" and python_version < "4.0"
|
websocket-client==1.6.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
webtest==2.0.35 ; python_version >= "3.8" and python_version < "4.0"
|
webtest==2.0.35 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
widgetsnbextension==4.0.3 ; python_version >= "3.8" and python_version < "4.0"
|
widgetsnbextension==4.0.8 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
zipp==3.9.0 ; python_version >= "3.8" and python_version < "3.10"
|
zipp==3.16.1 ; python_version >= "3.8" and python_version < "3.10"
|
||||||
-e src/.
|
-e src/.
|
||||||
|
|||||||
@ -2,23 +2,23 @@
|
|||||||
|
|
||||||
|
|
||||||
anki==2.1.49 ; python_version >= "3.8" and python_version < "4.0"
|
anki==2.1.49 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
beautifulsoup4==4.11.1 ; python_version >= "3.8" and python_version < "4.0"
|
beautifulsoup4==4.12.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
certifi==2022.9.24 ; python_version >= "3.8" and python_version < "4"
|
certifi==2023.5.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
charset-normalizer==2.1.1 ; python_version >= "3.8" and python_version < "4"
|
charset-normalizer==3.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
decorator==4.4.2 ; python_version >= "3.8" and python_version < "4.0"
|
decorator==4.4.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
distro==1.8.0 ; python_version >= "3.8" and python_version < "4.0"
|
distro==1.8.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
idna==3.4 ; python_version >= "3.8" and python_version < "4"
|
idna==3.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
importlib-metadata==5.0.0 ; python_version >= "3.8" and python_version < "3.10"
|
importlib-metadata==6.8.0 ; python_version >= "3.8" and python_version < "3.10"
|
||||||
markdown==3.3.7 ; python_version >= "3.8" and python_version < "4.0"
|
markdown==3.3.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
orjson==3.8.0 ; python_version >= "3.8" and python_version < "4.0" and platform_machine == "x86_64"
|
orjson==3.9.2 ; python_version >= "3.8" and python_version < "4.0" and platform_machine == "x86_64"
|
||||||
protobuf==3.20.2 ; python_version >= "3.8" and python_version < "4.0"
|
protobuf==3.20.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
psutil==5.9.2 ; python_version >= "3.8" and python_version < "4.0"
|
psutil==5.9.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
pysocks==1.7.1 ; python_version >= "3.8" and python_version < "4"
|
pysocks==1.7.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
requests==2.28.1 ; python_version >= "3.8" and python_version < "4"
|
requests==2.31.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
requests[socks]==2.28.1 ; python_version >= "3.8" and python_version < "4"
|
requests[socks]==2.31.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
send2trash==1.8.0 ; python_version >= "3.8" and python_version < "4.0"
|
send2trash==1.8.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
soupsieve==2.3.2.post1 ; python_version >= "3.8" and python_version < "4.0"
|
soupsieve==2.4.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
stringcase==1.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
stringcase==1.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
urllib3==1.26.12 ; python_version >= "3.8" and python_version < "4"
|
urllib3==2.0.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
webob==1.8.7 ; python_version >= "3.8" and python_version < "4.0"
|
webob==1.8.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||||
zipp==3.9.0 ; python_version >= "3.8" and python_version < "3.10"
|
zipp==3.16.1 ; python_version >= "3.8" and python_version < "3.10"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user