From eb36cf741379244c808f90624fbd3f83f7d4b49a Mon Sep 17 00:00:00 2001 From: zevaryx Date: Thu, 23 Mar 2023 21:56:54 -0600 Subject: [PATCH 01/12] Migrate to beanie --- .vscode/settings.json | 3 + jarvis_core/config.py | 119 +++- jarvis_core/db/__init__.py | 81 +-- jarvis_core/db/models/__init__.py | 271 ++++---- jarvis_core/db/models/actions.py | 87 ++- jarvis_core/db/models/modlog.py | 46 +- jarvis_core/db/models/reddit.py | 30 +- jarvis_core/db/models/twitter.py | 40 +- jarvis_core/util/__init__.py | 32 - poetry.lock | 987 ++++++++++++++++++------------ pyproject.toml | 11 +- 11 files changed, 970 insertions(+), 737 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..de288e1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.formatting.provider": "black" +} \ No newline at end of file diff --git a/jarvis_core/config.py b/jarvis_core/config.py index 994a6bb..3826dd6 100644 --- a/jarvis_core/config.py +++ b/jarvis_core/config.py @@ -1,10 +1,14 @@ """Load global config.""" +import ast +from os import environ from pathlib import Path -from typing import Union +from typing import Any, Dict, List, Optional, Type -from yaml import load +import orjson as json +import yaml +from dotenv import load_dotenv +from pydantic import BaseModel -from jarvis_core.util import Singleton try: from yaml import CLoader as Loader @@ -12,15 +16,88 @@ except ImportError: from yaml import Loader -DEFAULT_PATH = Path("config.yaml") +DEFAULT_YAML = Path("config.yaml") +DEFAULT_JSON = Path("config.json") -class Config(Singleton): - REQUIRED = [] - OPTIONAL = {} +class Config: + REQUIRED: Dict[str, Type] = {} + OPTIONAL: Dict[str, Dict[str, Any]] = {} + + def __new__(cls, *args: list, **kwargs: dict): + """Create a new Config object.""" + + for arg, flags in cls.OPTIONAL.items(): + kwargs[arg] = kwargs.get(arg, flags["default"]) + + inst = super().__new__(cls, *args, **kwargs) + inst._validate() + + return inst + + def _validate(self) -> None: + for key in self.REQUIRED.keys(): + if getattr(self, key, None) is None: + raise ValueError(f"Missing required key: {key}") @classmethod - def from_yaml(cls, filepath: Union[Path, str] = DEFAULT_PATH) -> "Config": + def from_env(cls) -> "Config": + """Load the .env config file.""" + load_dotenv() + data = {} + for k, t in cls.REQUIRED.items(): + value = environ.get(k.upper(), None) + if value and not isinstance(value, t): + if t is dict: + try: + value = ast.literal_eval(value) + except Exception: + raise ValueError(f"{k} is a dict but is not formatted properly") + elif t is bool: + value = value.lower() in ["true", "yes", "t", "y", "1"] + else: + try: + value = t(value) + except Exception: + continue + data[k] = value + for k, flags in cls.OPTIONAL.items(): + t = flags["type"] + value = environ.get(k.upper(), flags["default"]) + if value and not isinstance(value, t): + if t is dict: + try: + value = ast.literal_eval(value) + except Exception: + raise ValueError(f"{k} is a dict but is not formatted properly") + elif t is bool: + value = value.lower() in ["true", "yes", "t", "y", "1"] + else: + try: + value = t(value) + except Exception: + continue + data[k] = value + + return cls(**data) + + @classmethod + def from_json(cls, filepath: Path | str = DEFAULT_JSON) -> "Config": + """Load the json config file.""" + if inst := cls.__dict__.get("inst"): + return inst + + if isinstance(filepath, str): + filepath = Path(filepath) + + with filepath.open() as f: + raw = f.read() + + j = json.loads(raw) + return cls(**j) + + @classmethod + def from_yaml(cls, filepath: Path | str = DEFAULT_YAML) -> "Config": """Load the yaml config file.""" if inst := cls.__dict__.get("inst"): return inst @@ -31,9 +108,33 @@ class Config(Singleton): with filepath.open() as f: raw = f.read() - y = load(raw, Loader=Loader) + y = yaml.load(raw, Loader=Loader) return cls(**y) + @classmethod + def load(cls, method: Optional[str] = None) -> "Config": + """ + Load the config in a somewhat generic way. + + Default load order is: yaml, json, env + + Args: + method: Load method, one of: yaml, json, env + """ + methods = ["yaml", "json", "env"] + if method and method in methods: + methods.remove(method) + methods.insert(0, method) + for method in methods: + try: + m = cls.__dict__.get(f"from_{method}", None) + if m: + return m() + except Exception: + continue + + raise ValueError("Unable to load configuration, please create one of: config.yaml, config.json, .env") + @classmethod def reload(cls) -> bool: """Reload the config.""" diff --git a/jarvis_core/db/__init__.py b/jarvis_core/db/__init__.py index 5a1e219..b9eb8cd 100644 --- a/jarvis_core/db/__init__.py +++ b/jarvis_core/db/__init__.py @@ -1,20 +1,13 @@ """JARVIS database models and utilities.""" -from bson import ObjectId from motor.motor_asyncio import AsyncIOMotorClient from pytz import utc -from umongo.frameworks import MotorAsyncIOInstance +from beanie import init_beanie -from jarvis_core.util import find - -CLIENT = None -JARVISDB = None -CTC2DB = None -JARVIS_INST = MotorAsyncIOInstance() -CTC2_INST = MotorAsyncIOInstance() +from jarvis_core.db.models import all_models -def connect( - host: str, username: str, password: str, port: int = 27017, testing: bool = False +async def connect( + host: str, username: str, password: str, port: int = 27017, testing: bool = False, extra_models: list = [] ) -> None: """ Connect to MongoDB. @@ -24,66 +17,10 @@ def connect( username: Username password: Password port: Port + testing: Whether or not to use jarvis_dev + extra_models: Extra beanie models to register """ global CLIENT, JARVISDB, CTC2DB, JARVIS_INST, CTC2_INST - CLIENT = AsyncIOMotorClient( - host=host, username=username, password=password, port=port, tz_aware=True, tzinfo=utc - ) - JARVISDB = CLIENT.narvis if testing else CLIENT.jarvis - CTC2DB = CLIENT.ctc2 - - JARVIS_INST.set_db(JARVISDB) - CTC2_INST.set_db(CTC2DB) - - -QUERY_OPS = ["ne", "lt", "lte", "gt", "gte", "not", "in", "nin", "mod", "all", "size"] -STRING_OPS = [ - "exact", - "iexact", - "contains", - "icontains", - "startswith", - "istartswith", - "endswith", - "iendswith", - "wholeword", - "iwholeword", - "regex", - "iregex" "match", -] -GEO_OPS = [ - "get_within", - "geo_within_box", - "geo_within_polygon", - "geo_within_center", - "geo_within_sphere", - "geo_intersects", - "near", - "within_distance", - "within_spherical_distance", - "near_sphere", - "within_box", - "within_polygon", - "max_distance", - "min_distance", -] - -ALL_OPS = QUERY_OPS + STRING_OPS + GEO_OPS - - -def q(**kwargs: dict) -> dict: - """uMongo query wrapper.""" # noqa: D403 - query = {} - for key, value in kwargs.items(): - if key == "_id": - value = ObjectId(value) - elif "__" in key: - args = key.split("__") - if not any(x in ALL_OPS for x in args): - key = ".".join(args) - else: - idx = args.index(find(lambda x: x in ALL_OPS, args)) - key = ".".join(args[:idx]) - value = {f"${args[idx]}": value} - query[key] = value - return query + client = AsyncIOMotorClient(host=host, username=username, password=password, port=port, tz_aware=True, tzinfo=utc) + db = client.jarvis_dev if testing else client.jarvis + await init_beanie(database=db, document_models=all_models + extra_models) diff --git a/jarvis_core/db/models/__init__.py b/jarvis_core/db/models/__init__.py index 1f88675..24435a6 100644 --- a/jarvis_core/db/models/__init__.py +++ b/jarvis_core/db/models/__init__.py @@ -1,205 +1,248 @@ """JARVIS database models.""" from datetime import datetime, timezone -from typing import Any, List +from functools import partial -import marshmallow as ma -from umongo import Document, EmbeddedDocument, fields +from beanie import Document, Link +from pydantic import BaseModel, Field -from jarvis_core.db import CTC2_INST, JARVIS_INST from jarvis_core.db.models.actions import Ban, Kick, Mute, Unban, Warning from jarvis_core.db.models.modlog import Action, Modlog, Note from jarvis_core.db.models.reddit import Subreddit, SubredditFollow from jarvis_core.db.models.twitter import TwitterAccount, TwitterFollow +__all__ = [ + "Action", + "Autopurge", + "Autoreact", + "Ban", + "Config", + "Guess", + "Kick", + "Lock", + "Lockdown", + "Modlog", + "Mute", + "Note", + "Pin", + "Pinboard", + "Purge", + "Reminder", + "Rolegiver", + "Roleping", + "Setting", + "Subreddit", + "SubredditFollow", + "Temprole", + "TwitterAccount", + "TwitterFollow", + "Unban", + "UserSetting", + "Warning", + "all_models", +] + def get_now() -> datetime: """Get proper timestamp.""" return datetime.now(tz=timezone.utc) -class RawField(fields.BaseField, ma.fields.Raw): - pass +NowField = partial(Field, default_factory=get_now) -@JARVIS_INST.register class Autopurge(Document): - guild: int = fields.IntegerField(required=True) - channel: int = fields.IntegerField(required=True) - delay: int = fields.IntegerField(default=30) - admin: int = fields.IntegerField(required=True) - created_at: datetime = fields.DateTimeField(default=datetime.now) + guild: int + channel: int + delay: int = 30 + admin: int + created_at: datetime = NowField() -@JARVIS_INST.register class Autoreact(Document): - guild: int = fields.IntegerField(required=True) - channel: int = fields.IntegerField(required=True) - reactions: List[str] = fields.ListField(fields.StringField()) - admin: int = fields.IntegerField(required=True) - thread: bool = fields.BooleanField(default=True) - created_at: datetime = fields.DateTimeField(default=datetime.now) + guild: int + channel: int + reactions: list[str] = Field(default_factory=list) + admin: int + thread: bool + created_at: datetime = NowField() -@JARVIS_INST.register class Config(Document): """Config database object.""" - key: str = fields.StringField(required=True) - value: Any = RawField(required=True) + key: str + value: str | int | bool -@CTC2_INST.register class Guess(Document): """Guess database object.""" - correct: bool = fields.BooleanField(default=False) - guess: str = fields.StringField(required=True) - user: int = fields.IntegerField(required=True) + correct: bool + guess: str + user: int -@JARVIS_INST.register -class Permission(EmbeddedDocument): +class Permission(BaseModel): """Embedded Permissions document.""" - id: int = fields.IntegerField(required=True) - allow: int = fields.IntegerField(default=0) - deny: int = fields.IntegerField(default=0) + id: int + allow: int = 0 + deny: int = 0 -@JARVIS_INST.register class Lock(Document): """Lock database object.""" - active: bool = fields.BooleanField(default=True) - admin: int = fields.IntegerField(required=True) - channel: int = fields.IntegerField(required=True) - duration: int = fields.IntegerField(default=10) - guild: int = fields.IntegerField(required=True) - reason: str = fields.StringField(required=True) - original_perms: Permission = fields.EmbeddedField(Permission, required=False) - created_at: datetime = fields.DateTimeField(default=get_now) + active: bool = True + admin: int + channel: int + duration: int = 10 + reason: str + original_perms: Permission + created_at: datetime = NowField() -@JARVIS_INST.register class Lockdown(Document): """Lockdown database object.""" - active: bool = fields.BooleanField(default=True) - admin: int = fields.IntegerField(required=True) - duration: int = fields.IntegerField(default=10) - guild: int = fields.IntegerField(required=True) - reason: str = fields.StringField(required=True) - original_perms: int = fields.IntegerField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + active: bool = True + admin: int + duration: int = 10 + guild: int + reason: str + original_perms: int + created_at: datetime = NowField() -@JARVIS_INST.register class Purge(Document): """Purge database object.""" - admin: int = fields.IntegerField(required=True) - channel: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - count: int = fields.IntegerField(default=10) - created_at: datetime = fields.DateTimeField(default=get_now) + admin: int + channel: int + guild: int + count: int = 10 + created_at: datetime = NowField() -@JARVIS_INST.register class Reminder(Document): """Reminder database object.""" - active: bool = fields.BooleanField(default=True) - user: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - channel: int = fields.IntegerField(required=True) - message: str = fields.StringField(required=True) - remind_at: datetime = fields.DateTimeField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) - private: bool = fields.BooleanField(default=False) + active: bool = True + user: int + guild: int + channel: int + message: str + remind_at: datetime + created_at: datetime = NowField() + private: bool = False -@JARVIS_INST.register class Rolegiver(Document): """Rolegiver database object.""" - guild: int = fields.IntegerField(required=True) - roles: List[int] = fields.ListField(fields.IntegerField()) + guild: int + roles: list[int] -@JARVIS_INST.register -class Bypass(EmbeddedDocument): +class Bypass(BaseModel): """Roleping bypass embedded object.""" - users: List[int] = fields.ListField(fields.IntegerField()) - roles: List[int] = fields.ListField(fields.IntegerField()) + users: list[int] + roles: list[int] -@JARVIS_INST.register class Roleping(Document): """Roleping database object.""" - active: bool = fields.BooleanField(default=True) - role: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - admin: int = fields.IntegerField(required=True) - bypass: Bypass = fields.EmbeddedField(Bypass) - created_at: datetime = fields.DateTimeField(default=get_now) + active: bool = True + role: int + guild: int + admin: int + bypass: Bypass + created_at: datetime = NowField() -@JARVIS_INST.register class Setting(Document): """Setting database object.""" - guild: int = fields.IntegerField(required=True) - setting: str = fields.StringField(required=True) - value: Any = RawField() + guild: int + setting: str + value: str | int | bool -@JARVIS_INST.register -class Star(Document): - """Star database object.""" +class Pinboard(Document): + """Pinboard database object.""" - active: bool = fields.BooleanField(default=True) - index: int = fields.IntegerField(required=True) - message: int = fields.IntegerField(required=True) - channel: int = fields.IntegerField(required=True) - starboard: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - admin: int = fields.IntegerField(required=True) - star: int = fields.IntegerField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + channel: int + guild: int + admin: int + created_at: datetime = NowField() -@JARVIS_INST.register -class Starboard(Document): - """Starboard database object.""" +class Pin(Document): + """Pin database object.""" - channel: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - admin: int = fields.IntegerField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + active: bool = True + index: int + message: int + channel: int + pinboard: Link[Pinboard] + guild: int + admin: int + star: int + created_at: datetime = NowField() -@JARVIS_INST.register class Temprole(Document): """Temporary role object.""" - guild: int = fields.IntegerField(required=True) - user: int = fields.IntegerField(required=True) - role: int = fields.IntegerField(required=True) - admin: int = fields.IntegerField(required=True) - expires_at: datetime = fields.DateTimeField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + guild: int + user: int + role: int + admin: int + expires_at: datetime + reapply_on_rejoin: bool = True + created_at: datetime = NowField() -@JARVIS_INST.register class UserSetting(Document): """User Setting object.""" - user: int = fields.IntegerField(required=True) - type: str = fields.StringField(required=True) - setting: str = fields.StringField(required=True) - value: Any = RawField() + user: int + type: str + settings: str + value: str | int | bool - class Meta: - collection_name = "usersetting" + class Setting: + name = "usersetting" + + +all_models = [ + Action, + Autopurge, + Autoreact, + Ban, + Config, + Guess, + Kick, + Lock, + Lockdown, + Modlog, + Mute, + Note, + Pin, + Pinboard, + Purge, + Reminder, + Rolegiver, + Roleping, + Setting, + Subreddit, + SubredditFollow, + Temprole, + TwitterAccount, + TwitterFollow, + Unban, + UserSetting, + Warning, +] diff --git a/jarvis_core/db/models/actions.py b/jarvis_core/db/models/actions.py index 742eb0f..36f05c9 100644 --- a/jarvis_core/db/models/actions.py +++ b/jarvis_core/db/models/actions.py @@ -1,9 +1,9 @@ """User action models.""" from datetime import datetime, timezone +from functools import partial +from typing import Optional -from umongo import Document, fields - -from jarvis_core.db import JARVIS_INST +from beanie import Document, Field def get_now() -> datetime: @@ -11,66 +11,63 @@ def get_now() -> datetime: return datetime.now(tz=timezone.utc) -@JARVIS_INST.register +NowField = partial(Field, default_factory=get_now) + + class Ban(Document): - active: bool = fields.BooleanField(default=True) - admin: int = fields.IntegerField(required=True) - user: int = fields.IntegerField(required=True) - username: str = fields.StringField(required=True) - discrim: int = fields.IntegerField(required=True) - duration: int = fields.IntegerField(required=False, default=None) - guild: int = fields.IntegerField(required=True) - type: str = fields.StringField(default="perm") - reason: str = fields.StringField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + active: bool = True + admin: int + user: int + username: str + discrim: int + duration: Optional[int] + guild: int + type: str = "perm" + reason: str + created_at: datetime = NowField() -@JARVIS_INST.register class Kick(Document): """Kick database object.""" - admin: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - reason: str = fields.StringField(required=True) - user: int = fields.IntegerField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + admin: int + guild: int + reason: str + user: int + created_at: datetime = NowField() -@JARVIS_INST.register class Mute(Document): """Mute database object.""" - active: bool = fields.BooleanField(default=True) - user: int = fields.IntegerField(required=True) - admin: int = fields.IntegerField(required=True) - duration: int = fields.IntegerField(default=10) - guild: int = fields.IntegerField(required=True) - reason: str = fields.StringField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + active: bool = True + user: int + admin: int + duration: int = 10 + guild: int + reason: str + created_at: datetime = NowField() -@JARVIS_INST.register class Unban(Document): """Unban database object.""" - user: int = fields.IntegerField(required=True) - username: str = fields.StringField(required=True) - discrim: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - admin: int = fields.IntegerField(required=True) - reason: str = fields.StringField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + user: int + username: str + discrim: str + guild: int + reason: str + created_at: datetime = NowField() -@JARVIS_INST.register class Warning(Document): """Warning database object.""" - active: bool = fields.BooleanField(default=True) - admin: int = fields.IntegerField(required=True) - user: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - duration: int = fields.IntegerField(default=24) - reason: str = fields.StringField(required=True) - expires_at: datetime = fields.DateTimeField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + active: bool = True + admin: int + user: int + guild: int + duration: int = 24 + reason: str + expires_at: datetime + created_at: datetime = NowField() diff --git a/jarvis_core/db/models/modlog.py b/jarvis_core/db/models/modlog.py index 6c251be..6b53df3 100644 --- a/jarvis_core/db/models/modlog.py +++ b/jarvis_core/db/models/modlog.py @@ -1,12 +1,11 @@ """Modlog database models.""" from datetime import datetime, timezone -from typing import List +from functools import partial import nanoid from bson import ObjectId -from umongo import Document, EmbeddedDocument, fields - -from jarvis_core.db import JARVIS_INST +from beanie import Document +from pydantic import BaseModel, Field NANOID_ALPHA = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" @@ -21,33 +20,34 @@ def get_id() -> str: return nanoid.generate(NANOID_ALPHA, 12) -@JARVIS_INST.register -class Action(EmbeddedDocument): +NanoField = partial(Field, default_factory=get_id) +NowField = partial(Field, default_factory=get_now) + + +class Action(BaseModel): """Modlog embedded action document.""" - action_type: str = fields.StringField(required=True) - parent: ObjectId = fields.ObjectIdField(required=True) - orphaned: bool = fields.BoolField(default=False) + action_type: str + parent: ObjectId + orphaned: bool = False -@JARVIS_INST.register -class Note(EmbeddedDocument): +class Note(BaseModel): """Modlog embedded note document.""" - admin: int = fields.IntegerField(required=True) - content: str = fields.StrField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + admin: int + content: str + created_at: datetime = NowField() -@JARVIS_INST.register class Modlog(Document): """Modlog database object.""" - user: int = fields.IntegerField(required=True) - nanoid: str = fields.StringField(default=get_id) - guild: int = fields.IntegerField(required=True) - admin: int = fields.IntegerField(required=True) - actions: List[Action] = fields.ListField(fields.EmbeddedField(Action), factory=list) - open: bool = fields.BoolField(default=True) - created_at: datetime = fields.DateTimeField(default=get_now) - notes: List[Note] = fields.ListField(fields.EmbeddedField(Note), factory=list) + user: int + nanoid: str = NanoField() + guild: int + admin: int + actions: list[Action] = Field(default_factory=list) + notes: list[Note] = Field(default_factory=list) + open: bool = True + created_at: datetime = NowField diff --git a/jarvis_core/db/models/reddit.py b/jarvis_core/db/models/reddit.py index 51e9375..c30d3d7 100644 --- a/jarvis_core/db/models/reddit.py +++ b/jarvis_core/db/models/reddit.py @@ -1,9 +1,8 @@ """Reddit databaes models.""" from datetime import datetime, timezone +from functools import partial -from umongo import Document, fields - -from jarvis_core.db import JARVIS_INST +from beanie import Document, Field def get_now() -> datetime: @@ -11,24 +10,25 @@ def get_now() -> datetime: return datetime.now(tz=timezone.utc) -@JARVIS_INST.register +NowField = partial(Field, default_factory=get_now) + + class Subreddit(Document): """Subreddit object.""" - display_name: str = fields.StringField(required=True) - over18: bool = fields.BooleanField(default=False) + display_name: str + over18: bool = False -@JARVIS_INST.register class SubredditFollow(Document): """Subreddit Follow object.""" - active: bool = fields.BooleanField(default=True) - display_name: str = fields.StringField(required=True) - channel: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - admin: int = fields.IntegerField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + active: bool = True + display_name: str + channel: int + guild: int + admin: int + created_at: datetime = NowField() - class Meta: - collection_name = "subredditfollow" + class Setting: + name = "subredditfollow" diff --git a/jarvis_core/db/models/twitter.py b/jarvis_core/db/models/twitter.py index fa22c20..e13dd8a 100644 --- a/jarvis_core/db/models/twitter.py +++ b/jarvis_core/db/models/twitter.py @@ -1,9 +1,8 @@ """Twitter database models.""" from datetime import datetime, timezone +from functools import partial -from umongo import Document, fields - -from jarvis_core.db import JARVIS_INST +from beanie import Document, Field def get_now() -> datetime: @@ -11,30 +10,31 @@ def get_now() -> datetime: return datetime.now(tz=timezone.utc) -@JARVIS_INST.register +NowField = partial(Field, default_factory=get_now) + + class TwitterAccount(Document): """Twitter Account object.""" - handle: str = fields.StringField(required=True) - twitter_id: int = fields.IntegerField(required=True) - last_tweet: int = fields.IntegerField(required=True) - last_sync: datetime = fields.DateTimeField(default=get_now) + handle: str + twitter_id: int + last_tweet: int + last_sync: datetime = NowField() - class Meta: - collection_name = "twitteraccount" + class Setting: + name = "twitteraccount" -@JARVIS_INST.register class TwitterFollow(Document): """Twitter Follow object.""" - active: bool = fields.BooleanField(default=True) - twitter_id: int = fields.IntegerField(required=True) - channel: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - retweets: bool = fields.BooleanField(default=True) - admin: int = fields.IntegerField(required=True) - created_at: datetime = fields.DateTimeField(default=get_now) + active: bool = True + twitter_id: int + channel: int + guild: int + retweets: bool = True + admin: int + created_at: datetime = NowField() - class Meta: - collection_name = "twitterfollow" + class Setting: + name = "twitterfollow" diff --git a/jarvis_core/util/__init__.py b/jarvis_core/util/__init__.py index d6dddc3..79c7b1e 100644 --- a/jarvis_core/util/__init__.py +++ b/jarvis_core/util/__init__.py @@ -9,38 +9,6 @@ from jarvis_core.filters import url DEFAULT_BLOCKSIZE = 8 * 1024 * 1024 -class Singleton(object): - REQUIRED = [] - OPTIONAL = {} - - def __new__(cls, *args: list, **kwargs: dict): - """Create a new singleton.""" - inst = cls.__dict__.get("inst") - if inst is not None: - return inst - - inst = object.__new__(cls) - inst.init(*args, **kwargs) - inst._validate() - cls.__inst__ = inst - - return inst - - def _validate(self) -> None: - for key in self.REQUIRED: - if not getattr(self, key, None): - raise ValueError(f"Missing required key: {key}") - - def init(self, **kwargs: dict) -> None: - """Initialize the object.""" - for key, value in kwargs.items(): - setattr(self, key, value) - - for key, value in self.OPTIONAL.items(): - if not getattr(self, key, None): - setattr(self, key, value) - - async def hash( data: str, method: Union[Callable, str] = hashlib.sha256, size: int = DEFAULT_BLOCKSIZE ) -> Tuple[str, int, str]: diff --git a/poetry.lock b/poetry.lock index a014e2c..c77ca43 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. + [[package]] name = "aiohttp" version = "3.8.1" @@ -5,332 +7,7 @@ description = "Async http client/server framework (asyncio)" category = "main" optional = false python-versions = ">=3.6" - -[package.dependencies] -aiosignal = ">=1.1.2" -async-timeout = ">=4.0.0a3,<5.0" -attrs = ">=17.3.0" -charset-normalizer = ">=2.0,<3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["aiodns", "brotli", "cchardet"] - -[[package]] -name = "aiosignal" -version = "1.2.0" -description = "aiosignal: a list of registered asynchronous callbacks" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -frozenlist = ">=1.1.0" - -[[package]] -name = "async-timeout" -version = "4.0.2" -description = "Timeout context manager for asyncio programs" -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "attrs" -version = "21.4.0" -description = "Classes Without Boilerplate" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] - -[[package]] -name = "charset-normalizer" -version = "2.0.12" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.5.0" - -[package.extras] -unicode_backport = ["unicodedata2"] - -[[package]] -name = "colorama" -version = "0.4.4" -description = "Cross-platform colored terminal text." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "commonmark" -version = "0.9.1" -description = "Python parser for the CommonMark Markdown spec" -category = "main" -optional = false -python-versions = "*" - -[package.extras] -test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] - -[[package]] -name = "frozenlist" -version = "1.3.0" -description = "A list-like structure which implements collections.abc.MutableSequence" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "idna" -version = "3.3" -description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "marshmallow" -version = "3.15.0" -description = "A lightweight library for converting complex datatypes to and from native Python datatypes." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -packaging = "*" - -[package.extras] -dev = ["pytest", "pytz", "simplejson", "mypy (==0.940)", "flake8 (==4.0.1)", "flake8-bugbear (==22.1.11)", "pre-commit (>=2.4,<3.0)", "tox"] -docs = ["sphinx (==4.4.0)", "sphinx-issues (==3.0.1)", "alabaster (==0.7.12)", "sphinx-version-warning (==1.1.2)", "autodocsumm (==0.2.7)"] -lint = ["mypy (==0.940)", "flake8 (==4.0.1)", "flake8-bugbear (==22.1.11)", "pre-commit (>=2.4,<3.0)"] -tests = ["pytest", "pytz", "simplejson"] - -[[package]] -name = "motor" -version = "2.5.1" -description = "Non-blocking MongoDB driver for Tornado or asyncio" -category = "main" -optional = false -python-versions = ">=3.5.2" - -[package.dependencies] -pymongo = ">=3.12,<4" - -[package.extras] -encryption = ["pymongo[encryption] (>=3.12,<4)"] - -[[package]] -name = "multidict" -version = "6.0.2" -description = "multidict implementation" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "nanoid" -version = "2.0.0" -description = "A tiny, secure, URL-friendly, unique string ID generator for Python" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "orjson" -version = "3.6.8" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "packaging" -version = "21.3" -description = "Core utilities for Python packages" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" - -[[package]] -name = "pluggy" -version = "0.13.1" -description = "plugin and hook calling mechanisms for python" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.extras] -dev = ["pre-commit", "tox"] - -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "pygments" -version = "2.12.0" -description = "Pygments is a syntax highlighting package written in Python." -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "pymongo" -version = "3.12.3" -description = "Python driver for MongoDB " -category = "main" -optional = false -python-versions = "*" - -[package.extras] -aws = ["pymongo-auth-aws (<2.0.0)"] -encryption = ["pymongocrypt (>=1.1.0,<2.0.0)"] -gssapi = ["pykerberos"] -ocsp = ["pyopenssl (>=17.2.0)", "requests (<3.0.0)", "service-identity (>=18.1.0)", "certifi"] -snappy = ["python-snappy"] -srv = ["dnspython (>=1.16.0,<1.17.0)"] -tls = ["ipaddress"] -zstd = ["zstandard"] - -[[package]] -name = "pyparsing" -version = "3.0.8" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "main" -optional = false -python-versions = ">=3.6.8" - -[package.extras] -diagrams = ["railroad-diagrams", "jinja2"] - -[[package]] -name = "pytest" -version = "7.1.2" -description = "pytest: simple powerful testing with Python" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" - -[package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] - -[[package]] -name = "pytz" -version = "2022.1" -description = "World timezone definitions, modern and historical" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "pyyaml" -version = "6.0" -description = "YAML parser and emitter for Python" -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "rich" -version = "12.3.0" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -category = "main" -optional = false -python-versions = ">=3.6.3,<4.0.0" - -[package.dependencies] -commonmark = ">=0.9.0,<0.10.0" -pygments = ">=2.6.0,<3.0.0" - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "umongo" -version = "3.1.0" -description = "sync/async MongoDB ODM, yes." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -marshmallow = ">=3.10.0" -pymongo = ">=3.7.0" - -[package.extras] -mongomock = ["mongomock"] -motor = ["motor (>=2.0,<3.0)"] -txmongo = ["txmongo (>=19.2.0)"] - -[[package]] -name = "yarl" -version = "1.7.2" -description = "Yet another URL library" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" - -[metadata] -lock-version = "1.1" -python-versions = "^3.10" -content-hash = "4581dae71400051e27a4fedf8d3f91303102ab0e25e4b4392fa047f865419f3a" - -[metadata.files] -aiohttp = [ +files = [ {file = "aiohttp-3.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1ed0b6477896559f17b9eaeb6d38e07f7f9ffe40b9f0f9627ae8b9926ae260a8"}, {file = "aiohttp-3.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7dadf3c307b31e0e61689cbf9e06be7a867c563d5a63ce9dca578f956609abf8"}, {file = "aiohttp-3.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a79004bb58748f31ae1cbe9fa891054baaa46fb106c2dc7af9f8e3304dc30316"}, @@ -404,35 +81,209 @@ aiohttp = [ {file = "aiohttp-3.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:1c182cb873bc91b411e184dab7a2b664d4fea2743df0e4d57402f7f3fa644bac"}, {file = "aiohttp-3.8.1.tar.gz", hash = "sha256:fc5471e1a54de15ef71c1bc6ebe80d4dc681ea600e68bfd1cbce40427f0b7578"}, ] -aiosignal = [ + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = ">=4.0.0a3,<5.0" +attrs = ">=17.3.0" +charset-normalizer = ">=2.0,<3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "cchardet"] + +[[package]] +name = "aiosignal" +version = "1.2.0" +description = "aiosignal: a list of registered asynchronous callbacks" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ {file = "aiosignal-1.2.0-py3-none-any.whl", hash = "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a"}, {file = "aiosignal-1.2.0.tar.gz", hash = "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2"}, ] -async-timeout = [ + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "async-timeout" +version = "4.0.2" +description = "Timeout context manager for asyncio programs" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, ] -atomicwrites = [ + +[[package]] +name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] -attrs = [ + +[[package]] +name = "attrs" +version = "21.4.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, ] -charset-normalizer = [ - {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, - {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, + +[package.extras] +dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"] +docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] +tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"] +tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"] + +[[package]] +name = "beanie" +version = "1.17.0" +description = "Asynchronous Python ODM for MongoDB" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "beanie-1.17.0-py3-none-any.whl", hash = "sha256:a0711775051c72324fc4555120355da9a3c081d41db14ddaa8e9f368303436ef"}, + {file = "beanie-1.17.0.tar.gz", hash = "sha256:5f758785ce813838a0f25e171957afb6e70fa142dda937531427e0a530d03c64"}, ] -colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, + +[package.dependencies] +click = ">=7" +lazy-model = ">=0.0.3" +motor = ">=2.5,<4.0" +pydantic = ">=1.10.0" +toml = "*" + +[[package]] +name = "black" +version = "23.1.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "black-23.1.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:b6a92a41ee34b883b359998f0c8e6eb8e99803aa8bf3123bf2b2e6fec505a221"}, + {file = "black-23.1.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:57c18c5165c1dbe291d5306e53fb3988122890e57bd9b3dcb75f967f13411a26"}, + {file = "black-23.1.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:9880d7d419bb7e709b37e28deb5e68a49227713b623c72b2b931028ea65f619b"}, + {file = "black-23.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6663f91b6feca5d06f2ccd49a10f254f9298cc1f7f49c46e498a0771b507104"}, + {file = "black-23.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:9afd3f493666a0cd8f8df9a0200c6359ac53940cbde049dcb1a7eb6ee2dd7074"}, + {file = "black-23.1.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:bfffba28dc52a58f04492181392ee380e95262af14ee01d4bc7bb1b1c6ca8d27"}, + {file = "black-23.1.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c1c476bc7b7d021321e7d93dc2cbd78ce103b84d5a4cf97ed535fbc0d6660648"}, + {file = "black-23.1.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:382998821f58e5c8238d3166c492139573325287820963d2f7de4d518bd76958"}, + {file = "black-23.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bf649fda611c8550ca9d7592b69f0637218c2369b7744694c5e4902873b2f3a"}, + {file = "black-23.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:121ca7f10b4a01fd99951234abdbd97728e1240be89fde18480ffac16503d481"}, + {file = "black-23.1.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:a8471939da5e824b891b25751955be52ee7f8a30a916d570a5ba8e0f2eb2ecad"}, + {file = "black-23.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8178318cb74f98bc571eef19068f6ab5613b3e59d4f47771582f04e175570ed8"}, + {file = "black-23.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a436e7881d33acaf2536c46a454bb964a50eff59b21b51c6ccf5a40601fbef24"}, + {file = "black-23.1.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:a59db0a2094d2259c554676403fa2fac3473ccf1354c1c63eccf7ae65aac8ab6"}, + {file = "black-23.1.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:0052dba51dec07ed029ed61b18183942043e00008ec65d5028814afaab9a22fd"}, + {file = "black-23.1.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:49f7b39e30f326a34b5c9a4213213a6b221d7ae9d58ec70df1c4a307cf2a1580"}, + {file = "black-23.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:162e37d49e93bd6eb6f1afc3e17a3d23a823042530c37c3c42eeeaf026f38468"}, + {file = "black-23.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b70eb40a78dfac24842458476135f9b99ab952dd3f2dab738c1881a9b38b753"}, + {file = "black-23.1.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:a29650759a6a0944e7cca036674655c2f0f63806ddecc45ed40b7b8aa314b651"}, + {file = "black-23.1.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:bb460c8561c8c1bec7824ecbc3ce085eb50005883a6203dcfb0122e95797ee06"}, + {file = "black-23.1.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c91dfc2c2a4e50df0026f88d2215e166616e0c80e86004d0003ece0488db2739"}, + {file = "black-23.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a951cc83ab535d248c89f300eccbd625e80ab880fbcfb5ac8afb5f01a258ac9"}, + {file = "black-23.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:0680d4380db3719ebcfb2613f34e86c8e6d15ffeabcf8ec59355c5e7b85bb555"}, + {file = "black-23.1.0-py3-none-any.whl", hash = "sha256:7a0f701d314cfa0896b9001df70a530eb2472babb76086344e688829efd97d32"}, + {file = "black-23.1.0.tar.gz", hash = "sha256:b0bd97bea8903f5a2ba7219257a44e3f1f9d00073d6cc1add68f0beec69692ac"}, ] -commonmark = [ + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "charset-normalizer" +version = "2.1.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "charset-normalizer-2.1.0.tar.gz", hash = "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413"}, + {file = "charset_normalizer-2.1.0-py3-none-any.whl", hash = "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5"}, +] + +[package.extras] +unicode-backport = ["unicodedata2"] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.5" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, +] + +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +category = "main" +optional = false +python-versions = "*" +files = [ {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, ] -frozenlist = [ + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + +[[package]] +name = "frozenlist" +version = "1.3.0" +description = "A list-like structure which implements collections.abc.MutableSequence" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ {file = "frozenlist-1.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2257aaba9660f78c7b1d8fea963b68f3feffb1a9d5d05a18401ca9eb3e8d0a3"}, {file = "frozenlist-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4a44ebbf601d7bac77976d429e9bdb5a4614f9f4027777f9e54fd765196e9d3b"}, {file = "frozenlist-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:45334234ec30fc4ea677f43171b18a27505bfb2dba9aca4398a62692c0ea8868"}, @@ -493,23 +344,72 @@ frozenlist = [ {file = "frozenlist-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:772965f773757a6026dea111a15e6e2678fbd6216180f82a48a40b27de1ee2ab"}, {file = "frozenlist-1.3.0.tar.gz", hash = "sha256:ce6f2ba0edb7b0c1d8976565298ad2deba6f8064d2bebb6ffce2ca896eb35b0b"}, ] -idna = [ + +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] -iniconfig = [ + +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = "*" +files = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] -marshmallow = [ - {file = "marshmallow-3.15.0-py3-none-any.whl", hash = "sha256:ff79885ed43b579782f48c251d262e062bce49c65c52412458769a4fb57ac30f"}, - {file = "marshmallow-3.15.0.tar.gz", hash = "sha256:2aaaab4f01ef4f5a011a21319af9fce17ab13bf28a026d1252adab0e035648d5"}, + +[[package]] +name = "lazy-model" +version = "0.0.5" +description = "" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "lazy-model-0.0.5.tar.gz", hash = "sha256:2d98f9dfe275012477555a439dceb56364793a0f266758d1a33267d68e8fbc76"}, + {file = "lazy_model-0.0.5-py3-none-any.whl", hash = "sha256:8b4fc5eac99029f84b11b21e81a6894911a475f25e53227b7e44833e62e26553"}, ] -motor = [ + +[package.dependencies] +pydantic = ">=1.9.0" + +[[package]] +name = "motor" +version = "2.5.1" +description = "Non-blocking MongoDB driver for Tornado or asyncio" +category = "main" +optional = false +python-versions = ">=3.5.2" +files = [ {file = "motor-2.5.1-py3-none-any.whl", hash = "sha256:961fdceacaae2c7236c939166f66415be81be8bbb762da528386738de3a0f509"}, {file = "motor-2.5.1.tar.gz", hash = "sha256:663473f4498f955d35db7b6f25651cb165514c247136f368b84419cb7635f6b8"}, ] -multidict = [ + +[package.dependencies] +pymongo = ">=3.12,<4" + +[package.extras] +encryption = ["pymongo[encryption] (>=3.12,<4)"] + +[[package]] +name = "multidict" +version = "6.0.2" +description = "multidict implementation" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"}, {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3"}, {file = "multidict-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c"}, @@ -570,61 +470,215 @@ multidict = [ {file = "multidict-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae"}, {file = "multidict-6.0.2.tar.gz", hash = "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013"}, ] -nanoid = [ + +[[package]] +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 = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "nanoid" +version = "2.0.0" +description = "A tiny, secure, URL-friendly, unique string ID generator for Python" +category = "main" +optional = false +python-versions = "*" +files = [ {file = "nanoid-2.0.0-py3-none-any.whl", hash = "sha256:90aefa650e328cffb0893bbd4c236cfd44c48bc1f2d0b525ecc53c3187b653bb"}, {file = "nanoid-2.0.0.tar.gz", hash = "sha256:5a80cad5e9c6e9ae3a41fa2fb34ae189f7cb420b2a5d8f82bd9d23466e4efa68"}, ] -orjson = [ - {file = "orjson-3.6.8-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:3a287a650458de2211db03681b71c3e5cb2212b62f17a39df8ad99fc54855d0f"}, - {file = "orjson-3.6.8-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5204e25c12cea58e524fc82f7c27ed0586f592f777b33075a92ab7b3eb3687c2"}, - {file = "orjson-3.6.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77e8386393add64f959c044e0fb682364fd0e611a6f477aa13f0e6a733bd6a28"}, - {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:279f2d2af393fdf8601020744cb206b91b54ad60fb8401e0761819c7bda1f4e4"}, - {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:c31c9f389be7906f978ed4192eb58a4b74a37ad60556a0b88ddc47c576697770"}, - {file = "orjson-3.6.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0db5c5a0c5b89f092d52f6e5a3701660a9d6ffa9e2968b3ce17c2bc4f5eb0414"}, - {file = "orjson-3.6.8-cp310-none-win_amd64.whl", hash = "sha256:eb22485847b9a0c4bbedc668df860126ac931edbed1d456cf41a59f3cb961ed8"}, - {file = "orjson-3.6.8-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:1a5fe569310bc819279bd4d5f2c349910b104ed3207936246dd5d5e0b085e74a"}, - {file = "orjson-3.6.8-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ccb356a47ab1067cd3549847e9db1d279a63fe0482d315b3ffd6e7abef35ef77"}, - {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab29c069c222248ce302a25855b4e1664f9436e8ae5a131fb0859daf31676d2b"}, - {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d2b5e4cba9e774ac011071d9d27760f97f4b8cd46003e971d122e712f971345"}, - {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:c311ec504414d22834d5b972a209619925b48263856a11a14d90230f9682d49c"}, - {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:a3dfec7950b90fb8d143743503ee53fa06b32e6068bdea792fc866284da3d71d"}, - {file = "orjson-3.6.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b890dbbada2cbb26eb29bd43a848426f007f094bb0758df10dfe7a438e1cb4b4"}, - {file = "orjson-3.6.8-cp37-none-win_amd64.whl", hash = "sha256:9143ae2c52771525be9ad11a7a8cc8e7fd75391b107e7e644a9e0050496f6b4f"}, - {file = "orjson-3.6.8-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:33a82199fd42f6436f833e210ae5129c922a5c355629356ca7a8e82964da7285"}, - {file = "orjson-3.6.8-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:90159ea8b9a5a2a98fa33dc7b421cfac4d2ae91ba5e1058f5909e7f059f6b467"}, - {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:656fbe15d9ef0733e740d9def78f4fdb4153102f4836ee774a05123499005931"}, - {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7be3be6153843e0f01351b1313a5ad4723595427680dac2dfff22a37e652ce02"}, - {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:dd24f66b6697ee7424f7da575ec6cbffc8ede441114d53470949cda4d97c6e56"}, - {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:b07c780f7345ecf5901356dc21dee0669defc489c38ce7b9ab0f5e008cc0385c"}, - {file = "orjson-3.6.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ea32015a5d8a4ce00d348a0de5dc7040e0ad58f970a8fcbb5713a1eac129e493"}, - {file = "orjson-3.6.8-cp38-none-win_amd64.whl", hash = "sha256:c5a3e382194c838988ec128a26b08aa92044e5e055491cc4056142af0c1c54d7"}, - {file = "orjson-3.6.8-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:83a8424e857ae1bf53530e88b4eb2f16ca2b489073b924e655f1575cacd7f52a"}, - {file = "orjson-3.6.8-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:81e1a6a2d67f15007dadacbf9ba5d3d79237e5e33786c028557fe5a2b72f1c9a"}, - {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:137b539881c77866eba86ff6a11df910daf2eb9ab8f1acae62f879e83d7c38af"}, - {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cbd358f3b3ad539a27e36900e8e7d172d0e1b72ad9dd7d69544dcbc0f067ee7"}, - {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:6ab94701542d40b90903ecfc339333f458884979a01cb9268bc662cc67a5f6d8"}, - {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:32b6f26593a9eb606b40775826beb0dac152e3d224ea393688fced036045a821"}, - {file = "orjson-3.6.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:afd9e329ebd3418cac3cd747769b1d52daa25fa672bbf414ab59f0e0881b32b9"}, - {file = "orjson-3.6.8-cp39-none-win_amd64.whl", hash = "sha256:0c89b419914d3d1f65a1b0883f377abe42a6e44f6624ba1c63e8846cbfc2fa60"}, - {file = "orjson-3.6.8.tar.gz", hash = "sha256:e19d23741c5de13689bb316abfccea15a19c264e3ec8eb332a5319a583595ace"}, + +[[package]] +name = "orjson" +version = "3.7.2" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "orjson-3.7.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:4c6bdb0a7dfe53cca965a40371c7b8e72a0441c8bc4949c9015600f1c7fae408"}, + {file = "orjson-3.7.2-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:6e6fc60775bb0a050846710c4a110e8ad17f41e443ff9d0d05145d8f3a74b577"}, + {file = "orjson-3.7.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4b70bb1f746a9c9afb1f861a0496920b5833ff06f9d1b25b6a7d292cb7e8a06"}, + {file = "orjson-3.7.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99bb2127ee174dd6e68255db26dbef0bd6c4330377a17867ecfa314d47bfac82"}, + {file = "orjson-3.7.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:26306d988401cc34ac94dd38873b8c0384276a5ad80cdf50e266e06083284975"}, + {file = "orjson-3.7.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:34a67d810dbcec77d00d764ab730c5bbb0bee1d75a037c8d8e981506e8fba560"}, + {file = "orjson-3.7.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:14bc727f41ce0dd93d1a6a9fc06076e2401e71b00d0bf107bf64d88d2d963b77"}, + {file = "orjson-3.7.2-cp310-none-win_amd64.whl", hash = "sha256:4c686cbb73ccce02929dd799427897f0a0b2dd597d2f5b6b434917ecc3774146"}, + {file = "orjson-3.7.2-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:12eb683ddbdddd6847ca2b3b074f42574afc0fbf1aff33d8fdf3a4329167762a"}, + {file = "orjson-3.7.2-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:993550e6e451a2b71435142d4824a09f8db80d497abae23dc9f3fe62b6ca24c0"}, + {file = "orjson-3.7.2-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54cfa4d915a98209366dcf500ee5c3f66408cc9e2b4fd777c8508f69a8f519a1"}, + {file = "orjson-3.7.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f735999d49e2fff2c9812f1ea330b368349f77726894e2a06d17371e61d771bb"}, + {file = "orjson-3.7.2-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:b2b660790b0804624c569ddb8ca9d31bac6f94f880fd54b8cdff4198735a9fec"}, + {file = "orjson-3.7.2-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:590bc5f33e54eb2261de65e4026876e57d04437bab8dcade9514557e31d84537"}, + {file = "orjson-3.7.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8ac61c5c98cbcdcf7a3d0a4b62c873bbd9a996a69eaa44f8356a9e10aa29ef49"}, + {file = "orjson-3.7.2-cp37-none-win_amd64.whl", hash = "sha256:662bda15edf4d25d520945660873e730e3a6d9975041ba9c32f0ce93b632ee0d"}, + {file = "orjson-3.7.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:19eb800811a53efc7111ff7536079fb2f62da7098df0a42756ba91e7bdd01aff"}, + {file = "orjson-3.7.2-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:54a1e4e39c89d37d3dbc74dde36d09eebcde365ec6803431af9c86604bbbaf3a"}, + {file = "orjson-3.7.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fbd3b46ac514cbe29ecebcee3882383022acf84aa4d3338f26d068c6fbdf56a0"}, + {file = "orjson-3.7.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891640d332c8c7a1478ea6d13b676d239dc86451afa46000c4e8d0990a0d72dd"}, + {file = "orjson-3.7.2-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:9778a7ec4c72d6814f1e116591f351404a4df2e1dc52d282ff678781f45b509b"}, + {file = "orjson-3.7.2-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:b0b2483f8ad1f93ae4aa43bcf6a985e6ec278e931d0118bae605ffd811b614a1"}, + {file = "orjson-3.7.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2d90ca4e74750c7adfb7708deb096f835f7e6c4b892bdf703fe871565bb04ad7"}, + {file = "orjson-3.7.2-cp38-none-win_amd64.whl", hash = "sha256:b0f4e92bdfe86a0da57028e669bc1f50f48d810ef6f661e63dc6593c450314bf"}, + {file = "orjson-3.7.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:b705132b2827d33291684067cca6baa451a499b459e46761d30fcf4d6ce21a9a"}, + {file = "orjson-3.7.2-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c589d00b4fb0777f222b35925e4fa030c4777f16d1623669f44bdc191570be66"}, + {file = "orjson-3.7.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7e197e6779b230e74333e06db804ff876b27306470f68692ec70c27310e7366f"}, + {file = "orjson-3.7.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a82089ec9e1f7e9b992ff5ab98b4c3c2f98e7bbfdc6fadbef046c5aaafec2b54"}, + {file = "orjson-3.7.2-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:3ff49c219b30d715c8baae17c7c5839fe3f2c2db10a66c61d6b91bda80bf8789"}, + {file = "orjson-3.7.2-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:299a743576aaa04f5c7994010608f96df5d4a924d584a686c6e263cee732cb00"}, + {file = "orjson-3.7.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3ae3ed52c875ce1a6c607f852ca177057445289895483b0247f0dc57b481241"}, + {file = "orjson-3.7.2-cp39-none-win_amd64.whl", hash = "sha256:796914f7463277d371402775536fb461948c0d34a67d20a57dc4ec49a48a8613"}, + {file = "orjson-3.7.2.tar.gz", hash = "sha256:1cf9690a0b7c51a988221376741a31087bc1dc2ac327bb2dde919806dfa59444"}, ] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, + +[[package]] +name = "packaging" +version = "23.0" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, + {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, ] -pluggy = [ - {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, - {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, + +[[package]] +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 = [ + {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, + {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, ] -py = [ + +[[package]] +name = "platformdirs" +version = "3.1.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.1.1-py3-none-any.whl", hash = "sha256:e5986afb596e4bb5bde29a79ac9061aa955b94fca2399b7aaac4090860920dd8"}, + {file = "platformdirs-3.1.1.tar.gz", hash = "sha256:024996549ee88ec1a9aa99ff7f8fc819bb59e2c3477b410d90a16d32d6e707aa"}, +] + +[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.2.2)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] + +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] -pygments = [ + +[[package]] +name = "pydantic" +version = "1.10.7" +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"}, +] + +[package.dependencies] +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "pygments" +version = "2.12.0" +description = "Pygments is a syntax highlighting package written in Python." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ {file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"}, {file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"}, ] -pymongo = [ + +[[package]] +name = "pymongo" +version = "3.12.3" +description = "Python driver for MongoDB " +category = "main" +optional = false +python-versions = "*" +files = [ {file = "pymongo-3.12.3-cp27-cp27m-macosx_10_14_intel.whl", hash = "sha256:c164eda0be9048f83c24b9b2656900041e069ddf72de81c17d874d0c32f6079f"}, {file = "pymongo-3.12.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:a055d29f1302892a9389a382bed10a3f77708bcf3e49bfb76f7712fa5f391cc6"}, {file = "pymongo-3.12.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:8c7ad5cab282f53b9d78d51504330d1c88c83fbe187e472c07e6908a0293142e"}, @@ -636,6 +690,7 @@ pymongo = [ {file = "pymongo-3.12.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:71c0db2c313ea8a80825fb61b7826b8015874aec29ee6364ade5cb774fe4511b"}, {file = "pymongo-3.12.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b779e87300635b8075e8d5cfd4fdf7f46078cd7610c381d956bca5556bb8f97"}, {file = "pymongo-3.12.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:351a2efe1c9566c348ad0076f4bf541f4905a0ebe2d271f112f60852575f3c16"}, + {file = "pymongo-3.12.3-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:858af7c2ab98f21ed06b642578b769ecfcabe4754648b033168a91536f7beef9"}, {file = "pymongo-3.12.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0a02313e71b7c370c43056f6b16c45effbb2d29a44d24403a3d5ba6ed322fa3f"}, {file = "pymongo-3.12.3-cp310-cp310-manylinux1_i686.whl", hash = "sha256:d3082e5c4d7b388792124f5e805b469109e58f1ab1eb1fbd8b998e8ab766ffb7"}, {file = "pymongo-3.12.3-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:514e78d20d8382d5b97f32b20c83d1d0452c302c9a135f0a9022236eb9940fda"}, @@ -730,22 +785,79 @@ pymongo = [ {file = "pymongo-3.12.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0be605bfb8461384a4cb81e80f51eb5ca1b89851f2d0e69a75458c788a7263a4"}, {file = "pymongo-3.12.3-cp39-cp39-win32.whl", hash = "sha256:2157d68f85c28688e8b723bbe70c8013e0aba5570e08c48b3562f74d33fc05c4"}, {file = "pymongo-3.12.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfa217bf8cf3ff6b30c8e6a89014e0c0e7b50941af787b970060ae5ba04a4ce5"}, - {file = "pymongo-3.12.3-py2.7-macosx-10.14-intel.egg", hash = "sha256:d81299f63dc33cc172c26faf59cc54dd795fc6dd5821a7676cca112a5ee8bbd6"}, {file = "pymongo-3.12.3.tar.gz", hash = "sha256:0a89cadc0062a5e53664dde043f6c097172b8c1c5f0094490095282ff9995a5f"}, ] -pyparsing = [ - {file = "pyparsing-3.0.8-py3-none-any.whl", hash = "sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"}, - {file = "pyparsing-3.0.8.tar.gz", hash = "sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954"}, -] -pytest = [ + +[package.extras] +aws = ["pymongo-auth-aws (<2.0.0)"] +encryption = ["pymongocrypt (>=1.1.0,<2.0.0)"] +gssapi = ["pykerberos"] +ocsp = ["certifi", "pyopenssl (>=17.2.0)", "requests (<3.0.0)", "service-identity (>=18.1.0)"] +snappy = ["python-snappy"] +srv = ["dnspython (>=1.16.0,<1.17.0)"] +tls = ["ipaddress"] +zstd = ["zstandard"] + +[[package]] +name = "pytest" +version = "7.1.2" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ {file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"}, {file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"}, ] -pytz = [ + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +tomli = ">=1.0.0" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] + +[[package]] +name = "python-dotenv" +version = "0.20.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "python-dotenv-0.20.0.tar.gz", hash = "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f"}, + {file = "python_dotenv-0.20.0-py3-none-any.whl", hash = "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "pytz" +version = "2022.1" +description = "World timezone definitions, modern and historical" +category = "main" +optional = false +python-versions = "*" +files = [ {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, ] -pyyaml = [ + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, @@ -753,6 +865,13 @@ pyyaml = [ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, @@ -780,19 +899,70 @@ pyyaml = [ {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, ] -rich = [ - {file = "rich-12.3.0-py3-none-any.whl", hash = "sha256:0eb63013630c6ee1237e0e395d51cb23513de6b5531235e33889e8842bdf3a6f"}, - {file = "rich-12.3.0.tar.gz", hash = "sha256:7e8700cda776337036a712ff0495b04052fb5f957c7dfb8df997f88350044b64"}, + +[[package]] +name = "rich" +version = "12.4.4" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "main" +optional = false +python-versions = ">=3.6.3,<4.0.0" +files = [ + {file = "rich-12.4.4-py3-none-any.whl", hash = "sha256:d2bbd99c320a2532ac71ff6a3164867884357da3e3301f0240090c5d2fdac7ec"}, + {file = "rich-12.4.4.tar.gz", hash = "sha256:4c586de507202505346f3e32d1363eb9ed6932f0c2f63184dea88983ff4971e2"}, ] -tomli = [ + +[package.dependencies] +commonmark = ">=0.9.0,<0.10.0" +pygments = ">=2.6.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -umongo = [ - {file = "umongo-3.1.0-py2.py3-none-any.whl", hash = "sha256:f6913027651ae673d71aaf54285f9ebf1e49a3f57662e526d029ba72e1a3fcd5"}, - {file = "umongo-3.1.0.tar.gz", hash = "sha256:20c72f09edae931285c22c1928862af35b90ec639a4dac2dbf015aaaac00e931"}, + +[[package]] +name = "typing-extensions" +version = "4.5.0" +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"}, ] -yarl = [ + +[[package]] +name = "yarl" +version = "1.7.2" +description = "Yet another URL library" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95"}, {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b"}, {file = "yarl-1.7.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05"}, @@ -866,3 +1036,12 @@ yarl = [ {file = "yarl-1.7.2-cp39-cp39-win_amd64.whl", hash = "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58"}, {file = "yarl-1.7.2.tar.gz", hash = "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd"}, ] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "84cab99ecb88d9ec78e000c8c60846be692556b59fd0b9ceaf4be537329b1d66" diff --git a/pyproject.toml b/pyproject.toml index 6497c0d..e6df799 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,18 +6,23 @@ authors = ["Zevaryx "] [tool.poetry.dependencies] python = "^3.10" -orjson = "^3.6.6" +orjson = {version = "^3.6.6"} motor = "^2.5.1" -umongo = "^3.1.0" -PyYAML = "^6.0" +PyYAML = {version = "^6.0"} pytz = "^2022.1" aiohttp = "^3.8.1" rich = "^12.3.0" nanoid = "^2.0.0" +python-dotenv = {version = "^0.20.0"} +beanie = "^1.17.0" +pydantic = "^1.10.7" [tool.poetry.dev-dependencies] pytest = "^7.1" +[tool.poetry.group.dev.dependencies] +black = "^23.1.0" + [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" From 15fc5f93a6ca91857c0f07794a37ff0192db0122 Mon Sep 17 00:00:00 2001 From: zevaryx Date: Thu, 23 Mar 2023 22:06:12 -0600 Subject: [PATCH 02/12] Fix merge breaks --- jarvis_core/config.py | 3 ++- jarvis_core/db/models/modlog.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/jarvis_core/config.py b/jarvis_core/config.py index 15af84f..6802784 100644 --- a/jarvis_core/config.py +++ b/jarvis_core/config.py @@ -1,5 +1,6 @@ """Load global config.""" -import os +import ast +from os import environ from lib2to3.pgen2 import token from pathlib import Path from typing import Any, Dict, List, Optional, Type diff --git a/jarvis_core/db/models/modlog.py b/jarvis_core/db/models/modlog.py index 77cb6f2..6b53df3 100644 --- a/jarvis_core/db/models/modlog.py +++ b/jarvis_core/db/models/modlog.py @@ -2,6 +2,7 @@ from datetime import datetime, timezone from functools import partial +import nanoid from bson import ObjectId from beanie import Document from pydantic import BaseModel, Field From f0a4deaf72c17b227122d2011b9018513ed87e86 Mon Sep 17 00:00:00 2001 From: zevaryx Date: Thu, 23 Mar 2023 22:07:43 -0600 Subject: [PATCH 03/12] Use smarter replicated db management --- jarvis_core/db/__init__.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/jarvis_core/db/__init__.py b/jarvis_core/db/__init__.py index ad7ed25..5f12fb3 100644 --- a/jarvis_core/db/__init__.py +++ b/jarvis_core/db/__init__.py @@ -7,26 +7,24 @@ from jarvis_core.db.models import all_models async def connect( + host: list[str] | str, username: str, password: str, port: int = 27017, testing: bool = False, - host: str = None, - hosts: list[str] = None, - replicaset: str = None, extra_models: list = [], ) -> None: """ Connect to MongoDB. Args: - host: Hostname/IP + host: Hostname/IP, or list of hosts for replica sets username: Username password: Password port: Port testing: Whether or not to use jarvis_dev extra_models: Extra beanie models to register """ - client = AsyncIOMotorClient(host=host, username=username, password=password, port=port, tz_aware=True, tzinfo=utc) + client = AsyncIOMotorClient(host, username=username, password=password, port=port, tz_aware=True, tzinfo=utc) db = client.jarvis_dev if testing else client.jarvis await init_beanie(database=db, document_models=all_models + extra_models) From 60090951cf8dd51bc72f84bd1a6ec2488a27bf9f Mon Sep 17 00:00:00 2001 From: zevaryx Date: Fri, 24 Mar 2023 11:36:21 -0600 Subject: [PATCH 04/12] Change how config works, add missing models --- jarvis_core/config.py | 142 ------------------------------ jarvis_core/db/models/__init__.py | 28 +++++- 2 files changed, 26 insertions(+), 144 deletions(-) delete mode 100644 jarvis_core/config.py diff --git a/jarvis_core/config.py b/jarvis_core/config.py deleted file mode 100644 index 6802784..0000000 --- a/jarvis_core/config.py +++ /dev/null @@ -1,142 +0,0 @@ -"""Load global config.""" -import ast -from os import environ -from lib2to3.pgen2 import token -from pathlib import Path -from typing import Any, Dict, List, Optional, Type - -import orjson as json -import yaml -from dotenv import load_dotenv -from pydantic import BaseModel - - -try: - from yaml import CLoader as Loader -except ImportError: - from yaml import Loader - - -DEFAULT_YAML = Path("config.yaml") -DEFAULT_JSON = Path("config.json") - - -class Config: - REQUIRED: Dict[str, Type] = {} - OPTIONAL: Dict[str, Dict[str, Any]] = {} - - def __new__(cls, *args: list, **kwargs: dict): - """Create a new Config object.""" - - for arg, flags in cls.OPTIONAL.items(): - kwargs[arg] = kwargs.get(arg, flags["default"]) - - inst = super().__new__(cls, *args, **kwargs) - inst._validate() - - return inst - - def _validate(self) -> None: - for key in self.REQUIRED.keys(): - if getattr(self, key, None) is None: - raise ValueError(f"Missing required key: {key}") - - @classmethod - def from_env(cls) -> "Config": - """Load the .env config file.""" - load_dotenv() - data = {} - for k, t in cls.REQUIRED.items(): - value = environ.get(k.upper(), None) - if value and not isinstance(value, t): - if t is dict: - try: - value = ast.literal_eval(value) - except Exception: - raise ValueError(f"{k} is a dict but is not formatted properly") - elif t is bool: - value = value.lower() in ["true", "yes", "t", "y", "1"] - else: - try: - value = t(value) - except Exception: - continue - data[k] = value - for k, flags in cls.OPTIONAL.items(): - t = flags["type"] - value = environ.get(k.upper(), flags["default"]) - if value and not isinstance(value, t): - if t is dict: - try: - value = ast.literal_eval(value) - except Exception: - raise ValueError(f"{k} is a dict but is not formatted properly") - elif t is bool: - value = value.lower() in ["true", "yes", "t", "y", "1"] - else: - try: - value = t(value) - except Exception: - continue - data[k] = value - - return cls(**data) - - @classmethod - def from_json(cls, filepath: Path | str = DEFAULT_JSON) -> "Config": - """Load the json config file.""" - if inst := cls.__dict__.get("inst"): - return inst - - if isinstance(filepath, str): - filepath = Path(filepath) - - with filepath.open() as f: - raw = f.read() - - j = json.loads(raw) - return cls(**j) - - @classmethod - def from_yaml(cls, filepath: Path | str = DEFAULT_YAML) -> "Config": - """Load the yaml config file.""" - if inst := cls.__dict__.get("inst"): - return inst - - if isinstance(filepath, str): - filepath = Path(filepath) - - with filepath.open() as f: - raw = f.read() - - y = yaml.load(raw, Loader=Loader) - return cls(**y) - - @classmethod - def load(cls, method: Optional[str] = None) -> "Config": - """ - Load the config in a somewhat generic way. - - Default load order is: yaml, json, env - - Args: - method: Load method, one of: yaml, json, env - """ - methods = ["yaml", "json", "env"] - if method and method in methods: - methods.remove(method) - methods.insert(0, method) - for method in methods: - try: - m = cls.__dict__.get(f"from_{method}", None) - if m: - return m() - except Exception: - continue - - raise ValueError("Unable to load configuration, please create one of: config.yaml, config.json, .env") - - @classmethod - def reload(cls) -> bool: - """Reload the config.""" - return cls.__dict__.pop("inst", None) is None diff --git a/jarvis_core/db/models/__init__.py b/jarvis_core/db/models/__init__.py index 24435a6..7d424c0 100644 --- a/jarvis_core/db/models/__init__.py +++ b/jarvis_core/db/models/__init__.py @@ -1,6 +1,7 @@ """JARVIS database models.""" from datetime import datetime, timezone from functools import partial +from typing import Optional from beanie import Document, Link from pydantic import BaseModel, Field @@ -28,10 +29,12 @@ __all__ = [ "Purge", "Reminder", "Rolegiver", + "Bypass", "Roleping", "Setting", "Subreddit", "SubredditFollow", + "Tag", "Temprole", "TwitterAccount", "TwitterFollow", @@ -74,6 +77,14 @@ class Config(Document): value: str | int | bool +class Filter(Document): + """Filter database object.""" + + guild: int + name: str + filters: list[str] = Field(default_factory=list) + + class Guess(Document): """Guess database object.""" @@ -167,7 +178,7 @@ class Setting(Document): guild: int setting: str - value: str | int | bool + value: str | int | bool | list[int | str] class Pinboard(Document): @@ -189,10 +200,22 @@ class Pin(Document): pinboard: Link[Pinboard] guild: int admin: int - star: int + pin: int created_at: datetime = NowField() +class Tag(Document): + """Tag database object.""" + + creator: int + name: str + content: str + guild: int + created_at: datetime = NowField() + edited_at: Optional[datetime] = None + editor: Optional[int] = None + + class Temprole(Document): """Temporary role object.""" @@ -239,6 +262,7 @@ all_models = [ Setting, Subreddit, SubredditFollow, + Tag, Temprole, TwitterAccount, TwitterFollow, From 9ec12bb98c797bac465c5c00426f5c4f2a82282a Mon Sep 17 00:00:00 2001 From: zevaryx Date: Fri, 24 Mar 2023 13:43:25 -0600 Subject: [PATCH 05/12] Finish migrating to beanie, centralize partial fields --- jarvis_core/db/models/__init__.py | 30 +++-- jarvis_core/db/models/actions.py | 13 +-- jarvis_core/db/models/backups.py | 178 ++++++++++++++---------------- jarvis_core/db/models/mastodon.py | 32 +++--- jarvis_core/db/models/modlog.py | 25 +---- jarvis_core/db/models/reddit.py | 13 +-- jarvis_core/db/models/twitter.py | 13 +-- jarvis_core/db/utils.py | 8 +- 8 files changed, 126 insertions(+), 186 deletions(-) diff --git a/jarvis_core/db/models/__init__.py b/jarvis_core/db/models/__init__.py index 7d424c0..74c067f 100644 --- a/jarvis_core/db/models/__init__.py +++ b/jarvis_core/db/models/__init__.py @@ -1,6 +1,5 @@ """JARVIS database models.""" -from datetime import datetime, timezone -from functools import partial +from datetime import datetime from typing import Optional from beanie import Document, Link @@ -10,6 +9,7 @@ from jarvis_core.db.models.actions import Ban, Kick, Mute, Unban, Warning from jarvis_core.db.models.modlog import Action, Modlog, Note from jarvis_core.db.models.reddit import Subreddit, SubredditFollow from jarvis_core.db.models.twitter import TwitterAccount, TwitterFollow +from jarvis_core.db.utils import NowField __all__ = [ "Action", @@ -45,14 +45,6 @@ __all__ = [ ] -def get_now() -> datetime: - """Get proper timestamp.""" - return datetime.now(tz=timezone.utc) - - -NowField = partial(Field, default_factory=get_now) - - class Autopurge(Document): guild: int channel: int @@ -131,7 +123,7 @@ class Purge(Document): admin: int channel: int guild: int - count: int = 10 + count_: int = Field(10, alias="count") created_at: datetime = NowField() @@ -181,6 +173,15 @@ class Setting(Document): value: str | int | bool | list[int | str] +class Phishlist(Document): + """Phishlist database object.""" + + url: str + confirmed: bool = False + valid: bool = True + created_at: datetime = NowField() + + class Pinboard(Document): """Pinboard database object.""" @@ -233,15 +234,11 @@ class UserSetting(Document): user: int type: str - settings: str + setting: str value: str | int | bool - class Setting: - name = "usersetting" - all_models = [ - Action, Autopurge, Autoreact, Ban, @@ -252,7 +249,6 @@ all_models = [ Lockdown, Modlog, Mute, - Note, Pin, Pinboard, Purge, diff --git a/jarvis_core/db/models/actions.py b/jarvis_core/db/models/actions.py index 36f05c9..b2a66e0 100644 --- a/jarvis_core/db/models/actions.py +++ b/jarvis_core/db/models/actions.py @@ -1,17 +1,10 @@ """User action models.""" -from datetime import datetime, timezone -from functools import partial +from datetime import datetime from typing import Optional -from beanie import Document, Field +from beanie import Document - -def get_now() -> datetime: - """Get proper timestamp.""" - return datetime.now(tz=timezone.utc) - - -NowField = partial(Field, default_factory=get_now) +from jarvis_core.db.utils import NowField class Ban(Document): diff --git a/jarvis_core/db/models/backups.py b/jarvis_core/db/models/backups.py index 9a0b661..9926abb 100644 --- a/jarvis_core/db/models/backups.py +++ b/jarvis_core/db/models/backups.py @@ -1,122 +1,104 @@ from datetime import datetime -from typing import List, Optional +from typing import Optional -from umongo import Document, EmbeddedDocument, fields +from beanie import Document, Indexed, Link +from pydantic import BaseModel, Field from jarvis_core import __version__ -from jarvis_core.db import JARVIS_INST -from jarvis_core.db.fields import BinaryField -from jarvis_core.db.utils import get_id, get_now +from jarvis_core.db.utils import NanoField, NowField -@JARVIS_INST.register class Image(Document): - discord_id: int = fields.IntegerField(unique=True) - image_data: List[bytes] = BinaryField() - image_ext: str = fields.StringField() - created_at: datetime = fields.AwareDateTimeField(default=get_now) + discord_id: int = Indexed(int, unique=True) + image_data: list[bytes] + image_ext: str + created_at: datetime = NowField() -@JARVIS_INST.register -class PermissionOverwriteBackup(EmbeddedDocument): - id: int = fields.IntegerField() - type: int = fields.IntegerField() - allow: int = fields.IntegerField() - deny: int = fields.IntegerField() +class PermissionOverwriteBackup(BaseModel): + id: int + type: int + allow: int + deny: int -@JARVIS_INST.register -class WebhookBackup(EmbeddedDocument): - id: int = fields.IntegerField() - channel_id: int = fields.IntegerField() - type: int = fields.IntegerField() - avatar: Image = fields.ReferenceField(Image) - name: str = fields.StringField() +class WebhookBackup(BaseModel): + id: int + channel_id: int + type: int + avatar: Link[Image] + name: str -@JARVIS_INST.register -class ChannelBackup(EmbeddedDocument): - id: int = fields.IntegerField() - name: str = fields.StringField() - type: int = fields.IntegerField() - position: int = fields.IntegerField() - topic: Optional[str] = fields.StringField(default=None) - nsfw: bool = fields.BooleanField(default=False) - rate_limit_per_user: int = fields.IntegerField(default=None) - bitrate: Optional[int] = fields.IntegerField(default=None) - user_limit: Optional[int] = fields.IntegerField(default=None) - permission_overwrites: List[PermissionOverwriteBackup] = fields.ListField( - fields.EmbeddedField(PermissionOverwriteBackup), factory=list - ) - parent_id: Optional[int] = fields.IntegerField(default=None) - rtc_region: Optional[str] = fields.StringField(default=None) - video_quality_mode: Optional[int] = fields.IntegerField(default=None) - default_auto_archive_duration: Optional[int] = fields.IntegerField(default=None) - webhooks: List[WebhookBackup] = fields.ListField( - fields.EmbeddedField(WebhookBackup), factory=list - ) +class ChannelBackup(BaseModel): + id: int + name: str + type: int + position: int + topic: Optional[str] = None + nsfw: bool = False + rate_limit_per_user: Optional[int] = None + bitrate: Optional[int] = None + user_limit: Optional[int] = None + permission_overwrites: list[PermissionOverwriteBackup] = Field(default_factory=list) + parent_id: Optional[int] = None + rtc_region: Optional[str] = None + video_quality_mode: Optional[int] = None + default_auto_archive_duration: Optional[int] = None + webhooks: list[WebhookBackup] = Field(default_factory=list) -@JARVIS_INST.register -class RoleBackup(EmbeddedDocument): - id: int = fields.IntegerField() - name: str = fields.StringField() - permissions: int = fields.IntegerField() - color: str = fields.StringField() - hoist: bool = fields.BooleanField() - mentionable: bool = fields.BooleanField() +class RoleBackup(BaseModel): + id: int + name: str + permissions: int + color: str + hoist: bool + mentionable: bool -@JARVIS_INST.register -class EmojiBackup(EmbeddedDocument): - id: int = fields.IntegerField() - name: str = fields.StringField() - image: Image = fields.ReferenceField(Image) +class EmojiBackup(BaseModel): + id: int + name: str + image: Link[Image] -@JARVIS_INST.register -class StickerBackup(EmbeddedDocument): - id: int = fields.IntegerField() - name: str = fields.StringField() - format_type: int = fields.IntegerField() - tags: str = fields.StringField() - type: int = fields.IntegerField() - image: Image = fields.ReferenceField(Image) +class StickerBackup(BaseModel): + id: int + name: str + format_type: int + tags: str + type: int + image: Link[Image] -@JARVIS_INST.register -class GuildBackup(EmbeddedDocument): - name: str = fields.StringField(required=True) - description: str = fields.StringField(default=None) - default_message_notifications: Optional[int] = fields.IntegerField(default=None) - explicit_content_filter: Optional[int] = fields.IntegerField(default=None) - afk_channel: Optional[int] = fields.IntegerField(default=None) - afk_timeout: Optional[int] = fields.IntegerField(default=None) - icon: Optional[Image] = fields.ReferenceField(Image, default=None) - owner: int = fields.IntegerField(required=True) - splash: Optional[Image] = fields.ReferenceField(Image, default=None) - discovery_splash: Optional[Image] = fields.ReferenceField(Image, default=None) - banner: Optional[Image] = fields.ReferenceField(Image, default=None) - system_channel: Optional[int] = fields.IntegerField(default=None) - system_channel_flags: Optional[int] = fields.IntegerField(default=None) - rules_channel: Optional[int] = fields.IntegerField(default=None) - public_updates_channel: Optional[int] = fields.IntegerField(default=None) - preferred_locale: Optional[str] = fields.StringField(default=None) - features: List[str] = fields.ListField(fields.StringField, factory=list) - channels: List[ChannelBackup] = fields.ListField( - fields.EmbeddedField(ChannelBackup), factory=list - ) - roles: List[RoleBackup] = fields.ListField(fields.EmbeddedField(RoleBackup), factory=list) - emojis: List[EmojiBackup] = fields.ListField(fields.EmbeddedField(EmojiBackup), factory=list) - stickers: List[StickerBackup] = fields.ListField( - fields.EmbeddedField(StickerBackup), factory=list - ) +class GuildBackup(BaseModel): + name: str + description: Optional[str] = None + default_message_notifications: Optional[int] = None + explicit_content_filter: Optional[int] = None + afk_channel: Optional[int] = None + afk_timeout: Optional[int] = None + icon: Optional[Link[Image]] = None + owner: int + splash: Optional[Link[Image]] = None + discovery_splash: Optional[Link[Image]] = None + banner: Optional[Link[Image]] = None + system_channel: Optional[int] = None + system_channel_flags: Optional[int] = None + rules_channel: Optional[int] = None + public_updates_channel: Optional[int] = None + preferred_locale: Optional[str] = None + features: list[str] = Field(default_factory=list) + channels: list[ChannelBackup] = Field(default_factory=list) + roles: list[RoleBackup] = Field(default_factory=list) + emojis: list[EmojiBackup] = Field(default_factory=list) + stickers: list[StickerBackup] = Field(default_factory=list) -@JARVIS_INST.register class Backup(Document): - created_at: datetime = fields.AwareDateTimeField(default=get_now) - guild_id: int = fields.IntegerField() - bkid: str = fields.StringField(default=get_id) - guild: GuildBackup = fields.EmbeddedField(GuildBackup, required=True) - version: str = fields.StringField(default=__version__) + created_at: datetime = NowField() + guild_id: int + bkid: str = NanoField() + guild: GuildBackup + version: str = Field(default=__version__) diff --git a/jarvis_core/db/models/mastodon.py b/jarvis_core/db/models/mastodon.py index 1a79ed0..f7384b9 100644 --- a/jarvis_core/db/models/mastodon.py +++ b/jarvis_core/db/models/mastodon.py @@ -1,36 +1,30 @@ """Mastodon databaes models.""" from datetime import datetime, timezone -from umongo import Document, fields +from beanie import Document from jarvis_core.db import JARVIS_INST -from jarvis_core.db.utils import get_now +from jarvis_core.db.utils import NowField @JARVIS_INST.register class MastodonUser(Document): """User object.""" - user_id: int = fields.IntegerField(required=True) - acct: str = fields.StringField(required=True) - username: str = fields.StringField(required=True) - last_sync: datetime = fields.AwareDateTimeField(default=get_now) - - class Meta: - collection_name = "mastodonuser" + user_id: int + acct: str + username: str + last_sync: datetime = NowField() @JARVIS_INST.register class MastodonFollow(Document): """User Follow object.""" - active: bool = fields.BooleanField(default=True) - user_id: int = fields.IntegerField(required=True) - channel: int = fields.IntegerField(required=True) - guild: int = fields.IntegerField(required=True) - reblogged: bool = fields.BooleanField(default=True) - admin: int = fields.IntegerField(required=True) - created_at: datetime = fields.AwareDateTimeField(default=get_now) - - class Meta: - collection_name = "mastodonfollow" + active: bool = True + user_id: int + channel: int + guild: int + reblogged: bool = True + admin: int + created_at: datetime = NowField() diff --git a/jarvis_core/db/models/modlog.py b/jarvis_core/db/models/modlog.py index 6b53df3..4641162 100644 --- a/jarvis_core/db/models/modlog.py +++ b/jarvis_core/db/models/modlog.py @@ -1,34 +1,17 @@ """Modlog database models.""" -from datetime import datetime, timezone -from functools import partial +from datetime import datetime -import nanoid -from bson import ObjectId -from beanie import Document +from beanie import Document, PydanticObjectId from pydantic import BaseModel, Field -NANOID_ALPHA = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - - -def get_now() -> datetime: - """Get proper timestamp.""" - return datetime.now(tz=timezone.utc) - - -def get_id() -> str: - """Get nanoid.""" - return nanoid.generate(NANOID_ALPHA, 12) - - -NanoField = partial(Field, default_factory=get_id) -NowField = partial(Field, default_factory=get_now) +from jarvis_core.db.utils import NowField, NanoField class Action(BaseModel): """Modlog embedded action document.""" action_type: str - parent: ObjectId + parent: PydanticObjectId orphaned: bool = False diff --git a/jarvis_core/db/models/reddit.py b/jarvis_core/db/models/reddit.py index eeb8926..fc6be4e 100644 --- a/jarvis_core/db/models/reddit.py +++ b/jarvis_core/db/models/reddit.py @@ -1,16 +1,9 @@ """Reddit databaes models.""" -from datetime import datetime, timezone -from functools import partial +from datetime import datetime -from beanie import Document, Field +from beanie import Document - -def get_now() -> datetime: - """Get proper timestamp.""" - return datetime.now(tz=timezone.utc) - - -NowField = partial(Field, default_factory=get_now) +from jarvis_core.db.utils import NowField class Subreddit(Document): diff --git a/jarvis_core/db/models/twitter.py b/jarvis_core/db/models/twitter.py index e13dd8a..a494aae 100644 --- a/jarvis_core/db/models/twitter.py +++ b/jarvis_core/db/models/twitter.py @@ -1,16 +1,9 @@ """Twitter database models.""" -from datetime import datetime, timezone -from functools import partial +from datetime import datetime -from beanie import Document, Field +from beanie import Document - -def get_now() -> datetime: - """Get proper timestamp.""" - return datetime.now(tz=timezone.utc) - - -NowField = partial(Field, default_factory=get_now) +from jarvis_core.db.utils import NowField class TwitterAccount(Document): diff --git a/jarvis_core/db/utils.py b/jarvis_core/db/utils.py index c56a2e2..393889e 100644 --- a/jarvis_core/db/utils.py +++ b/jarvis_core/db/utils.py @@ -1,6 +1,8 @@ from datetime import datetime, timezone +from functools import partial import nanoid +from pydantic import Field NANOID_ALPHA = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" @@ -12,4 +14,8 @@ def get_now() -> datetime: def get_id() -> str: """Get nanoid.""" - return nanoid.generate(NANOID_ALPHA, 12) + return nanoid.generate(NANOID_ALPHA, 12) + + +NowField = partial(Field, default_factory=get_now) +NanoField = partial(Field, default_factory=get_id) From 2521b7d6c92232d9fa5e2802ca06b63faf7cfb5d Mon Sep 17 00:00:00 2001 From: zevaryx Date: Tue, 9 May 2023 09:20:22 -0600 Subject: [PATCH 06/12] fix: Finalize beanie migration --- jarvis_core/db/models/__init__.py | 2 ++ jarvis_core/db/models/captcha.py | 12 ++++++++++++ pyproject.toml | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 jarvis_core/db/models/captcha.py diff --git a/jarvis_core/db/models/__init__.py b/jarvis_core/db/models/__init__.py index 74c067f..d9347c8 100644 --- a/jarvis_core/db/models/__init__.py +++ b/jarvis_core/db/models/__init__.py @@ -17,6 +17,7 @@ __all__ = [ "Autoreact", "Ban", "Config", + "Filter", "Guess", "Kick", "Lock", @@ -243,6 +244,7 @@ all_models = [ Autoreact, Ban, Config, + Filter, Guess, Kick, Lock, diff --git a/jarvis_core/db/models/captcha.py b/jarvis_core/db/models/captcha.py new file mode 100644 index 0000000..d10752f --- /dev/null +++ b/jarvis_core/db/models/captcha.py @@ -0,0 +1,12 @@ +from datetime import datetime +from beanie import Document +from pydantic import Field + +from jarvis_core.db.utils import get_now + + +class Captcha(Document): + user: int + guild: int + correct: str + created_at: datetime = Field(default_factory=get_now) diff --git a/pyproject.toml b/pyproject.toml index aa6972a..1f63e82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ description = "JARVIS core" authors = ["Zevaryx "] [tool.poetry.dependencies] -python = "^3.10" +python = ">=3.10,<4" orjson = {version = "^3.6.6"} motor = "^3.1.1" PyYAML = {version = "^6.0"} From 515cf962083bf5a9c585ec7be96ee1a380e92f71 Mon Sep 17 00:00:00 2001 From: Zevaryx Date: Wed, 10 May 2023 22:26:58 +0000 Subject: [PATCH 07/12] feat: Add VoteMod, ref jarvis-bot#178 --- jarvis_core/db/models/__init__.py | 547 +++++++++++++++--------------- jarvis_core/db/models/votemod.py | 26 ++ 2 files changed, 303 insertions(+), 270 deletions(-) create mode 100644 jarvis_core/db/models/votemod.py diff --git a/jarvis_core/db/models/__init__.py b/jarvis_core/db/models/__init__.py index d9347c8..8ddb96d 100644 --- a/jarvis_core/db/models/__init__.py +++ b/jarvis_core/db/models/__init__.py @@ -1,270 +1,277 @@ -"""JARVIS database models.""" -from datetime import datetime -from typing import Optional - -from beanie import Document, Link -from pydantic import BaseModel, Field - -from jarvis_core.db.models.actions import Ban, Kick, Mute, Unban, Warning -from jarvis_core.db.models.modlog import Action, Modlog, Note -from jarvis_core.db.models.reddit import Subreddit, SubredditFollow -from jarvis_core.db.models.twitter import TwitterAccount, TwitterFollow -from jarvis_core.db.utils import NowField - -__all__ = [ - "Action", - "Autopurge", - "Autoreact", - "Ban", - "Config", - "Filter", - "Guess", - "Kick", - "Lock", - "Lockdown", - "Modlog", - "Mute", - "Note", - "Pin", - "Pinboard", - "Purge", - "Reminder", - "Rolegiver", - "Bypass", - "Roleping", - "Setting", - "Subreddit", - "SubredditFollow", - "Tag", - "Temprole", - "TwitterAccount", - "TwitterFollow", - "Unban", - "UserSetting", - "Warning", - "all_models", -] - - -class Autopurge(Document): - guild: int - channel: int - delay: int = 30 - admin: int - created_at: datetime = NowField() - - -class Autoreact(Document): - guild: int - channel: int - reactions: list[str] = Field(default_factory=list) - admin: int - thread: bool - created_at: datetime = NowField() - - -class Config(Document): - """Config database object.""" - - key: str - value: str | int | bool - - -class Filter(Document): - """Filter database object.""" - - guild: int - name: str - filters: list[str] = Field(default_factory=list) - - -class Guess(Document): - """Guess database object.""" - - correct: bool - guess: str - user: int - - -class Permission(BaseModel): - """Embedded Permissions document.""" - - id: int - allow: int = 0 - deny: int = 0 - - -class Lock(Document): - """Lock database object.""" - - active: bool = True - admin: int - channel: int - duration: int = 10 - reason: str - original_perms: Permission - created_at: datetime = NowField() - - -class Lockdown(Document): - """Lockdown database object.""" - - active: bool = True - admin: int - duration: int = 10 - guild: int - reason: str - original_perms: int - created_at: datetime = NowField() - - -class Purge(Document): - """Purge database object.""" - - admin: int - channel: int - guild: int - count_: int = Field(10, alias="count") - created_at: datetime = NowField() - - -class Reminder(Document): - """Reminder database object.""" - - active: bool = True - user: int - guild: int - channel: int - message: str - remind_at: datetime - created_at: datetime = NowField() - private: bool = False - - -class Rolegiver(Document): - """Rolegiver database object.""" - - guild: int - roles: list[int] - - -class Bypass(BaseModel): - """Roleping bypass embedded object.""" - - users: list[int] - roles: list[int] - - -class Roleping(Document): - """Roleping database object.""" - - active: bool = True - role: int - guild: int - admin: int - bypass: Bypass - created_at: datetime = NowField() - - -class Setting(Document): - """Setting database object.""" - - guild: int - setting: str - value: str | int | bool | list[int | str] - - -class Phishlist(Document): - """Phishlist database object.""" - - url: str - confirmed: bool = False - valid: bool = True - created_at: datetime = NowField() - - -class Pinboard(Document): - """Pinboard database object.""" - - channel: int - guild: int - admin: int - created_at: datetime = NowField() - - -class Pin(Document): - """Pin database object.""" - - active: bool = True - index: int - message: int - channel: int - pinboard: Link[Pinboard] - guild: int - admin: int - pin: int - created_at: datetime = NowField() - - -class Tag(Document): - """Tag database object.""" - - creator: int - name: str - content: str - guild: int - created_at: datetime = NowField() - edited_at: Optional[datetime] = None - editor: Optional[int] = None - - -class Temprole(Document): - """Temporary role object.""" - - guild: int - user: int - role: int - admin: int - expires_at: datetime - reapply_on_rejoin: bool = True - created_at: datetime = NowField() - - -class UserSetting(Document): - """User Setting object.""" - - user: int - type: str - setting: str - value: str | int | bool - - -all_models = [ - Autopurge, - Autoreact, - Ban, - Config, - Filter, - Guess, - Kick, - Lock, - Lockdown, - Modlog, - Mute, - Pin, - Pinboard, - Purge, - Reminder, - Rolegiver, - Roleping, - Setting, - Subreddit, - SubredditFollow, - Tag, - Temprole, - TwitterAccount, - TwitterFollow, - Unban, - UserSetting, - Warning, -] +"""JARVIS database models.""" +from datetime import datetime +from typing import Optional + +from beanie import Document, Link +from pydantic import BaseModel, Field + +from jarvis_core.db.models.actions import Ban, Kick, Mute, Unban, Warning +from jarvis_core.db.models.modlog import Action, Modlog, Note +from jarvis_core.db.models.reddit import Subreddit, SubredditFollow +from jarvis_core.db.models.twitter import TwitterAccount, TwitterFollow +from jarvis_core.db.models.votemod import Karma, Vote, VoteMod +from jarvis_core.db.utils import NowField + +__all__ = [ + "Action", + "Autopurge", + "Autoreact", + "Ban", + "Config", + "Filter", + "Guess", + "Kick", + "Lock", + "Lockdown", + "Modlog", + "Mute", + "Note", + "Pin", + "Pinboard", + "Purge", + "Reminder", + "Rolegiver", + "Bypass", + "Roleping", + "Setting", + "Subreddit", + "SubredditFollow", + "Tag", + "Temprole", + "TwitterAccount", + "TwitterFollow", + "Unban", + "UserSetting", + "Warning", + "Karma", + "Vote", + "VoteMod", + "all_models", +] + + +class Autopurge(Document): + guild: int + channel: int + delay: int = 30 + admin: int + created_at: datetime = NowField() + + +class Autoreact(Document): + guild: int + channel: int + reactions: list[str] = Field(default_factory=list) + admin: int + thread: bool + created_at: datetime = NowField() + + +class Config(Document): + """Config database object.""" + + key: str + value: str | int | bool + + +class Filter(Document): + """Filter database object.""" + + guild: int + name: str + filters: list[str] = Field(default_factory=list) + + +class Guess(Document): + """Guess database object.""" + + correct: bool + guess: str + user: int + + +class Permission(BaseModel): + """Embedded Permissions document.""" + + id: int + allow: int = 0 + deny: int = 0 + + +class Lock(Document): + """Lock database object.""" + + active: bool = True + admin: int + channel: int + duration: int = 10 + reason: str + original_perms: Permission + created_at: datetime = NowField() + + +class Lockdown(Document): + """Lockdown database object.""" + + active: bool = True + admin: int + duration: int = 10 + guild: int + reason: str + original_perms: int + created_at: datetime = NowField() + + +class Purge(Document): + """Purge database object.""" + + admin: int + channel: int + guild: int + count_: int = Field(10, alias="count") + created_at: datetime = NowField() + + +class Reminder(Document): + """Reminder database object.""" + + active: bool = True + user: int + guild: int + channel: int + message: str + remind_at: datetime + created_at: datetime = NowField() + private: bool = False + + +class Rolegiver(Document): + """Rolegiver database object.""" + + guild: int + roles: list[int] + + +class Bypass(BaseModel): + """Roleping bypass embedded object.""" + + users: list[int] + roles: list[int] + + +class Roleping(Document): + """Roleping database object.""" + + active: bool = True + role: int + guild: int + admin: int + bypass: Bypass + created_at: datetime = NowField() + + +class Setting(Document): + """Setting database object.""" + + guild: int + setting: str + value: str | int | bool | list[int | str] + + +class Phishlist(Document): + """Phishlist database object.""" + + url: str + confirmed: bool = False + valid: bool = True + created_at: datetime = NowField() + + +class Pinboard(Document): + """Pinboard database object.""" + + channel: int + guild: int + admin: int + created_at: datetime = NowField() + + +class Pin(Document): + """Pin database object.""" + + active: bool = True + index: int + message: int + channel: int + pinboard: Link[Pinboard] + guild: int + admin: int + pin: int + created_at: datetime = NowField() + + +class Tag(Document): + """Tag database object.""" + + creator: int + name: str + content: str + guild: int + created_at: datetime = NowField() + edited_at: Optional[datetime] = None + editor: Optional[int] = None + + +class Temprole(Document): + """Temporary role object.""" + + guild: int + user: int + role: int + admin: int + expires_at: datetime + reapply_on_rejoin: bool = True + created_at: datetime = NowField() + + +class UserSetting(Document): + """User Setting object.""" + + user: int + type: str + setting: str + value: str | int | bool + + +all_models = [ + Autopurge, + Autoreact, + Ban, + Config, + Filter, + Guess, + Karma, + Kick, + Lock, + Lockdown, + Modlog, + Mute, + Pin, + Pinboard, + Purge, + Reminder, + Rolegiver, + Roleping, + Setting, + Subreddit, + SubredditFollow, + Tag, + Temprole, + TwitterAccount, + TwitterFollow, + Unban, + UserSetting, + Vote, + VoteMod, + Warning, +] diff --git a/jarvis_core/db/models/votemod.py b/jarvis_core/db/models/votemod.py new file mode 100644 index 0000000..df168b5 --- /dev/null +++ b/jarvis_core/db/models/votemod.py @@ -0,0 +1,26 @@ +"""VoteMod models.""" +from typing import Optional + +from beanie import Document +from pydantic import BaseModel + + +class Vote(BaseModel): + user: int + score: int + + +class Karma(Document): + user: int + karma: int = 1 + revoked: bool = False + + +class VoteMod(Document): + initiator: int + target: int + message: int + content: str + attachments: list[str] + score: int + votes: list[Vote] \ No newline at end of file From e04661bc46fd67ba062948ec7958d2e8c0f22f7f Mon Sep 17 00:00:00 2001 From: zevaryx Date: Wed, 10 May 2023 18:07:05 -0600 Subject: [PATCH 08/12] fix: Don't include Vote in all_models --- jarvis_core/db/models/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/jarvis_core/db/models/__init__.py b/jarvis_core/db/models/__init__.py index 8ddb96d..8b82e21 100644 --- a/jarvis_core/db/models/__init__.py +++ b/jarvis_core/db/models/__init__.py @@ -271,7 +271,6 @@ all_models = [ TwitterFollow, Unban, UserSetting, - Vote, VoteMod, Warning, ] From 89016de8cab9d364a76410f27c52397edbb7468b Mon Sep 17 00:00:00 2001 From: zevaryx Date: Wed, 10 May 2023 18:48:07 -0600 Subject: [PATCH 09/12] Add origin to VoteMod --- jarvis_core/db/models/votemod.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jarvis_core/db/models/votemod.py b/jarvis_core/db/models/votemod.py index df168b5..d63df9d 100644 --- a/jarvis_core/db/models/votemod.py +++ b/jarvis_core/db/models/votemod.py @@ -19,8 +19,9 @@ class Karma(Document): class VoteMod(Document): initiator: int target: int + origin: str message: int content: str attachments: list[str] score: int - votes: list[Vote] \ No newline at end of file + votes: list[Vote] From 048d370ef0aa2298dd335db5f8c5c78c3c385d49 Mon Sep 17 00:00:00 2001 From: zevaryx Date: Sun, 27 Aug 2023 14:08:30 -0600 Subject: [PATCH 10/12] v0.18.0, match ipy5 branch of JARVIS --- .flake8 | 42 +++-- .pre-commit-config.yaml | 95 +++++------ jarvis_core/config.py | 72 ++++++++ jarvis_core/db/models/__init__.py | 10 +- jarvis_core/db/models/actions.py | 4 +- jarvis_core/db/models/votemod.py | 27 --- poetry.lock | 269 ++++++++++++++++++------------ pyproject.toml | 8 +- 8 files changed, 306 insertions(+), 221 deletions(-) create mode 100644 jarvis_core/config.py delete mode 100644 jarvis_core/db/models/votemod.py diff --git a/.flake8 b/.flake8 index ad648a0..0b7f497 100644 --- a/.flake8 +++ b/.flake8 @@ -1,22 +1,20 @@ -[flake8] -exclude = - tests/* - -extend-ignore = - Q0, E501, C812, E203, W503, # These default to arguing with Black. We might configure some of them eventually - ANN1, # Ignore self and cls annotations - ANN204, ANN206, # return annotations for special methods and class methods - D105, D107, # Missing Docstrings in magic method and __init__ - S311, # Standard pseudo-random generators are not suitable for security/cryptographic purposes. - D401, # First line should be in imperative mood; try rephrasing - D400, # First line should end with a period - D101, # Missing docstring in public class - D106, # Missing docstring in public nested class - - # Plugins we don't currently include: flake8-return - R503, # missing explicit return at the end of function ableto return non-None value. - -max-line-length=100 - -per-file-ignores = - jarvis_core/db/models/__init__.py:F401 +[flake8] +exclude = + tests/* + +extend-ignore = + Q0, E501, C812, E203, W503, + ANN1, ANN003, + ANN204, ANN206, + D105, D107, + S311, + D401, + D400, + D101, D102, + D106, + R503, + +max-line-length=100 + +per-file-ignores = + jarvis_core/db/models/__init__.py:F401 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f32edb1..80a9854 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,49 +1,46 @@ -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 - hooks: - - id: check-toml - - id: check-yaml - args: [--unsafe] - - id: check-merge-conflict - - id: requirements-txt-fixer - - id: end-of-file-fixer - - id: debug-statements - language_version: python3.10 - - id: trailing-whitespace - args: [--markdown-linebreak-ext=md] - - - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.9.0 - hooks: - - id: python-check-blanket-noqa - - - repo: https://github.com/psf/black - rev: 22.3.0 - hooks: - - id: black - args: [--line-length=100, --target-version=py310] - language_version: python3.10 - - - repo: https://github.com/pre-commit/mirrors-isort - rev: v5.10.1 - hooks: - - id: isort - args: ["--profile", "black"] - - - repo: https://github.com/pycqa/flake8 - rev: 4.0.1 - hooks: - - id: flake8 - additional_dependencies: - - flake8-annotations~=2.0 - #- flake8-bandit # Uncomment once works again - - flake8-docstrings~=1.5 - - flake8-bugbear - - flake8-comprehensions - - flake8-quotes - - flake8-raise - - flake8-deprecated - - flake8-print - - flake8-return - language_version: python3.10 +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-toml + - id: check-yaml + args: [--unsafe] + - id: check-merge-conflict + - id: requirements-txt-fixer + - id: end-of-file-fixer + - id: debug-statements + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + + - repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.10.0 + hooks: + - id: python-check-blanket-noqa + + - repo: https://github.com/psf/black + rev: 23.7.0 + hooks: + - id: black + args: [--line-length=100] + + - repo: https://github.com/pre-commit/mirrors-isort + rev: v5.10.1 + hooks: + - id: isort + args: ["--profile", "black"] + + - repo: https://github.com/pycqa/flake8 + rev: 6.1.0 + hooks: + - id: flake8 + additional_dependencies: + - flake8-annotations~=2.0 + #- flake8-bandit # Uncomment once works again + - flake8-docstrings~=1.5 + - flake8-bugbear + - flake8-comprehensions + - flake8-quotes + - flake8-raise + - flake8-deprecated + - flake8-print + - flake8-return diff --git a/jarvis_core/config.py b/jarvis_core/config.py new file mode 100644 index 0000000..5f7ea0e --- /dev/null +++ b/jarvis_core/config.py @@ -0,0 +1,72 @@ +"""Load global config.""" +import os +from pathlib import Path +from typing import Union + +from dotenv import load_dotenv +from yaml import load + +from jarvis_core.util import Singleton + +try: + from yaml import CLoader as Loader +except ImportError: + from yaml import Loader + +DEFAULT_YAML_PATH = Path("config.yaml") +DEFAULT_ENV_PATH = Path(".env") + + +class Config(Singleton): + REQUIRED = [] + OPTIONAL = {} + ENV_REQUIRED = [] + ENV_OPTIONAL = {} + + @classmethod + def _process_env(cls, **kwargs) -> dict: + """Process environment variables into standard arguments""" + + @classmethod + def from_env(cls, filepath: Union[Path, str] = DEFAULT_ENV_PATH) -> "Config": + """Loag the environment config.""" + if inst := cls.__dict__.get("inst"): + return inst + + load_dotenv(filepath) + + data = {} + for item in cls.ENV_REQUIRED: + data[item] = os.environ.get(item, None) + for item, default in cls.ENV_OPTIONAL.items(): + data[item] = os.environ.get(item, default) + + data = cls._process_env(**data) + + return cls(**data) + + @classmethod + def from_yaml(cls, filepath: Union[Path, str] = DEFAULT_YAML_PATH) -> "Config": + """Load the yaml config file.""" + if inst := cls.__dict__.get("inst"): + return inst + + if isinstance(filepath, str): + filepath = Path(filepath) + + with filepath.open() as f: + raw = f.read() + + y = load(raw, Loader=Loader) + return cls(**y) + + @classmethod + def load(cls) -> "Config": + if DEFAULT_ENV_PATH.exists(): + return cls.from_env() + return cls.from_yaml() + + @classmethod + def reload(cls) -> bool: + """Reload the config.""" + return cls.__dict__.pop("inst", None) is None diff --git a/jarvis_core/db/models/__init__.py b/jarvis_core/db/models/__init__.py index 8b82e21..5507aa2 100644 --- a/jarvis_core/db/models/__init__.py +++ b/jarvis_core/db/models/__init__.py @@ -9,7 +9,6 @@ from jarvis_core.db.models.actions import Ban, Kick, Mute, Unban, Warning from jarvis_core.db.models.modlog import Action, Modlog, Note from jarvis_core.db.models.reddit import Subreddit, SubredditFollow from jarvis_core.db.models.twitter import TwitterAccount, TwitterFollow -from jarvis_core.db.models.votemod import Karma, Vote, VoteMod from jarvis_core.db.utils import NowField __all__ = [ @@ -43,9 +42,6 @@ __all__ = [ "Unban", "UserSetting", "Warning", - "Karma", - "Vote", - "VoteMod", "all_models", ] @@ -142,6 +138,10 @@ class Reminder(Document): message: str remind_at: datetime created_at: datetime = NowField() + repeat: Optional[str] = None + timezone: str = "UTC" + total_reminders: int = 0 + parent: Optional[str] = None private: bool = False @@ -250,7 +250,6 @@ all_models = [ Config, Filter, Guess, - Karma, Kick, Lock, Lockdown, @@ -271,6 +270,5 @@ all_models = [ TwitterFollow, Unban, UserSetting, - VoteMod, Warning, ] diff --git a/jarvis_core/db/models/actions.py b/jarvis_core/db/models/actions.py index b2a66e0..4583f53 100644 --- a/jarvis_core/db/models/actions.py +++ b/jarvis_core/db/models/actions.py @@ -12,7 +12,7 @@ class Ban(Document): admin: int user: int username: str - discrim: int + discrim: Optional[int] duration: Optional[int] guild: int type: str = "perm" @@ -47,7 +47,7 @@ class Unban(Document): user: int username: str - discrim: str + discrim: Optional[str] guild: int reason: str created_at: datetime = NowField() diff --git a/jarvis_core/db/models/votemod.py b/jarvis_core/db/models/votemod.py deleted file mode 100644 index d63df9d..0000000 --- a/jarvis_core/db/models/votemod.py +++ /dev/null @@ -1,27 +0,0 @@ -"""VoteMod models.""" -from typing import Optional - -from beanie import Document -from pydantic import BaseModel - - -class Vote(BaseModel): - user: int - score: int - - -class Karma(Document): - user: int - karma: int = 1 - revoked: bool = False - - -class VoteMod(Document): - initiator: int - target: int - origin: str - message: int - content: str - attachments: list[str] - score: int - votes: list[Vote] diff --git a/poetry.lock b/poetry.lock index f552824..54740da 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "aiohttp" version = "3.8.4" description = "Async http client/server framework (asyncio)" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -113,7 +112,6 @@ speedups = ["Brotli", "aiodns", "cchardet"] name = "aiosignal" version = "1.3.1" description = "aiosignal: a list of registered asynchronous callbacks" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -124,11 +122,21 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "annotated-types" +version = "0.5.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.7" +files = [ + {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, + {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, +] + [[package]] name = "appnope" version = "0.1.3" description = "Disable App Nap on macOS >= 10.9" -category = "dev" optional = false python-versions = "*" files = [ @@ -140,7 +148,6 @@ files = [ name = "asttokens" version = "2.2.1" description = "Annotate AST trees with source code positions" -category = "dev" optional = false python-versions = "*" files = [ @@ -158,7 +165,6 @@ test = ["astroid", "pytest"] name = "async-timeout" version = "4.0.2" description = "Timeout context manager for asyncio programs" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -170,7 +176,6 @@ files = [ name = "attrs" version = "22.2.0" description = "Classes Without Boilerplate" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -189,7 +194,6 @@ tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy name = "backcall" version = "0.2.0" description = "Specifications for callback functions passed in to an API" -category = "dev" optional = false python-versions = "*" files = [ @@ -199,28 +203,32 @@ files = [ [[package]] name = "beanie" -version = "1.17.0" +version = "1.21.0" description = "Asynchronous Python ODM for MongoDB" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ - {file = "beanie-1.17.0-py3-none-any.whl", hash = "sha256:a0711775051c72324fc4555120355da9a3c081d41db14ddaa8e9f368303436ef"}, - {file = "beanie-1.17.0.tar.gz", hash = "sha256:5f758785ce813838a0f25e171957afb6e70fa142dda937531427e0a530d03c64"}, + {file = "beanie-1.21.0-py3-none-any.whl", hash = "sha256:180a6d5e854297be2da84689b03509e7dc4f40f00c58a894a17ad40a00630838"}, + {file = "beanie-1.21.0.tar.gz", hash = "sha256:df1bcac1d5834730d3a1e461814fd0dfa173d91daca047b4d8ddcbf54343b4fd"}, ] [package.dependencies] click = ">=7" -lazy-model = ">=0.0.3" -motor = ">=2.5,<4.0" -pydantic = ">=1.10.0" +lazy-model = "0.1.0b0" +motor = ">=2.5.0,<4.0.0" +pydantic = ">=1.10,<3.0" toml = "*" +typing-extensions = ">=4.7" + +[package.extras] +doc = ["Markdown (>=3.3)", "Pygments (>=2.8.0)", "jinja2 (>=3.0.3)", "mkdocs (>=1.4)", "mkdocs-material (>=9.0)", "pydoc-markdown (>=4.8)"] +queue = ["beanie-batteries-queue (>=0.2)"] +test = ["asgi-lifespan (>=1.0.1)", "dnspython (>=2.1.0)", "fastapi (>=0.100)", "flake8 (>=3)", "httpx (>=0.23.0)", "pre-commit (>=2.3.0)", "pydantic-settings (>=2.0)", "pyright (>=0)", "pytest (>=6.0.0)", "pytest-asyncio (>=0.21.0)", "pytest-cov (>=2.8.1)"] [[package]] name = "black" version = "23.1.0" description = "The uncompromising code formatter." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -269,7 +277,6 @@ uvloop = ["uvloop (>=0.15.2)"] 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 = [ @@ -354,7 +361,6 @@ files = [ name = "click" version = "8.1.3" description = "Composable command line interface toolkit" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -369,7 +375,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} 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 = [ @@ -381,7 +386,6 @@ files = [ name = "commonmark" version = "0.9.1" description = "Python parser for the CommonMark Markdown spec" -category = "main" optional = false python-versions = "*" files = [ @@ -396,7 +400,6 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] name = "decorator" version = "5.1.1" description = "Decorators for Humans" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -408,7 +411,6 @@ files = [ name = "dnspython" version = "2.3.0" description = "DNS toolkit" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -429,7 +431,6 @@ wmi = ["wmi (>=1.5.1,<2.0.0)"] name = "exceptiongroup" version = "1.1.1" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -444,7 +445,6 @@ test = ["pytest (>=6)"] name = "executing" version = "1.2.0" description = "Get the currently executing AST node of a frame, and other information" -category = "dev" optional = false python-versions = "*" files = [ @@ -459,7 +459,6 @@ tests = ["asttokens", "littleutils", "pytest", "rich"] name = "frozenlist" version = "1.3.3" description = "A list-like structure which implements collections.abc.MutableSequence" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -543,7 +542,6 @@ files = [ name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -555,7 +553,6 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -567,7 +564,6 @@ files = [ name = "ipython" version = "8.11.0" description = "IPython: Productive Interactive Computing" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -606,7 +602,6 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pa name = "jedi" version = "0.18.2" description = "An autocompletion tool for Python that can be used for text editors." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -624,14 +619,13 @@ testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "lazy-model" -version = "0.0.5" +version = "0.1.0b0" description = "" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ - {file = "lazy-model-0.0.5.tar.gz", hash = "sha256:2d98f9dfe275012477555a439dceb56364793a0f266758d1a33267d68e8fbc76"}, - {file = "lazy_model-0.0.5-py3-none-any.whl", hash = "sha256:8b4fc5eac99029f84b11b21e81a6894911a475f25e53227b7e44833e62e26553"}, + {file = "lazy-model-0.1.0b0.tar.gz", hash = "sha256:90dd0b26d3033fadc18f697ab9cdd66cdf8e55469f32f2d88efd92610468e2d6"}, + {file = "lazy_model-0.1.0b0-py3-none-any.whl", hash = "sha256:74406bd54cf96a89b73570d8409b538c660ae4d0bfb4b30bbe46db2658a5937d"}, ] [package.dependencies] @@ -641,7 +635,6 @@ pydantic = ">=1.9.0" name = "matplotlib-inline" version = "0.1.6" description = "Inline Matplotlib backend for Jupyter" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -656,7 +649,6 @@ traitlets = "*" name = "motor" version = "3.1.1" description = "Non-blocking MongoDB driver for Tornado or asyncio" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -680,7 +672,6 @@ zstd = ["pymongo[zstd] (>=4.1,<5)"] name = "multidict" version = "6.0.4" description = "multidict implementation" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -764,7 +755,6 @@ files = [ 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 = [ @@ -776,7 +766,6 @@ files = [ name = "nanoid" version = "2.0.0" description = "A tiny, secure, URL-friendly, unique string ID generator for Python" -category = "main" optional = false python-versions = "*" files = [ @@ -788,7 +777,6 @@ files = [ name = "orjson" version = "3.8.8" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -847,7 +835,6 @@ files = [ name = "packaging" version = "23.0" description = "Core utilities for Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -859,7 +846,6 @@ files = [ name = "parso" version = "0.8.3" description = "A Python Parser" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -875,7 +861,6 @@ testing = ["docopt", "pytest (<6.0.0)"] 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 = [ @@ -887,7 +872,6 @@ files = [ name = "pexpect" version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." -category = "dev" optional = false python-versions = "*" files = [ @@ -902,7 +886,6 @@ ptyprocess = ">=0.5" name = "pickleshare" version = "0.7.5" description = "Tiny 'shelve'-like database with concurrency support" -category = "dev" optional = false python-versions = "*" files = [ @@ -914,7 +897,6 @@ files = [ name = "platformdirs" version = "3.1.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 = [ @@ -930,7 +912,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytes name = "pluggy" version = "1.0.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -946,7 +927,6 @@ testing = ["pytest", "pytest-benchmark"] name = "prompt-toolkit" version = "3.0.38" description = "Library for building powerful interactive command lines in Python" -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -961,7 +941,6 @@ wcwidth = "*" name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -973,7 +952,6 @@ files = [ name = "pure-eval" version = "0.2.2" description = "Safely evaluate AST nodes without side effects" -category = "dev" optional = false python-versions = "*" files = [ @@ -986,62 +964,145 @@ tests = ["pytest"] [[package]] name = "pydantic" -version = "1.10.7" -description = "Data validation and settings management using python type hints" -category = "main" +version = "2.3.0" +description = "Data validation using Python type hints" 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-2.3.0-py3-none-any.whl", hash = "sha256:45b5e446c6dfaad9444819a293b921a40e1db1aa61ea08aede0522529ce90e81"}, + {file = "pydantic-2.3.0.tar.gz", hash = "sha256:1607cc106602284cd4a00882986570472f193fde9cb1259bceeaedb26aa79a6d"}, ] [package.dependencies] -typing-extensions = ">=4.2.0" +annotated-types = ">=0.4.0" +pydantic-core = "2.6.3" +typing-extensions = ">=4.6.1" [package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.6.3" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1a0ddaa723c48af27d19f27f1c73bdc615c73686d763388c8683fe34ae777bad"}, + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5cfde4fab34dd1e3a3f7f3db38182ab6c95e4ea91cf322242ee0be5c2f7e3d2f"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5493a7027bfc6b108e17c3383959485087d5942e87eb62bbac69829eae9bc1f7"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84e87c16f582f5c753b7f39a71bd6647255512191be2d2dbf49458c4ef024588"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:522a9c4a4d1924facce7270c84b5134c5cabcb01513213662a2e89cf28c1d309"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaafc776e5edc72b3cad1ccedb5fd869cc5c9a591f1213aa9eba31a781be9ac1"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a750a83b2728299ca12e003d73d1264ad0440f60f4fc9cee54acc489249b728"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e8b374ef41ad5c461efb7a140ce4730661aadf85958b5c6a3e9cf4e040ff4bb"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b594b64e8568cf09ee5c9501ede37066b9fc41d83d58f55b9952e32141256acd"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a20c533cb80466c1d42a43a4521669ccad7cf2967830ac62c2c2f9cece63e7e"}, + {file = "pydantic_core-2.6.3-cp310-none-win32.whl", hash = "sha256:04fe5c0a43dec39aedba0ec9579001061d4653a9b53a1366b113aca4a3c05ca7"}, + {file = "pydantic_core-2.6.3-cp310-none-win_amd64.whl", hash = "sha256:6bf7d610ac8f0065a286002a23bcce241ea8248c71988bda538edcc90e0c39ad"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bcc1ad776fffe25ea5c187a028991c031a00ff92d012ca1cc4714087e575973"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:df14f6332834444b4a37685810216cc8fe1fe91f447332cd56294c984ecbff1c"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b7486d85293f7f0bbc39b34e1d8aa26210b450bbd3d245ec3d732864009819"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a892b5b1871b301ce20d40b037ffbe33d1407a39639c2b05356acfef5536d26a"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:883daa467865e5766931e07eb20f3e8152324f0adf52658f4d302242c12e2c32"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4eb77df2964b64ba190eee00b2312a1fd7a862af8918ec70fc2d6308f76ac64"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce8c84051fa292a5dc54018a40e2a1926fd17980a9422c973e3ebea017aa8da"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22134a4453bd59b7d1e895c455fe277af9d9d9fbbcb9dc3f4a97b8693e7e2c9b"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:02e1c385095efbd997311d85c6021d32369675c09bcbfff3b69d84e59dc103f6"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d79f1f2f7ebdb9b741296b69049ff44aedd95976bfee38eb4848820628a99b50"}, + {file = "pydantic_core-2.6.3-cp311-none-win32.whl", hash = "sha256:430ddd965ffd068dd70ef4e4d74f2c489c3a313adc28e829dd7262cc0d2dd1e8"}, + {file = "pydantic_core-2.6.3-cp311-none-win_amd64.whl", hash = "sha256:84f8bb34fe76c68c9d96b77c60cef093f5e660ef8e43a6cbfcd991017d375950"}, + {file = "pydantic_core-2.6.3-cp311-none-win_arm64.whl", hash = "sha256:5a2a3c9ef904dcdadb550eedf3291ec3f229431b0084666e2c2aa8ff99a103a2"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8421cf496e746cf8d6b677502ed9a0d1e4e956586cd8b221e1312e0841c002d5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bb128c30cf1df0ab78166ded1ecf876620fb9aac84d2413e8ea1594b588c735d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37a822f630712817b6ecc09ccc378192ef5ff12e2c9bae97eb5968a6cdf3b862"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:240a015102a0c0cc8114f1cba6444499a8a4d0333e178bc504a5c2196defd456"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f90e5e3afb11268628c89f378f7a1ea3f2fe502a28af4192e30a6cdea1e7d5e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:340e96c08de1069f3d022a85c2a8c63529fd88709468373b418f4cf2c949fb0e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1480fa4682e8202b560dcdc9eeec1005f62a15742b813c88cdc01d44e85308e5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f14546403c2a1d11a130b537dda28f07eb6c1805a43dae4617448074fd49c282"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a87c54e72aa2ef30189dc74427421e074ab4561cf2bf314589f6af5b37f45e6d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f93255b3e4d64785554e544c1c76cd32f4a354fa79e2eeca5d16ac2e7fdd57aa"}, + {file = "pydantic_core-2.6.3-cp312-none-win32.whl", hash = "sha256:f70dc00a91311a1aea124e5f64569ea44c011b58433981313202c46bccbec0e1"}, + {file = "pydantic_core-2.6.3-cp312-none-win_amd64.whl", hash = "sha256:23470a23614c701b37252618e7851e595060a96a23016f9a084f3f92f5ed5881"}, + {file = "pydantic_core-2.6.3-cp312-none-win_arm64.whl", hash = "sha256:1ac1750df1b4339b543531ce793b8fd5c16660a95d13aecaab26b44ce11775e9"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:a53e3195f134bde03620d87a7e2b2f2046e0e5a8195e66d0f244d6d5b2f6d31b"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:f2969e8f72c6236c51f91fbb79c33821d12a811e2a94b7aa59c65f8dbdfad34a"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:672174480a85386dd2e681cadd7d951471ad0bb028ed744c895f11f9d51b9ebe"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:002d0ea50e17ed982c2d65b480bd975fc41086a5a2f9c924ef8fc54419d1dea3"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ccc13afee44b9006a73d2046068d4df96dc5b333bf3509d9a06d1b42db6d8bf"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:439a0de139556745ae53f9cc9668c6c2053444af940d3ef3ecad95b079bc9987"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d63b7545d489422d417a0cae6f9898618669608750fc5e62156957e609e728a5"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b44c42edc07a50a081672e25dfe6022554b47f91e793066a7b601ca290f71e42"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1c721bfc575d57305dd922e6a40a8fe3f762905851d694245807a351ad255c58"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5e4a2cf8c4543f37f5dc881de6c190de08096c53986381daebb56a355be5dfe6"}, + {file = "pydantic_core-2.6.3-cp37-none-win32.whl", hash = "sha256:d9b4916b21931b08096efed090327f8fe78e09ae8f5ad44e07f5c72a7eedb51b"}, + {file = "pydantic_core-2.6.3-cp37-none-win_amd64.whl", hash = "sha256:a8acc9dedd304da161eb071cc7ff1326aa5b66aadec9622b2574ad3ffe225525"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:5e9c068f36b9f396399d43bfb6defd4cc99c36215f6ff33ac8b9c14ba15bdf6b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e61eae9b31799c32c5f9b7be906be3380e699e74b2db26c227c50a5fc7988698"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85463560c67fc65cd86153a4975d0b720b6d7725cf7ee0b2d291288433fc21b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9616567800bdc83ce136e5847d41008a1d602213d024207b0ff6cab6753fe645"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e9b65a55bbabda7fccd3500192a79f6e474d8d36e78d1685496aad5f9dbd92c"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f468d520f47807d1eb5d27648393519655eadc578d5dd862d06873cce04c4d1b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9680dd23055dd874173a3a63a44e7f5a13885a4cfd7e84814be71be24fba83db"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a718d56c4d55efcfc63f680f207c9f19c8376e5a8a67773535e6f7e80e93170"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8ecbac050856eb6c3046dea655b39216597e373aa8e50e134c0e202f9c47efec"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:788be9844a6e5c4612b74512a76b2153f1877cd845410d756841f6c3420230eb"}, + {file = "pydantic_core-2.6.3-cp38-none-win32.whl", hash = "sha256:07a1aec07333bf5adebd8264047d3dc518563d92aca6f2f5b36f505132399efc"}, + {file = "pydantic_core-2.6.3-cp38-none-win_amd64.whl", hash = "sha256:621afe25cc2b3c4ba05fff53525156d5100eb35c6e5a7cf31d66cc9e1963e378"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:813aab5bfb19c98ae370952b6f7190f1e28e565909bfc219a0909db168783465"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:50555ba3cb58f9861b7a48c493636b996a617db1a72c18da4d7f16d7b1b9952b"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e20f8baedd7d987bd3f8005c146e6bcbda7cdeefc36fad50c66adb2dd2da48"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b0a5d7edb76c1c57b95df719af703e796fc8e796447a1da939f97bfa8a918d60"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f06e21ad0b504658a3a9edd3d8530e8cea5723f6ea5d280e8db8efc625b47e49"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea053cefa008fda40f92aab937fb9f183cf8752e41dbc7bc68917884454c6362"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:171a4718860790f66d6c2eda1d95dd1edf64f864d2e9f9115840840cf5b5713f"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ed7ceca6aba5331ece96c0e328cd52f0dcf942b8895a1ed2642de50800b79d3"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:acafc4368b289a9f291e204d2c4c75908557d4f36bd3ae937914d4529bf62a76"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1aa712ba150d5105814e53cb141412217146fedc22621e9acff9236d77d2a5ef"}, + {file = "pydantic_core-2.6.3-cp39-none-win32.whl", hash = "sha256:44b4f937b992394a2e81a5c5ce716f3dcc1237281e81b80c748b2da6dd5cf29a"}, + {file = "pydantic_core-2.6.3-cp39-none-win_amd64.whl", hash = "sha256:9b33bf9658cb29ac1a517c11e865112316d09687d767d7a0e4a63d5c640d1b17"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d7050899026e708fb185e174c63ebc2c4ee7a0c17b0a96ebc50e1f76a231c057"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99faba727727b2e59129c59542284efebbddade4f0ae6a29c8b8d3e1f437beb7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fa159b902d22b283b680ef52b532b29554ea2a7fc39bf354064751369e9dbd7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:046af9cfb5384f3684eeb3f58a48698ddab8dd870b4b3f67f825353a14441418"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:930bfe73e665ebce3f0da2c6d64455098aaa67e1a00323c74dc752627879fc67"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:85cc4d105747d2aa3c5cf3e37dac50141bff779545ba59a095f4a96b0a460e70"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b25afe9d5c4f60dcbbe2b277a79be114e2e65a16598db8abee2a2dcde24f162b"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e49ce7dc9f925e1fb010fc3d555250139df61fa6e5a0a95ce356329602c11ea9"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2dd50d6a1aef0426a1d0199190c6c43ec89812b1f409e7fe44cb0fbf6dfa733c"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6595b0d8c8711e8e1dc389d52648b923b809f68ac1c6f0baa525c6440aa0daa"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ef724a059396751aef71e847178d66ad7fc3fc969a1a40c29f5aac1aa5f8784"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3c8945a105f1589ce8a693753b908815e0748f6279959a4530f6742e1994dcb6"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c8c6660089a25d45333cb9db56bb9e347241a6d7509838dbbd1931d0e19dbc7f"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:692b4ff5c4e828a38716cfa92667661a39886e71136c97b7dac26edef18767f7"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:f1a5d8f18877474c80b7711d870db0eeef9442691fcdb00adabfc97e183ee0b0"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3796a6152c545339d3b1652183e786df648ecdf7c4f9347e1d30e6750907f5bb"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b962700962f6e7a6bd77e5f37320cabac24b4c0f76afeac05e9f93cf0c620014"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56ea80269077003eaa59723bac1d8bacd2cd15ae30456f2890811efc1e3d4413"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c0ebbebae71ed1e385f7dfd9b74c1cff09fed24a6df43d326dd7f12339ec34"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:252851b38bad3bfda47b104ffd077d4f9604a10cb06fe09d020016a25107bf98"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6656a0ae383d8cd7cc94e91de4e526407b3726049ce8d7939049cbfa426518c8"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9140ded382a5b04a1c030b593ed9bf3088243a0a8b7fa9f071a5736498c5483"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d38bbcef58220f9c81e42c255ef0bf99735d8f11edef69ab0b499da77105158a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c9d469204abcca28926cbc28ce98f28e50e488767b084fb3fbdf21af11d3de26"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48c1ed8b02ffea4d5c9c220eda27af02b8149fe58526359b3c07eb391cb353a2"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2b1bfed698fa410ab81982f681f5b1996d3d994ae8073286515ac4d165c2e7"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf9d42a71a4d7a7c1f14f629e5c30eac451a6fc81827d2beefd57d014c006c4a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4292ca56751aebbe63a84bbfc3b5717abb09b14d4b4442cc43fd7c49a1529efd"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7dc2ce039c7290b4ef64334ec7e6ca6494de6eecc81e21cb4f73b9b39991408c"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:615a31b1629e12445c0e9fc8339b41aaa6cc60bd53bf802d5fe3d2c0cda2ae8d"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1fa1f6312fb84e8c281f32b39affe81984ccd484da6e9d65b3d18c202c666149"}, + {file = "pydantic_core-2.6.3.tar.gz", hash = "sha256:1508f37ba9e3ddc0189e6ff4e2228bd2d3c3a4641cbe8c07177162f76ed696c7"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pygments" version = "2.14.0" description = "Pygments is a syntax highlighting package written in Python." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1056,7 +1117,6 @@ plugins = ["importlib-metadata"] name = "pymongo" version = "4.3.3" description = "Python driver for MongoDB " -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1151,7 +1211,6 @@ zstd = ["zstandard"] name = "pytest" version = "7.2.2" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1175,7 +1234,6 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. name = "python-dotenv" version = "0.21.1" description = "Read key-value pairs from a .env file and set them as environment variables" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1190,7 +1248,6 @@ cli = ["click (>=5.0)"] name = "pytz" version = "2022.7.1" description = "World timezone definitions, modern and historical" -category = "main" optional = false python-versions = "*" files = [ @@ -1202,7 +1259,6 @@ files = [ name = "pyyaml" version = "6.0" description = "YAML parser and emitter for Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1252,7 +1308,6 @@ files = [ name = "rich" version = "12.6.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -category = "main" optional = false python-versions = ">=3.6.3,<4.0.0" files = [ @@ -1271,7 +1326,6 @@ jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1283,7 +1337,6 @@ files = [ name = "stack-data" version = "0.6.2" description = "Extract data from python stack frames and tracebacks for informative displays" -category = "dev" optional = false python-versions = "*" files = [ @@ -1303,7 +1356,6 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" -category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1315,7 +1367,6 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1327,7 +1378,6 @@ files = [ name = "traitlets" version = "5.9.0" description = "Traitlets Python configuration system" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1341,21 +1391,19 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] [[package]] name = "typing-extensions" -version = "4.5.0" +version = "4.7.1" 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.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, ] [[package]] name = "wcwidth" version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -1367,7 +1415,6 @@ files = [ name = "yarl" version = "1.8.2" description = "Yet another URL library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1453,5 +1500,5 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" -python-versions = "^3.10" -content-hash = "4d0aa596f6a594ab85cbff2e97483cc0de6c659b4cb1b8d99e5fa322e8ac9365" +python-versions = ">=3.10,<4" +content-hash = "40bd2055155a2ec2acef066cd9cf5c3a5d6599a16157a60e5e2be50746b35554" diff --git a/pyproject.toml b/pyproject.toml index 1f63e82..fca0b7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,21 +1,21 @@ [tool.poetry] name = "jarvis-core" -version = "0.17.0" +version = "0.18.0" description = "JARVIS core" authors = ["Zevaryx "] [tool.poetry.dependencies] python = ">=3.10,<4" -orjson = {version = "^3.6.6"} +orjson = { version = "^3.6.6" } motor = "^3.1.1" -PyYAML = {version = "^6.0"} +PyYAML = { version = "^6.0" } pytz = "^2022.1" aiohttp = "^3.8.1" rich = "^12.3.0" nanoid = "^2.0.0" python-dotenv = "^0.21.0" beanie = "^1.17.0" -pydantic = "^1.10.7" +pydantic = ">=2.3.0,<3" [tool.poetry.dev-dependencies] pytest = "^7.1" From 7ce36505dbc2fa8feb9ad4eaa3d0529a61859d56 Mon Sep 17 00:00:00 2001 From: zevaryx Date: Sun, 27 Aug 2023 16:57:24 -0600 Subject: [PATCH 11/12] Fix missing phishlist import --- jarvis_core/db/models/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jarvis_core/db/models/__init__.py b/jarvis_core/db/models/__init__.py index 5507aa2..8ed076a 100644 --- a/jarvis_core/db/models/__init__.py +++ b/jarvis_core/db/models/__init__.py @@ -27,6 +27,7 @@ __all__ = [ "Note", "Pin", "Pinboard", + "Phishlist", "Purge", "Reminder", "Rolegiver", @@ -257,6 +258,7 @@ all_models = [ Mute, Pin, Pinboard, + Phishlist, Purge, Reminder, Rolegiver, From 5b0a8cc301be8a4c6a7e1b1e9b3083d1d21918d4 Mon Sep 17 00:00:00 2001 From: zevaryx Date: Sun, 27 Aug 2023 22:43:11 -0600 Subject: [PATCH 12/12] Rolegiver groups --- jarvis_core/db/models/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/jarvis_core/db/models/__init__.py b/jarvis_core/db/models/__init__.py index 8ed076a..b7ebca3 100644 --- a/jarvis_core/db/models/__init__.py +++ b/jarvis_core/db/models/__init__.py @@ -151,6 +151,7 @@ class Rolegiver(Document): guild: int roles: list[int] + group: Optional[str] = None class Bypass(BaseModel):