uhhhhhhhh lots of stuff
This commit is contained in:
parent
57beb9c43b
commit
bd3a1760f9
27 changed files with 1674 additions and 0 deletions
0
masto_ld/__init__.py
Normal file
0
masto_ld/__init__.py
Normal file
0
masto_ld/bots/__init__.py
Normal file
0
masto_ld/bots/__init__.py
Normal file
184
masto_ld/bots/mastodon.py
Normal file
184
masto_ld/bots/mastodon.py
Normal file
|
@ -0,0 +1,184 @@
|
|||
import pdb
|
||||
from typing import Optional
|
||||
from urllib.parse import urlsplit
|
||||
from masto_ld.config import Config
|
||||
from masto_ld.models.models import Account, List
|
||||
from masto_ld.models.post import Status
|
||||
from masto_ld.logger import init_logger
|
||||
from masto_ld.patterns.tag import Namespaced_Tag
|
||||
from masto_ld.interfaces.smw import SMW
|
||||
from masto_ld.interfaces.mediawiki import Wiki
|
||||
|
||||
import pypandoc
|
||||
|
||||
from mastodon import Mastodon, StreamListener
|
||||
|
||||
class UserListener(StreamListener):
|
||||
"""
|
||||
Listener for all events that are in our feed
|
||||
"""
|
||||
def __init__(self, client:Mastodon, config:Config):
|
||||
self.client = client
|
||||
self.config = config
|
||||
self.logger = init_logger(name="user-listener", basedir=config.LOGDIR)
|
||||
|
||||
def on_update(self, status):
|
||||
status = Status(**status)
|
||||
tag = Namespaced_Tag.from_html(status.content)
|
||||
if tag is not None:
|
||||
self.handle_tagged_post(status, tag)
|
||||
|
||||
pdb.set_trace()
|
||||
|
||||
def on_notification(self, notification):
|
||||
pdb.set_trace()
|
||||
if notification.get('type', '') == 'follow':
|
||||
self.logger.debug(f'following back {notification["account"]["url"]}')
|
||||
self.follow_back(notification)
|
||||
|
||||
|
||||
def follow_back(self, notification):
|
||||
self.client.account_follow(notification['account']['id'])
|
||||
self.logger.debug(f'account followed! {notification["account"]["url"]} with id {notification["account"]["id"]}')
|
||||
|
||||
def handle_tagged_post(self, status:Status, tag:Namespaced_Tag):
|
||||
# FIXME: This is the worst way of doing this
|
||||
|
||||
# resolve the name of the tag
|
||||
# find the right field
|
||||
field = [f for f in status.account.fields if f.name == tag.tags[0]]
|
||||
if len(field) == 0:
|
||||
raise ValueError('No namespace found!')
|
||||
else:
|
||||
field = field[0]
|
||||
|
||||
# get the tags from that field
|
||||
smw = SMW(self.config.WIKI_URL)
|
||||
pagename = urlsplit(field.url).path.lstrip('/')
|
||||
wiki_tags = smw.tags(pagename)
|
||||
|
||||
# find the long name of the tag
|
||||
longname = [t for t in wiki_tags if t[0] == tag.tags[1]]
|
||||
if len(longname) == 0:
|
||||
raise ValueError('No matching tag found!')
|
||||
else:
|
||||
longname = longname[0]
|
||||
|
||||
# format our freaking page IN PLACE LIKE AN ANIMAL
|
||||
page_content = (
|
||||
"{{Thread\n",
|
||||
f"|About={longname}\n",
|
||||
f"|URL={status.url}\n",
|
||||
"}}\n\n"
|
||||
)
|
||||
|
||||
page_content += pypandoc.convert_text(status.content, 'mediawiki-raw_html', format='html')
|
||||
|
||||
page_name = status.soup.find('h1')
|
||||
if page_name is None:
|
||||
raise ValueError('No Header found!')
|
||||
page_
|
||||
|
||||
|
||||
wiki = Wiki(self.config, log_dir=self.config.LOGDIR)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ListListener(StreamListener):
|
||||
"""
|
||||
Listener for events from users on our follows list
|
||||
"""
|
||||
def __init__(self, client: Mastodon, config:Optional[Config]=None):
|
||||
super(Listener, self).__init__()
|
||||
self.client = client
|
||||
|
||||
if config is None:
|
||||
config = Config()
|
||||
self.config = config
|
||||
|
||||
self.logger = init_logger('mastogit_bot-stream', basedir=self.config.LOGDIR)
|
||||
|
||||
self.repo = Repo(path=config.GIT_REPO)
|
||||
|
||||
|
||||
|
||||
def on_update(self, status:dict):
|
||||
status = Status(**status)
|
||||
if status.visibility in ('private', 'direct'):
|
||||
# not xposting dms
|
||||
self.logger.info('Not xposting private messages')
|
||||
return
|
||||
|
||||
post = Post.from_status(status)
|
||||
if post.text.startswith('xpost'):
|
||||
self.logger.info('Not xposting an xpost')
|
||||
return
|
||||
|
||||
success = self.repo.post(post.format_commit())
|
||||
if success:
|
||||
self.logger.info('Posted to git!')
|
||||
else:
|
||||
self.logger.exception('Failed to post to git!')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Bot:
|
||||
def __init__(self, config:Optional[Config]=None, post_length=500):
|
||||
self._me = None # type: Optional[Account]
|
||||
# self._me_list = None # type: Optional[List]
|
||||
|
||||
if config is None:
|
||||
config = Config()
|
||||
|
||||
self.config = config
|
||||
self.config.LOGDIR.mkdir(exist_ok=True)
|
||||
# self.post_length = post_length
|
||||
self.logger = init_logger('mastogit_bot', basedir=self.config.LOGDIR)
|
||||
|
||||
self.client = Mastodon(
|
||||
access_token=self.config.MASTO_TOKEN,
|
||||
api_base_url=self.config.MASTO_URL
|
||||
)
|
||||
|
||||
def init_stream(self, run_async:bool=True):
|
||||
# Listen to a stream consisting of just us.
|
||||
listener = UserListener(self.client, self.config)
|
||||
self.logger.info('Initializing streaming')
|
||||
self.client.stream_user(
|
||||
listener = listener,
|
||||
run_async=run_async
|
||||
)
|
||||
|
||||
def post(self, post:str):
|
||||
|
||||
self.client.status_post(post)
|
||||
self.logger.info(f"Posted:\n{post}")
|
||||
|
||||
@property
|
||||
def me(self) -> Account:
|
||||
if self._me is None:
|
||||
self._me = Account(**self.client.me())
|
||||
return self._me
|
||||
|
||||
def _make_me_list(self) -> List:
|
||||
me_list = List(**self.client.list_create('me'))
|
||||
self.client.list_accounts_add(me_list.id, [self.me.id])
|
||||
self.logger.info('Created list with just me in it!')
|
||||
return me_list
|
||||
|
||||
# @property
|
||||
# def me_list(self) -> List:
|
||||
# if self._me_list is None:
|
||||
# lists = self.client.lists()
|
||||
# me_list = [l for l in lists if l.get('title', '') == 'me']
|
||||
# if len(me_list)>0:
|
||||
# self._me_list = List(**me_list[0])
|
||||
# else:
|
||||
# self._me_list = self._make_me_list()
|
||||
# return self._me_list
|
16
masto_ld/config.py
Normal file
16
masto_ld/config.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from pathlib import Path
|
||||
from pydantic import BaseSettings, AnyHttpUrl
|
||||
|
||||
class Config(BaseSettings):
|
||||
MASTO_URL:AnyHttpUrl
|
||||
MASTO_TOKEN:str
|
||||
WIKI_URL:AnyHttpUrl
|
||||
WIKI_USER:str
|
||||
WIKI_PASSWORD:str
|
||||
LOGDIR:Path=Path().home() / '.mastold'
|
||||
|
||||
class Config:
|
||||
env_file = '.env'
|
||||
env_file_encoding = 'utf-8'
|
||||
env_prefix = "MASTOLD_"
|
||||
|
6
masto_ld/creds.py
Normal file
6
masto_ld/creds.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class Mediawiki_Creds:
|
||||
user:str
|
||||
password:str
|
0
masto_ld/formats/__init__.py
Normal file
0
masto_ld/formats/__init__.py
Normal file
17
masto_ld/formats/wiki.py
Normal file
17
masto_ld/formats/wiki.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
"""
|
||||
Helper functions for dealing with wiki syntax as well as format
|
||||
output posts triggered by :class:`.action.WikiLink`
|
||||
"""
|
||||
from dataclasses import dataclass
|
||||
import wikitextparser as wtp
|
||||
|
||||
@dataclass
|
||||
class WikiPage:
|
||||
title:str
|
||||
source:str
|
||||
content:wtp.WikiText
|
||||
|
||||
@classmethod
|
||||
def from_source(self, title, source) -> 'WikiPage':
|
||||
content = wtp.parse(source)
|
||||
return WikiPage(title, source, content)
|
0
masto_ld/interfaces/__init__.py
Normal file
0
masto_ld/interfaces/__init__.py
Normal file
150
masto_ld/interfaces/mediawiki.py
Normal file
150
masto_ld/interfaces/mediawiki.py
Normal file
|
@ -0,0 +1,150 @@
|
|||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from urllib.parse import urljoin
|
||||
|
||||
import requests
|
||||
from masto_ld.creds import Mediawiki_Creds
|
||||
from masto_ld.formats.wiki import WikiPage
|
||||
from masto_ld.logger import init_logger
|
||||
from masto_ld.config import Config
|
||||
|
||||
|
||||
class Wiki:
|
||||
def __init__(self, config:Config,
|
||||
api_suffix:str="/api.php", index_page="Discord Messages",
|
||||
log_dir:Path=Path('/var/www/wikibot')):
|
||||
self.url = config.WIKI_URL
|
||||
self.api_url = urljoin(self.url, api_suffix)
|
||||
self.creds = Mediawiki_Creds(config.WIKI_USER, config.WIKI_PASSWORD)
|
||||
self.sess = None
|
||||
self.index_page = index_page
|
||||
self.logger = init_logger('wiki_interface', basedir=log_dir)
|
||||
self.login(self.creds)
|
||||
|
||||
def login(self, creds:Mediawiki_Creds):
|
||||
# get token to log in
|
||||
sess = requests.Session()
|
||||
|
||||
login_token = sess.get(
|
||||
self.api_url,
|
||||
params={
|
||||
"action":"query",
|
||||
"meta":"tokens",
|
||||
"type":"login",
|
||||
"format":"json"
|
||||
},
|
||||
verify=False
|
||||
).json()['query']['tokens']['logintoken']
|
||||
|
||||
|
||||
login_result = sess.post(
|
||||
self.api_url,
|
||||
data = {
|
||||
"action":"login",
|
||||
"lgname":creds.user,
|
||||
"lgpassword":creds.password,
|
||||
"lgtoken": login_token,
|
||||
"format": "json"
|
||||
},
|
||||
verify=False
|
||||
)
|
||||
assert login_result.json()['login']['result'] == "Success"
|
||||
self.sess = sess
|
||||
|
||||
def get_page(self, page:str) -> Optional[WikiPage]:
|
||||
|
||||
content = self.sess.get(
|
||||
self.api_url,
|
||||
params={
|
||||
'action':'parse',
|
||||
'page': page,
|
||||
'prop': 'wikitext',
|
||||
'formatversion':'2',
|
||||
'format':'json'
|
||||
}
|
||||
).json()
|
||||
|
||||
if content.get('error', {}).get('code', '') == 'missingtitle':
|
||||
# Page does not exist!
|
||||
self.logger.debug("Page does not exist")
|
||||
return None
|
||||
|
||||
self.logger.debug(f"Got Page content:")
|
||||
self.logger.debug(content)
|
||||
return WikiPage.from_source(title=content['parse']['title'], source=content['parse']['wikitext'])
|
||||
|
||||
def new_page(self, page, text):
|
||||
token = self.sess.get(
|
||||
self.api_url,
|
||||
params={
|
||||
"action": "query",
|
||||
"meta": "tokens",
|
||||
"format": "json"
|
||||
},
|
||||
verify=False
|
||||
).json()['query']['tokens']['csrftoken']
|
||||
|
||||
result = self.sess.post(
|
||||
self.api_url,
|
||||
data={
|
||||
"action": "edit",
|
||||
"title": page,
|
||||
"appendtext": text,
|
||||
"format": "json",
|
||||
"token": token
|
||||
}
|
||||
)
|
||||
|
||||
def insert_text(self, page, section, text):
|
||||
|
||||
# TODO: Move finding section IDs into the page class!
|
||||
page_text = self.get_page(page)
|
||||
matching_section = -1
|
||||
if page_text is not None:
|
||||
# find section number
|
||||
sections = page_text.content.get_sections()
|
||||
|
||||
for i, page_section in enumerate(sections):
|
||||
if page_section.title is not None and page_section.title.strip().lower() == section.lower():
|
||||
matching_section = i
|
||||
break
|
||||
|
||||
|
||||
token = self.sess.get(
|
||||
self.api_url,
|
||||
params={
|
||||
"action": "query",
|
||||
"meta": "tokens",
|
||||
"format": "json"
|
||||
},
|
||||
verify=False
|
||||
).json()['query']['tokens']['csrftoken']
|
||||
|
||||
if matching_section >= 0:
|
||||
print(f'found matching section {matching_section}')
|
||||
result = self.sess.post(
|
||||
self.api_url,
|
||||
data={
|
||||
"action":"edit",
|
||||
"title":page,
|
||||
"section":str(matching_section),
|
||||
"appendtext":text,
|
||||
"format":"json",
|
||||
"token":token
|
||||
}
|
||||
)
|
||||
else:
|
||||
self.logger.debug('making new section')
|
||||
result = self.sess.post(
|
||||
self.api_url,
|
||||
data={
|
||||
"action":"edit",
|
||||
"title":page,
|
||||
"section":"new",
|
||||
"sectiontitle":section,
|
||||
"appendtext":text,
|
||||
"format":"json",
|
||||
"token":token
|
||||
}
|
||||
)
|
||||
return result
|
127
masto_ld/interfaces/smw.py
Normal file
127
masto_ld/interfaces/smw.py
Normal file
|
@ -0,0 +1,127 @@
|
|||
"""
|
||||
Adapted from https://github.com/auto-pi-lot/autopilot/blob/main/autopilot/utils/wiki.py
|
||||
|
||||
So sort of shit.
|
||||
|
||||
"""
|
||||
|
||||
import requests
|
||||
from typing import List, Union
|
||||
from urllib.parse import urljoin
|
||||
|
||||
class SMW:
|
||||
|
||||
def __init__(self, url:str, api_suffix="api.php"):
|
||||
self.url = url
|
||||
self.api_url = urljoin(self.url, api_suffix)
|
||||
|
||||
def tags(self, page:str):
|
||||
"""SUPER MEGA HACK DO NOT READ"""
|
||||
res = self.ask(filters="[["+page+"]]", properties='Tag')
|
||||
tags = res[0]['Tag']
|
||||
clean_tags = []
|
||||
for tag in tags:
|
||||
shortname = tag['ShortName']['item'][0]
|
||||
longurl = tag['LongName']['item'][0]['fulltext']
|
||||
clean_tags = (shortname, longurl)
|
||||
return clean_tags
|
||||
|
||||
|
||||
def ask(self,
|
||||
filters:Union[List[str],str],
|
||||
properties:Union[None,List[str],str]=None,
|
||||
clean:bool=True
|
||||
) -> List[dict]:
|
||||
"""
|
||||
|
||||
Args:
|
||||
filters (list, str): A list of strings or a single string of semantic
|
||||
mediawiki formatted property filters, eg ``"[[Category:Hardware]]"``
|
||||
or ``"[[Has Contributor::sneakers-the-rat]]"``. Refer to the
|
||||
`semantic mediawiki documentation <https://www.semantic-mediawiki.org/wiki/Help:Selecting_pages>`_
|
||||
for more information on syntax
|
||||
properties (None, list, str): Properties to return from filtered pages,
|
||||
see the `available properties <https://wiki.auto-pi-lot.com/index.php/Special:Properties>`_
|
||||
on the wiki and the `semantic mediawiki documentation <https://www.semantic-mediawiki.org/wiki/Help:Selecting_pages>`_
|
||||
for more information on syntax. If ``None`` (default), just return
|
||||
the names of the pages
|
||||
full_url (bool): If ``True`` (default), prepend ``f'{WIKI_URL}api.php?action=ask&query='``
|
||||
to the returned string to make it `ready for an API call <https://www.semantic-mediawiki.org/wiki/Help:API:ask>`_
|
||||
|
||||
"""
|
||||
query_str = self._make_ask_string(filters, properties, full_url=True)
|
||||
result = requests.get(query_str)
|
||||
if clean:
|
||||
unnested = []
|
||||
for entry in result.json()['query']['results']:
|
||||
entry_name = list(entry.keys())[0]
|
||||
nested_entry = entry[entry_name]
|
||||
unnest_entry = _clean_smw_result(nested_entry)
|
||||
unnested.append(unnest_entry)
|
||||
return unnested
|
||||
else:
|
||||
return result.json()
|
||||
|
||||
|
||||
def _make_ask_string(self,
|
||||
filters: Union[List[str], str],
|
||||
properties: Union[None, List[str], str] = None,
|
||||
full_url: bool = True) -> str:
|
||||
"""
|
||||
Create a query string to request semantic information from a semantic wiki
|
||||
|
||||
Returns:
|
||||
str: the formatted query string
|
||||
"""
|
||||
# combine the components, separated by pipes or pip question marks as the case may be
|
||||
if isinstance(filters, str):
|
||||
filters = [filters]
|
||||
|
||||
if len(filters) == 0:
|
||||
raise ValueError(f'You need to provide at least one filter! Cant get the whole wiki!')
|
||||
|
||||
query_str = "|".join(filters)
|
||||
|
||||
if isinstance(properties, str):
|
||||
properties = [properties]
|
||||
elif properties is None:
|
||||
properties = []
|
||||
|
||||
if len(properties) > 0:
|
||||
# double join with ?| so it goes between
|
||||
# all the properties *and* between filters and
|
||||
query_str = "|?".join((
|
||||
query_str,
|
||||
"|?".join(properties)
|
||||
))
|
||||
|
||||
# add api call boilerplate and URI-encode
|
||||
query_str = requests.utils.quote(query_str) + "&format=json&api_version=3"
|
||||
|
||||
if full_url:
|
||||
return f"{self.api_url}?action=ask&query=" + query_str
|
||||
else:
|
||||
return query_str
|
||||
|
||||
def _clean_smw_result(nested_entry:dict) -> dict:
|
||||
# unnest entries that are [[Has type::page]] and thus have extra metadata
|
||||
unnest_entry = {}
|
||||
printouts = nested_entry.get('printouts', {})
|
||||
if len(printouts)>0:
|
||||
for k, v in printouts.items():
|
||||
if isinstance(v, list) and len(v) > 1:
|
||||
unnest_entry[k] = []
|
||||
for subv in v:
|
||||
if isinstance(subv, dict) and 'fulltext' in subv.keys():
|
||||
subv = subv['fulltext']
|
||||
unnest_entry[k].append(subv)
|
||||
elif isinstance(v, list) and len(v) == 1:
|
||||
unnest_entry[k] = v[0]
|
||||
if isinstance(unnest_entry[k], dict) and 'fulltext' in unnest_entry[k].keys():
|
||||
unnest_entry[k] = unnest_entry[k]['fulltext']
|
||||
else:
|
||||
unnest_entry[k] = v
|
||||
|
||||
unnest_entry['name'] = nested_entry['fulltext']
|
||||
unnest_entry['url'] = nested_entry['fullurl']
|
||||
return unnest_entry
|
56
masto_ld/logger.py
Normal file
56
masto_ld/logger.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
import logging
|
||||
from rich.logging import RichHandler
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import typing
|
||||
from typing import Optional, Union, Tuple, List, Dict, Literal
|
||||
from logging.handlers import RotatingFileHandler
|
||||
|
||||
def init_logger(
|
||||
name:Optional[str]=None,
|
||||
basedir:Optional[Path]=None,
|
||||
loglevel:str='DEBUG',
|
||||
loglevel_disk:Optional[str]='DEBUG'
|
||||
):
|
||||
if name is None:
|
||||
name = 'masto_ld'
|
||||
else:
|
||||
if not name.startswith('masto_ld'):
|
||||
name = '.'.join(['masto_ld', name])
|
||||
|
||||
if loglevel_disk is None:
|
||||
loglevel_disk = loglevel
|
||||
|
||||
logger = logging.getLogger(name)
|
||||
logger.setLevel(loglevel)
|
||||
|
||||
|
||||
if basedir is not None:
|
||||
logger.addHandler(_file_handler(basedir, name, loglevel_disk))
|
||||
|
||||
logger.addHandler(_rich_handler())
|
||||
return logger
|
||||
|
||||
|
||||
def _file_handler(basedir:Path, name:str, loglevel:str="DEBUG") -> RotatingFileHandler:
|
||||
filename = Path(basedir) / '.'.join([name, 'log'])
|
||||
basedir.mkdir(parents=True, exist_ok=True)
|
||||
file_handler = RotatingFileHandler(
|
||||
str(filename),
|
||||
mode='a',
|
||||
maxBytes=2 ** 24,
|
||||
backupCount=5
|
||||
)
|
||||
file_formatter = logging.Formatter("[%(asctime)s] %(levelname)s [%(name)s]: %(message)s")
|
||||
file_handler.setLevel(loglevel)
|
||||
file_handler.setFormatter(file_formatter)
|
||||
return file_handler
|
||||
|
||||
def _rich_handler() -> RichHandler:
|
||||
rich_handler = RichHandler(rich_tracebacks=True, markup=True)
|
||||
rich_formatter = logging.Formatter(
|
||||
"[bold green]\[%(name)s][/bold green] %(message)s",
|
||||
datefmt='[%y-%m-%dT%H:%M:%S]'
|
||||
)
|
||||
rich_handler.setFormatter(rich_formatter)
|
||||
return rich_handler
|
18
masto_ld/main.py
Normal file
18
masto_ld/main.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
from typing import Optional
|
||||
from masto_ld.config import Config
|
||||
from masto_ld.bots.mastodon import Bot
|
||||
from time import sleep
|
||||
|
||||
|
||||
def masto_ld(config:Optional[Config]=None):
|
||||
if config is None:
|
||||
config = Config()
|
||||
|
||||
bot = Bot(config=config)
|
||||
try:
|
||||
bot.init_stream()
|
||||
while True:
|
||||
sleep(60*60)
|
||||
bot.logger.info('taking a breath')
|
||||
except KeyboardInterrupt:
|
||||
bot.logger.info('quitting!')
|
0
masto_ld/models/__init__.py
Normal file
0
masto_ld/models/__init__.py
Normal file
52
masto_ld/models/models.py
Normal file
52
masto_ld/models/models.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
from pydantic import BaseModel, AnyHttpUrl
|
||||
from pydantic import Field as _Field
|
||||
from datetime import datetime
|
||||
from typing import Optional, List
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
|
||||
# class List(BaseModel):
|
||||
# """A mastodon list!"""
|
||||
# id: str
|
||||
# title: str
|
||||
#
|
||||
# class Config:
|
||||
# extra = 'ignore'
|
||||
|
||||
class Field(BaseModel):
|
||||
name: str
|
||||
value: str
|
||||
url: Optional[AnyHttpUrl] = None
|
||||
|
||||
def __init__(self, name:str, value:str):
|
||||
soup = BeautifulSoup(value, 'lxml')
|
||||
a = soup.find('a')
|
||||
if a is not None:
|
||||
url = a.get('href')
|
||||
else:
|
||||
url = None
|
||||
super().__init__(name=name, value=value, url=url)
|
||||
|
||||
class Config:
|
||||
extra = "ignore"
|
||||
|
||||
|
||||
class Account(BaseModel):
|
||||
"""Not transcribing full model now, just using to check"""
|
||||
acct: str
|
||||
avatar: str
|
||||
avatar_static: str
|
||||
bot: bool
|
||||
created_at:datetime
|
||||
discoverable:bool
|
||||
display_name:str
|
||||
fields: List[Field] = _Field(default_factory=list)
|
||||
followers_count:int
|
||||
following_count:int
|
||||
id: int
|
||||
url: AnyHttpUrl
|
||||
username: str
|
||||
|
||||
class Config:
|
||||
extra = 'ignore'
|
58
masto_ld/models/post.py
Normal file
58
masto_ld/models/post.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
from typing import Optional, Literal, List
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel, Field
|
||||
import re
|
||||
from bs4 import BeautifulSoup
|
||||
import pypandoc
|
||||
|
||||
from masto_ld.models.models import Account
|
||||
from masto_ld.patterns.wikilink import Wikilink
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from masto_ld.models.thread import Thread
|
||||
|
||||
class Mention(BaseModel):
|
||||
acct: str
|
||||
id: int
|
||||
url: str
|
||||
username: str
|
||||
|
||||
class Status(BaseModel):
|
||||
"""
|
||||
Model of a toot on mastodon
|
||||
|
||||
See: https://mastodonpy.readthedocs.io/en/stable/#toot-dicts
|
||||
"""
|
||||
id: int
|
||||
url: str
|
||||
account: Account
|
||||
content: str
|
||||
created_at: datetime
|
||||
visibility: Literal['public', 'unlisted', 'private', 'direct']
|
||||
in_reply_to_id: Optional[int] = None
|
||||
in_reply_to_account_id: Optional[int] = None
|
||||
mentions: Optional[List[Mention]] = None
|
||||
|
||||
def format_content(self, format:str='commonmark-raw_html') -> str:
|
||||
"""Format the HTMl content of the post using pypandoc"""
|
||||
output = pypandoc.convert_text(self.content, format, format='html')
|
||||
return output
|
||||
|
||||
@property
|
||||
def soup(self) -> BeautifulSoup:
|
||||
return BeautifulSoup(self.content)
|
||||
|
||||
@property
|
||||
def wikilinks(self) -> List[Wikilink]:
|
||||
return Wikilink.parse(self.content)
|
||||
|
||||
class Config:
|
||||
extra='ignore'
|
||||
|
||||
class Post(BaseModel):
|
||||
#timestamp: Optional[datetime] = None
|
||||
text:str
|
||||
status:Optional[Status] = None
|
||||
|
||||
|
11
masto_ld/models/thread.py
Normal file
11
masto_ld/models/thread.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from pydantic import BaseModel
|
||||
from typing import List, Optional, Union
|
||||
|
||||
from masto_ld.models.post import Status
|
||||
|
||||
class Thread(BaseModel):
|
||||
"""
|
||||
Container for multiple posts, allowing appending, resolving of the last subject, etc.
|
||||
"""
|
||||
posts: List[Status]
|
||||
|
0
masto_ld/patterns/__init__.py
Normal file
0
masto_ld/patterns/__init__.py
Normal file
11
masto_ld/patterns/patterns.py
Normal file
11
masto_ld/patterns/patterns.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
"""
|
||||
Basic regex patterns that are simply `re.compile`d
|
||||
"""
|
||||
|
||||
class Pattern:
|
||||
"""
|
||||
Metaclass for detecting patterns
|
||||
|
||||
Not sure what should go here but making it just for the sake of structure
|
||||
"""
|
||||
|
31
masto_ld/patterns/tag.py
Normal file
31
masto_ld/patterns/tag.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from typing import List, Optional
|
||||
import pyparsing as pp
|
||||
from bs4 import BeautifulSoup
|
||||
from dataclasses import dataclass
|
||||
|
||||
EXAMPLE = '<p># My New Post</p><p><span class="h-card"><a href="https://masto.synthesis-infrastructures.wiki/@jonny" class="u-url mention">@<span>jonny</span></a></span>:wiki:scruffy</p><p>Here is some new post where I talk about being real scruffy</p>'
|
||||
|
||||
@dataclass
|
||||
class Namespaced_Tag:
|
||||
username: str
|
||||
tags: List[str]
|
||||
|
||||
@classmethod
|
||||
def from_html(cls, html:str) -> Optional['Namespaced_Tag']:
|
||||
"""
|
||||
# FIXME: Just finds the first one for now
|
||||
"""
|
||||
soup = BeautifulSoup(html, 'lxml')
|
||||
mention = soup.find(class_='h-card')
|
||||
if mention is None:
|
||||
return None
|
||||
username = mention.text
|
||||
tags = mention.next_sibling.text.split(':')
|
||||
# FIXME: super weak check, just check that the next text starts with a ':'
|
||||
if tags[0] != '':
|
||||
return None
|
||||
tags = tags[1:]
|
||||
return Namespaced_Tag(username=username, tags=tags)
|
||||
|
||||
|
||||
|
189
masto_ld/patterns/wikilink.py
Normal file
189
masto_ld/patterns/wikilink.py
Normal file
|
@ -0,0 +1,189 @@
|
|||
import re
|
||||
from masto_ld.patterns.patterns import Pattern
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, Union, List
|
||||
import pyparsing as pp
|
||||
from pprint import pformat
|
||||
|
||||
|
||||
WIKILINK = re.compile(r'\[\[(.*?)\]\]', re.IGNORECASE)
|
||||
"""
|
||||
Basic structure of wikilink, used to detect presence
|
||||
"""
|
||||
|
||||
class NBack:
|
||||
FIELDS = ('wildcard', 'start', 'end')
|
||||
|
||||
def __init__(self, start:Optional[int]=None, end:Optional[int]=None,
|
||||
wildcard:Optional[Union[str,bool]]=None,
|
||||
one:Optional[str]=None):
|
||||
|
||||
if wildcard:
|
||||
self.wildcard = True
|
||||
self.start = None
|
||||
self.end = None
|
||||
return
|
||||
else:
|
||||
self.wildcard = False
|
||||
|
||||
if one:
|
||||
self.start = 1
|
||||
self.end = 1
|
||||
else:
|
||||
if start is not None:
|
||||
start = int(start)
|
||||
if end is not None:
|
||||
end = int(end)
|
||||
self.start = start
|
||||
self.end = end
|
||||
|
||||
if self.start is not None and self.end is not None:
|
||||
if self.start > self.end:
|
||||
raise ValueError(f"Start value must be less than end value, got start:{self.start}, end:{self.end}")
|
||||
|
||||
@classmethod
|
||||
def make_parser(cls) -> pp.ParserElement:
|
||||
# --------------------------------------------------
|
||||
# n-back links immediately follow the [[ and can be one of
|
||||
# ^
|
||||
# ^*
|
||||
# ^{n,m}
|
||||
# ^{n,}
|
||||
# ^{,m}
|
||||
# ^{m}
|
||||
|
||||
# make elements
|
||||
caret = pp.Literal("^")
|
||||
lcurly = pp.Literal('{').suppress()
|
||||
rcurly = pp.Literal('}').suppress()
|
||||
integer = pp.Word(pp.nums)
|
||||
comma = pp.Literal(',').suppress()
|
||||
nb_range = caret + lcurly
|
||||
|
||||
# combine into matches
|
||||
nb_wildcard = caret.suppress() + "*"
|
||||
# start or end can be omitted if comma is present
|
||||
nb_full = nb_range + pp.Optional(integer("start")) + comma + pp.Optional(integer("end")) + rcurly
|
||||
# if no comma present, it's just an end
|
||||
nb_end = nb_range + integer("end") + rcurly
|
||||
|
||||
# combine into full nback parser
|
||||
nback = pp.Group(nb_wildcard('wildcard') | nb_full | nb_end | caret("one")).set_results_name("nback")
|
||||
return nback
|
||||
|
||||
def __eq__(self, other:'NBack'):
|
||||
return all([getattr(self, f) == getattr(other, f) for f in self.FIELDS])
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return pformat({f:getattr(self, f) for f in self.FIELDS})
|
||||
|
||||
class Wikilink(Pattern):
|
||||
"""
|
||||
Pattern for detecting wikilinks!
|
||||
|
||||
This pattern implements an extended wikilink syntax that includes
|
||||
|
||||
* **n-back links** - allows the user to specify messages in threads that are not the initiating message, and
|
||||
* **Semantic wikilinks** - specify a triplet subject-predicate-object link
|
||||
|
||||
In each of the following examples, `LINK` is a placeholder for the text of the wikilink to be made.
|
||||
|
||||
# N-Back Links (see :class:`.NBack`)
|
||||
|
||||
For all of these, whitespace in-between the n-back specifier and the link text will be ignored. So
|
||||
`[[^LINK]]` and `[[^ LINK]]` are both valid.
|
||||
|
||||
* **Preceding Message** - `[[^LINK]]`
|
||||
* **Entire Preceding Thread** - `[[^*LINK]]`
|
||||
* **Ranges**
|
||||
** **Fully specified** - `[[^{n,m}LINK]]` where `n` and `m` are the start and end of the range to be included, inclusive.
|
||||
eg. `[[^{2,5}LINK]]` would specify four messages: the 2nd one above the initiating message through the 5th, and
|
||||
`n == 0` indicates the initiating message.
|
||||
** **End specified** - `[[^{,m}LINK]]` OR `[[^{m}LINK]]` - include the initiating message and the `m` messages above it.
|
||||
** **Start specified** - `[[^{n,}LINK]]` - include all preceding messages in the thread before the `nth` message
|
||||
|
||||
# Semantic Wikilinks
|
||||
|
||||
Semantic wikilinks create a subject, predicate, object triplet. The subject will be the page that the
|
||||
|
||||
Semantic wikilinks use `::` as a delimiter between terms, and a `::` indicates that a wikilink is semantic.
|
||||
|
||||
`SUB`, `PRED`, and `OBJ` are placeholders for the parts of
|
||||
a triplet in the following examples.
|
||||
|
||||
* **Complete Triplet** - `[[SUB::PRED::OBJ]]` - create a semantic wikilink on the `SUB`ject page that links to the
|
||||
`OBJ`ect page with the indicated predicate.
|
||||
|
||||
eg. `[[Paper::Has DOI::https://doi.org/10.xxx/yyyy]]`
|
||||
|
||||
* **Implicit Triplet** - `[[PRED::OBJ]]` after a `[[SUB]]` wikilink has been previously used in the message or thread.
|
||||
A subject can also be declared with a complete triplet.
|
||||
"""
|
||||
FIELDS = ('link', 'nback', 'predicate', 'object', 'section')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
link: str,
|
||||
nback: Optional[Union[NBack, tuple, dict]] = None,
|
||||
predicate: Optional[str] = None,
|
||||
object: Optional[str] = None,
|
||||
section: Optional[str] = None,
|
||||
**kwargs):
|
||||
super(Wikilink, self).__init__(**kwargs)
|
||||
|
||||
self.link = link
|
||||
if isinstance(nback, (tuple, list)):
|
||||
nback = NBack(*nback)
|
||||
elif isinstance(nback, dict):
|
||||
nback = NBack(**nback)
|
||||
elif isinstance(nback, pp.ParseResults):
|
||||
nback = NBack(**dict(nback))
|
||||
|
||||
if isinstance(section, pp.ParseResults):
|
||||
section = section[0]
|
||||
|
||||
self.nback = nback
|
||||
self.predicate = predicate
|
||||
self.object = object
|
||||
self.section = section
|
||||
|
||||
@classmethod
|
||||
def make_parser(cls) -> pp.ParserElement:
|
||||
"""
|
||||
Make the parser to detect wikilinks!
|
||||
"""
|
||||
# All wikilinks start with [[ and end with ]]
|
||||
lbracket = pp.Literal('[[').suppress()
|
||||
rbracket = pp.Literal(']]').suppress()
|
||||
|
||||
#nback parser
|
||||
nback = NBack.make_parser()
|
||||
|
||||
# main wikilink subject text
|
||||
link = pp.Word(pp.printables+ " ", excludeChars="#[]{}|")
|
||||
|
||||
# optional page section
|
||||
hash = pp.Literal("#").suppress()
|
||||
section = hash + link
|
||||
|
||||
# Combine all
|
||||
parser = lbracket + pp.Optional(nback) + link("link") + pp.Optional(section("section")) + rbracket
|
||||
return parser
|
||||
|
||||
@classmethod
|
||||
def parse(cls, string:str, return_parsed:bool=False) -> List['Wikilink']:
|
||||
parser = cls.make_parser()
|
||||
results = parser.search_string(string)
|
||||
if return_parsed:
|
||||
return results
|
||||
else:
|
||||
return [Wikilink(**dict(res.items())) for res in results]
|
||||
|
||||
def __eq__(self, other:'Wikilink'):
|
||||
return all(getattr(self, f) == getattr(other, f) for f in self.FIELDS)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return pformat({f:getattr(self, f) for f in self.FIELDS if getattr(self, f) is not None})
|
||||
|
||||
|
||||
|
8
masto_ld/templates/__init__.py
Normal file
8
masto_ld/templates/__init__.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
from pydantic import BaseModel
|
||||
|
||||
class WikiPage(BaseModel):
|
||||
"""
|
||||
A wiki page that should be just straight up added to the wiki as is
|
||||
"""
|
||||
name: str
|
||||
body: str
|
12
masto_ld/templates/categories.py
Normal file
12
masto_ld/templates/categories.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
from masto_ld.templates import WikiPage
|
||||
|
||||
class Category(WikiPage):
|
||||
"""Trivial subclass to indicate these are categories!"""
|
||||
pass
|
||||
|
||||
Thread = Category(
|
||||
name="Category:Thread",
|
||||
body="""
|
||||
[[Imported from::schema:SocialMediaPosting]]
|
||||
"""
|
||||
)
|
48
masto_ld/templates/properties.py
Normal file
48
masto_ld/templates/properties.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
from masto_ld.templates import WikiPage
|
||||
|
||||
class Property(WikiPage):
|
||||
"""Trivial subclass to indicate that these are properties!"""
|
||||
pass
|
||||
|
||||
Tag = Property(
|
||||
name="Property:Tag",
|
||||
body="""
|
||||
[[Has type::Record]]
|
||||
[[Has fields::ShortName;LongName]]
|
||||
"""
|
||||
)
|
||||
|
||||
ShortName = Property(
|
||||
name="Property:ShortName",
|
||||
body="""
|
||||
A short name [[Used In::Property:Tag]]
|
||||
[[Has type::Text]]
|
||||
"""
|
||||
)
|
||||
|
||||
LongName = Property(
|
||||
name="Property:LongName",
|
||||
body="""
|
||||
A long name [[Used In::Property:Tag]]
|
||||
[[Has type::Page]]
|
||||
"""
|
||||
)
|
||||
|
||||
HasThread = Property(
|
||||
name="Property:Has_Thread",
|
||||
body="""
|
||||
To specify a thread page that is about this page!
|
||||
[[Has type::Page]]
|
||||
[[Imported from::schema:subjectOf]]
|
||||
"""
|
||||
)
|
||||
|
||||
About = Property(
|
||||
name="Property:About",
|
||||
body="""
|
||||
To specify that something is about another thing!
|
||||
[[Has type::Page]]
|
||||
[[Imported from::schema:about]]
|
||||
"""
|
||||
)
|
||||
|
23
masto_ld/templates/templates.py
Normal file
23
masto_ld/templates/templates.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from masto_ld.templates import WikiPage
|
||||
from typing import List
|
||||
|
||||
class Template(WikiPage):
|
||||
"""Trivial subclass to indicate template!"""
|
||||
params: List[str]
|
||||
|
||||
Thread = Template(
|
||||
name="Template:Thread",
|
||||
params= ['About', 'URL'],
|
||||
body="""
|
||||
<includeonly>
|
||||
{|class="wikitable sortable"
|
||||
! About
|
||||
| [[About::{{{About|}}}]]
|
||||
|-
|
||||
! Thread URL
|
||||
| [[Has URL::{{{URL|}}}]]
|
||||
|}
|
||||
[[Category:Thread]]
|
||||
</includeonly>
|
||||
"""
|
||||
)
|
0
masto_ld/templates/thread.py
Normal file
0
masto_ld/templates/thread.py
Normal file
629
poetry.lock
generated
Normal file
629
poetry.lock
generated
Normal file
|
@ -0,0 +1,629 @@
|
|||
[[package]]
|
||||
name = "beautifulsoup4"
|
||||
version = "4.11.1"
|
||||
description = "Screen-scraping library"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6.0"
|
||||
|
||||
[package.dependencies]
|
||||
soupsieve = ">1.2"
|
||||
|
||||
[package.extras]
|
||||
html5lib = ["html5lib"]
|
||||
lxml = ["lxml"]
|
||||
|
||||
[[package]]
|
||||
name = "blurhash"
|
||||
version = "1.1.4"
|
||||
description = "Pure-Python implementation of the blurhash algorithm."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.extras]
|
||||
test = ["Pillow", "numpy", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2022.9.24"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "2.1.1"
|
||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6.0"
|
||||
|
||||
[package.extras]
|
||||
unicode-backport = ["unicodedata2"]
|
||||
|
||||
[[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 = "decorator"
|
||||
version = "5.1.1"
|
||||
description = "Decorators for Humans"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "dnspython"
|
||||
version = "2.2.1"
|
||||
description = "DNS toolkit"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6,<4.0"
|
||||
|
||||
[package.extras]
|
||||
curio = ["curio (>=1.2,<2.0)", "sniffio (>=1.1,<2.0)"]
|
||||
dnssec = ["cryptography (>=2.6,<37.0)"]
|
||||
doh = ["h2 (>=4.1.0)", "httpx (>=0.21.1)", "requests (>=2.23.0,<3.0.0)", "requests-toolbelt (>=0.9.1,<0.10.0)"]
|
||||
idna = ["idna (>=2.1,<4.0)"]
|
||||
trio = ["trio (>=0.14,<0.20)"]
|
||||
wmi = ["wmi (>=1.5.1,<2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "email-validator"
|
||||
version = "1.3.0"
|
||||
description = "A robust email address syntax and deliverability validation library."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||
|
||||
[package.dependencies]
|
||||
dnspython = ">=1.15.0"
|
||||
idna = ">=2.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.4"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "lxml"
|
||||
version = "4.9.1"
|
||||
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
|
||||
|
||||
[package.extras]
|
||||
cssselect = ["cssselect (>=0.7)"]
|
||||
html5 = ["html5lib"]
|
||||
htmlsoup = ["BeautifulSoup4"]
|
||||
source = ["Cython (>=0.29.7)"]
|
||||
|
||||
[[package]]
|
||||
name = "mastodon-py"
|
||||
version = "1.5.2"
|
||||
description = "Python wrapper for the Mastodon API"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
blurhash = ">=1.1.4"
|
||||
decorator = ">=4.0.0"
|
||||
python-dateutil = "*"
|
||||
python-magic = "*"
|
||||
pytz = "*"
|
||||
requests = ">=2.4.2"
|
||||
six = "*"
|
||||
|
||||
[package.extras]
|
||||
blurhash = ["blurhash (>=1.1.4)"]
|
||||
test = ["blurhash (>=1.1.4)", "cryptography (>=1.6.0)", "http-ece (>=1.0.5)", "pytest", "pytest-cov", "pytest-mock", "pytest-runner", "pytest-vcr", "requests-mock", "vcrpy"]
|
||||
webpush = ["cryptography (>=1.6.0)", "http-ece (>=1.0.5)"]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "1.10.2"
|
||||
description = "Data validation and settings management using python type hints"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
email-validator = {version = ">=1.0.3", optional = true, markers = "extra == \"email\""}
|
||||
python-dotenv = {version = ">=0.10.4", optional = true, markers = "extra == \"dotenv\""}
|
||||
typing-extensions = ">=4.1.0"
|
||||
|
||||
[package.extras]
|
||||
dotenv = ["python-dotenv (>=0.10.4)"]
|
||||
email = ["email-validator (>=1.0.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.13.0"
|
||||
description = "Pygments is a syntax highlighting package written in Python."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.extras]
|
||||
plugins = ["importlib-metadata"]
|
||||
|
||||
[[package]]
|
||||
name = "pypandoc"
|
||||
version = "1.10"
|
||||
description = "Thin wrapper for pandoc."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.0.9"
|
||||
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6.8"
|
||||
|
||||
[package.extras]
|
||||
diagrams = ["jinja2", "railroad-diagrams"]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.8.2"
|
||||
description = "Extensions to the standard Python datetime module"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||
|
||||
[package.dependencies]
|
||||
six = ">=1.5"
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "0.21.0"
|
||||
description = "Read key-value pairs from a .env file and set them as environment variables"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
cli = ["click (>=5.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "python-magic"
|
||||
version = "0.4.27"
|
||||
description = "File type identification using libmagic"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2022.6"
|
||||
description = "World timezone definitions, modern and historical"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "2022.10.31"
|
||||
description = "Alternative regular expression module, to replace re."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.28.1"
|
||||
description = "Python HTTP for Humans."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7, <4"
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
charset-normalizer = ">=2,<3"
|
||||
idna = ">=2.5,<4"
|
||||
urllib3 = ">=1.21.1,<1.27"
|
||||
|
||||
[package.extras]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
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"
|
||||
|
||||
[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 = "six"
|
||||
version = "1.16.0"
|
||||
description = "Python 2 and 3 compatibility utilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "soupsieve"
|
||||
version = "2.3.2.post1"
|
||||
description = "A modern CSS selector implementation for Beautiful Soup."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.4.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "1.26.12"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4"
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
|
||||
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "wcwidth"
|
||||
version = "0.2.5"
|
||||
description = "Measures the displayed width of unicode strings in a terminal"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "wikitextparser"
|
||||
version = "0.51.1"
|
||||
description = "A simple parsing tool for MediaWiki's wikitext markup."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
regex = ">=2022.9.11"
|
||||
wcwidth = "*"
|
||||
|
||||
[package.extras]
|
||||
dev = ["coverage", "path.py", "twine"]
|
||||
tests = ["pytest"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "d0b7c1d488d5cf14efa9dc53449d39e6b9a032c09a81fae39b9ce3a1dc5c3ba0"
|
||||
|
||||
[metadata.files]
|
||||
beautifulsoup4 = [
|
||||
{file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"},
|
||||
{file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"},
|
||||
]
|
||||
blurhash = [
|
||||
{file = "blurhash-1.1.4-py2.py3-none-any.whl", hash = "sha256:7611c1bc41383d2349b6129208587b5d61e8792ce953893cb49c38beeb400d1d"},
|
||||
{file = "blurhash-1.1.4.tar.gz", hash = "sha256:da56b163e5a816e4ad07172f5639287698e09d7f3dc38d18d9726d9c1dbc4cee"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"},
|
||||
{file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"},
|
||||
]
|
||||
charset-normalizer = [
|
||||
{file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"},
|
||||
{file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"},
|
||||
]
|
||||
commonmark = [
|
||||
{file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
|
||||
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
|
||||
]
|
||||
decorator = [
|
||||
{file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
|
||||
{file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
|
||||
]
|
||||
dnspython = [
|
||||
{file = "dnspython-2.2.1-py3-none-any.whl", hash = "sha256:a851e51367fb93e9e1361732c1d60dab63eff98712e503ea7d92e6eccb109b4f"},
|
||||
{file = "dnspython-2.2.1.tar.gz", hash = "sha256:0f7569a4a6ff151958b64304071d370daa3243d15941a7beedf0c9fe5105603e"},
|
||||
]
|
||||
email-validator = [
|
||||
{file = "email_validator-1.3.0-py2.py3-none-any.whl", hash = "sha256:816073f2a7cffef786b29928f58ec16cdac42710a53bb18aa94317e3e145ec5c"},
|
||||
{file = "email_validator-1.3.0.tar.gz", hash = "sha256:553a66f8be2ec2dea641ae1d3f29017ab89e9d603d4a25cdaac39eefa283d769"},
|
||||
]
|
||||
idna = [
|
||||
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
|
||||
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
|
||||
]
|
||||
lxml = [
|
||||
{file = "lxml-4.9.1-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:98cafc618614d72b02185ac583c6f7796202062c41d2eeecdf07820bad3295ed"},
|
||||
{file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c62e8dd9754b7debda0c5ba59d34509c4688f853588d75b53c3791983faa96fc"},
|
||||
{file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21fb3d24ab430fc538a96e9fbb9b150029914805d551deeac7d7822f64631dfc"},
|
||||
{file = "lxml-4.9.1-cp27-cp27m-win32.whl", hash = "sha256:86e92728ef3fc842c50a5cb1d5ba2bc66db7da08a7af53fb3da79e202d1b2cd3"},
|
||||
{file = "lxml-4.9.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4cfbe42c686f33944e12f45a27d25a492cc0e43e1dc1da5d6a87cbcaf2e95627"},
|
||||
{file = "lxml-4.9.1-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dad7b164905d3e534883281c050180afcf1e230c3d4a54e8038aa5cfcf312b84"},
|
||||
{file = "lxml-4.9.1-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a614e4afed58c14254e67862456d212c4dcceebab2eaa44d627c2ca04bf86837"},
|
||||
{file = "lxml-4.9.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f9ced82717c7ec65a67667bb05865ffe38af0e835cdd78728f1209c8fffe0cad"},
|
||||
{file = "lxml-4.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:d9fc0bf3ff86c17348dfc5d322f627d78273eba545db865c3cd14b3f19e57fa5"},
|
||||
{file = "lxml-4.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e5f66bdf0976ec667fc4594d2812a00b07ed14d1b44259d19a41ae3fff99f2b8"},
|
||||
{file = "lxml-4.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fe17d10b97fdf58155f858606bddb4e037b805a60ae023c009f760d8361a4eb8"},
|
||||
{file = "lxml-4.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8caf4d16b31961e964c62194ea3e26a0e9561cdf72eecb1781458b67ec83423d"},
|
||||
{file = "lxml-4.9.1-cp310-cp310-win32.whl", hash = "sha256:4780677767dd52b99f0af1f123bc2c22873d30b474aa0e2fc3fe5e02217687c7"},
|
||||
{file = "lxml-4.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:b122a188cd292c4d2fcd78d04f863b789ef43aa129b233d7c9004de08693728b"},
|
||||
{file = "lxml-4.9.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:be9eb06489bc975c38706902cbc6888f39e946b81383abc2838d186f0e8b6a9d"},
|
||||
{file = "lxml-4.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f1be258c4d3dc609e654a1dc59d37b17d7fef05df912c01fc2e15eb43a9735f3"},
|
||||
{file = "lxml-4.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:927a9dd016d6033bc12e0bf5dee1dde140235fc8d0d51099353c76081c03dc29"},
|
||||
{file = "lxml-4.9.1-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9232b09f5efee6a495a99ae6824881940d6447debe272ea400c02e3b68aad85d"},
|
||||
{file = "lxml-4.9.1-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:04da965dfebb5dac2619cb90fcf93efdb35b3c6994fea58a157a834f2f94b318"},
|
||||
{file = "lxml-4.9.1-cp35-cp35m-win32.whl", hash = "sha256:4d5bae0a37af799207140652a700f21a85946f107a199bcb06720b13a4f1f0b7"},
|
||||
{file = "lxml-4.9.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4878e667ebabe9b65e785ac8da4d48886fe81193a84bbe49f12acff8f7a383a4"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:1355755b62c28950f9ce123c7a41460ed9743c699905cbe664a5bcc5c9c7c7fb"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:bcaa1c495ce623966d9fc8a187da80082334236a2a1c7e141763ffaf7a405067"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6eafc048ea3f1b3c136c71a86db393be36b5b3d9c87b1c25204e7d397cee9536"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:13c90064b224e10c14dcdf8086688d3f0e612db53766e7478d7754703295c7c8"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:206a51077773c6c5d2ce1991327cda719063a47adc02bd703c56a662cdb6c58b"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e8f0c9d65da595cfe91713bc1222af9ecabd37971762cb830dea2fc3b3bb2acf"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8f0a4d179c9a941eb80c3a63cdb495e539e064f8054230844dcf2fcb812b71d3"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:830c88747dce8a3e7525defa68afd742b4580df6aa2fdd6f0855481e3994d391"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-win32.whl", hash = "sha256:1e1cf47774373777936c5aabad489fef7b1c087dcd1f426b621fda9dcc12994e"},
|
||||
{file = "lxml-4.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:5974895115737a74a00b321e339b9c3f45c20275d226398ae79ac008d908bff7"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:1423631e3d51008871299525b541413c9b6c6423593e89f9c4cfbe8460afc0a2"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:2aaf6a0a6465d39b5ca69688fce82d20088c1838534982996ec46633dc7ad6cc"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:9f36de4cd0c262dd9927886cc2305aa3f2210db437aa4fed3fb4940b8bf4592c"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae06c1e4bc60ee076292e582a7512f304abdf6c70db59b56745cca1684f875a4"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:57e4d637258703d14171b54203fd6822fda218c6c2658a7d30816b10995f29f3"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6d279033bf614953c3fc4a0aa9ac33a21e8044ca72d4fa8b9273fe75359d5cca"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a60f90bba4c37962cbf210f0188ecca87daafdf60271f4c6948606e4dabf8785"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6ca2264f341dd81e41f3fffecec6e446aa2121e0b8d026fb5130e02de1402785"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-win32.whl", hash = "sha256:27e590352c76156f50f538dbcebd1925317a0f70540f7dc8c97d2931c595783a"},
|
||||
{file = "lxml-4.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:eea5d6443b093e1545ad0210e6cf27f920482bfcf5c77cdc8596aec73523bb7e"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f05251bbc2145349b8d0b77c0d4e5f3b228418807b1ee27cefb11f69ed3d233b"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:487c8e61d7acc50b8be82bda8c8d21d20e133c3cbf41bd8ad7eb1aaeb3f07c97"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d1a92d8e90b286d491e5626af53afef2ba04da33e82e30744795c71880eaa21"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:b570da8cd0012f4af9fa76a5635cd31f707473e65a5a335b186069d5c7121ff2"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ef87fca280fb15342726bd5f980f6faf8b84a5287fcc2d4962ea8af88b35130"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:93e414e3206779ef41e5ff2448067213febf260ba747fc65389a3ddaa3fb8715"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6653071f4f9bac46fbc30f3c7838b0e9063ee335908c5d61fb7a4a86c8fd2036"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:32a73c53783becdb7eaf75a2a1525ea8e49379fb7248c3eeefb9412123536387"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-win32.whl", hash = "sha256:1a7c59c6ffd6ef5db362b798f350e24ab2cfa5700d53ac6681918f314a4d3b94"},
|
||||
{file = "lxml-4.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:1436cf0063bba7888e43f1ba8d58824f085410ea2025befe81150aceb123e345"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:4beea0f31491bc086991b97517b9683e5cfb369205dac0148ef685ac12a20a67"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:41fb58868b816c202e8881fd0f179a4644ce6e7cbbb248ef0283a34b73ec73bb"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:bd34f6d1810d9354dc7e35158aa6cc33456be7706df4420819af6ed966e85448"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:edffbe3c510d8f4bf8640e02ca019e48a9b72357318383ca60e3330c23aaffc7"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d949f53ad4fc7cf02c44d6678e7ff05ec5f5552b235b9e136bd52e9bf730b91"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:079b68f197c796e42aa80b1f739f058dcee796dc725cc9a1be0cdb08fc45b000"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9c3a88d20e4fe4a2a4a84bf439a5ac9c9aba400b85244c63a1ab7088f85d9d25"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4e285b5f2bf321fc0857b491b5028c5f276ec0c873b985d58d7748ece1d770dd"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-win32.whl", hash = "sha256:ef72013e20dd5ba86a8ae1aed7f56f31d3374189aa8b433e7b12ad182c0d2dfb"},
|
||||
{file = "lxml-4.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:10d2017f9150248563bb579cd0d07c61c58da85c922b780060dcc9a3aa9f432d"},
|
||||
{file = "lxml-4.9.1-pp37-pypy37_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538747a9d7827ce3e16a8fdd201a99e661c7dee3c96c885d8ecba3c35d1032c"},
|
||||
{file = "lxml-4.9.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0645e934e940107e2fdbe7c5b6fb8ec6232444260752598bc4d09511bd056c0b"},
|
||||
{file = "lxml-4.9.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6daa662aba22ef3258934105be2dd9afa5bb45748f4f702a3b39a5bf53a1f4dc"},
|
||||
{file = "lxml-4.9.1-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:603a464c2e67d8a546ddaa206d98e3246e5db05594b97db844c2f0a1af37cf5b"},
|
||||
{file = "lxml-4.9.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c4b2e0559b68455c085fb0f6178e9752c4be3bba104d6e881eb5573b399d1eb2"},
|
||||
{file = "lxml-4.9.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0f3f0059891d3254c7b5fb935330d6db38d6519ecd238ca4fce93c234b4a0f73"},
|
||||
{file = "lxml-4.9.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c852b1530083a620cb0de5f3cd6826f19862bafeaf77586f1aef326e49d95f0c"},
|
||||
{file = "lxml-4.9.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:287605bede6bd36e930577c5925fcea17cb30453d96a7b4c63c14a257118dbb9"},
|
||||
{file = "lxml-4.9.1.tar.gz", hash = "sha256:fe749b052bb7233fe5d072fcb549221a8cb1a16725c47c37e42b0b9cb3ff2c3f"},
|
||||
]
|
||||
mastodon-py = [
|
||||
{file = "Mastodon.py-1.5.2-py2.py3-none-any.whl", hash = "sha256:49afbf9f4347f355bee5638b71a5231b0e1164a58d253ccd9b4345d999c43369"},
|
||||
{file = "Mastodon.py-1.5.2.tar.gz", hash = "sha256:c98fd97b7450cd02262669b80be20f53657b5540c4888a47231df11856910918"},
|
||||
]
|
||||
pydantic = [
|
||||
{file = "pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"},
|
||||
{file = "pydantic-1.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98"},
|
||||
{file = "pydantic-1.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912"},
|
||||
{file = "pydantic-1.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559"},
|
||||
{file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236"},
|
||||
{file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c"},
|
||||
{file = "pydantic-1.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644"},
|
||||
{file = "pydantic-1.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f"},
|
||||
{file = "pydantic-1.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a"},
|
||||
{file = "pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525"},
|
||||
{file = "pydantic-1.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283"},
|
||||
{file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42"},
|
||||
{file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52"},
|
||||
{file = "pydantic-1.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c"},
|
||||
{file = "pydantic-1.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5"},
|
||||
{file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"},
|
||||
{file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"},
|
||||
{file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5"},
|
||||
{file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d"},
|
||||
{file = "pydantic-1.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2"},
|
||||
{file = "pydantic-1.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13"},
|
||||
{file = "pydantic-1.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116"},
|
||||
{file = "pydantic-1.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624"},
|
||||
{file = "pydantic-1.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1"},
|
||||
{file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"},
|
||||
{file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965"},
|
||||
{file = "pydantic-1.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e"},
|
||||
{file = "pydantic-1.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488"},
|
||||
{file = "pydantic-1.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41"},
|
||||
{file = "pydantic-1.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b"},
|
||||
{file = "pydantic-1.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe"},
|
||||
{file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d"},
|
||||
{file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda"},
|
||||
{file = "pydantic-1.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6"},
|
||||
{file = "pydantic-1.10.2-py3-none-any.whl", hash = "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709"},
|
||||
{file = "pydantic-1.10.2.tar.gz", hash = "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410"},
|
||||
]
|
||||
pygments = [
|
||||
{file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"},
|
||||
{file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"},
|
||||
]
|
||||
pypandoc = [
|
||||
{file = "pypandoc-1.10-py3-none-any.whl", hash = "sha256:ff9658cda18865a822695349a7c707756ecc454b59b71f920b554579ec54aaa7"},
|
||||
{file = "pypandoc-1.10.tar.gz", hash = "sha256:101164d154f0b9957372cdbf285396153b74144fda47f531fb556de244efc86e"},
|
||||
]
|
||||
pyparsing = [
|
||||
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
|
||||
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
|
||||
]
|
||||
python-dateutil = [
|
||||
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
|
||||
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
|
||||
]
|
||||
python-dotenv = [
|
||||
{file = "python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"},
|
||||
{file = "python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5"},
|
||||
]
|
||||
python-magic = [
|
||||
{file = "python-magic-0.4.27.tar.gz", hash = "sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b"},
|
||||
{file = "python_magic-0.4.27-py2.py3-none-any.whl", hash = "sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3"},
|
||||
]
|
||||
pytz = [
|
||||
{file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"},
|
||||
{file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"},
|
||||
]
|
||||
regex = [
|
||||
{file = "regex-2022.10.31-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8ff454ef0bb061e37df03557afda9d785c905dab15584860f982e88be73015f"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1eba476b1b242620c266edf6325b443a2e22b633217a9835a52d8da2b5c051f9"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0e5af9a9effb88535a472e19169e09ce750c3d442fb222254a276d77808620b"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d03fe67b2325cb3f09be029fd5da8df9e6974f0cde2c2ac6a79d2634e791dd57"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9d0b68ac1743964755ae2d89772c7e6fb0118acd4d0b7464eaf3921c6b49dd4"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a45b6514861916c429e6059a55cf7db74670eaed2052a648e3e4d04f070e001"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8b0886885f7323beea6f552c28bff62cbe0983b9fbb94126531693ea6c5ebb90"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5aefb84a301327ad115e9d346c8e2760009131d9d4b4c6b213648d02e2abe144"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:702d8fc6f25bbf412ee706bd73019da5e44a8400861dfff7ff31eb5b4a1276dc"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a3c1ebd4ed8e76e886507c9eddb1a891673686c813adf889b864a17fafcf6d66"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:50921c140561d3db2ab9f5b11c5184846cde686bb5a9dc64cae442926e86f3af"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:7db345956ecce0c99b97b042b4ca7326feeec6b75facd8390af73b18e2650ffc"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:763b64853b0a8f4f9cfb41a76a4a85a9bcda7fdda5cb057016e7706fde928e66"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-win32.whl", hash = "sha256:44136355e2f5e06bf6b23d337a75386371ba742ffa771440b85bed367c1318d1"},
|
||||
{file = "regex-2022.10.31-cp310-cp310-win_amd64.whl", hash = "sha256:bfff48c7bd23c6e2aec6454aaf6edc44444b229e94743b34bdcdda2e35126cf5"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b4b1fe58cd102d75ef0552cf17242705ce0759f9695334a56644ad2d83903fe"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:542e3e306d1669b25936b64917285cdffcd4f5c6f0247636fec037187bd93542"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c27cc1e4b197092e50ddbf0118c788d9977f3f8f35bfbbd3e76c1846a3443df7"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8e38472739028e5f2c3a4aded0ab7eadc447f0d84f310c7a8bb697ec417229e"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:76c598ca73ec73a2f568e2a72ba46c3b6c8690ad9a07092b18e48ceb936e9f0c"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c28d3309ebd6d6b2cf82969b5179bed5fefe6142c70f354ece94324fa11bf6a1"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9af69f6746120998cd9c355e9c3c6aec7dff70d47247188feb4f829502be8ab4"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a5f9505efd574d1e5b4a76ac9dd92a12acb2b309551e9aa874c13c11caefbe4f"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5ff525698de226c0ca743bfa71fc6b378cda2ddcf0d22d7c37b1cc925c9650a5"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:4fe7fda2fe7c8890d454f2cbc91d6c01baf206fbc96d89a80241a02985118c0c"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2cdc55ca07b4e70dda898d2ab7150ecf17c990076d3acd7a5f3b25cb23a69f1c"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:44a6c2f6374e0033873e9ed577a54a3602b4f609867794c1a3ebba65e4c93ee7"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-win32.whl", hash = "sha256:d8716f82502997b3d0895d1c64c3b834181b1eaca28f3f6336a71777e437c2af"},
|
||||
{file = "regex-2022.10.31-cp311-cp311-win_amd64.whl", hash = "sha256:61edbca89aa3f5ef7ecac8c23d975fe7261c12665f1d90a6b1af527bba86ce61"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0a069c8483466806ab94ea9068c34b200b8bfc66b6762f45a831c4baaa9e8cdd"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d26166acf62f731f50bdd885b04b38828436d74e8e362bfcb8df221d868b5d9b"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac741bf78b9bb432e2d314439275235f41656e189856b11fb4e774d9f7246d81"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75f591b2055523fc02a4bbe598aa867df9e953255f0b7f7715d2a36a9c30065c"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bddd61d2a3261f025ad0f9ee2586988c6a00c780a2fb0a92cea2aa702c54"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef4163770525257876f10e8ece1cf25b71468316f61451ded1a6f44273eedeb5"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7b280948d00bd3973c1998f92e22aa3ecb76682e3a4255f33e1020bd32adf443"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:d0213671691e341f6849bf33cd9fad21f7b1cb88b89e024f33370733fec58742"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:22e7ebc231d28393dfdc19b185d97e14a0f178bedd78e85aad660e93b646604e"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:8ad241da7fac963d7573cc67a064c57c58766b62a9a20c452ca1f21050868dfa"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:586b36ebda81e6c1a9c5a5d0bfdc236399ba6595e1397842fd4a45648c30f35e"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0653d012b3bf45f194e5e6a41df9258811ac8fc395579fa82958a8b76286bea4"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-win32.whl", hash = "sha256:144486e029793a733e43b2e37df16a16df4ceb62102636ff3db6033994711066"},
|
||||
{file = "regex-2022.10.31-cp36-cp36m-win_amd64.whl", hash = "sha256:c14b63c9d7bab795d17392c7c1f9aaabbffd4cf4387725a0ac69109fb3b550c6"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4cac3405d8dda8bc6ed499557625585544dd5cbf32072dcc72b5a176cb1271c8"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23cbb932cc53a86ebde0fb72e7e645f9a5eec1a5af7aa9ce333e46286caef783"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74bcab50a13960f2a610cdcd066e25f1fd59e23b69637c92ad470784a51b1347"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78d680ef3e4d405f36f0d6d1ea54e740366f061645930072d39bca16a10d8c93"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce6910b56b700bea7be82c54ddf2e0ed792a577dfaa4a76b9af07d550af435c6"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:659175b2144d199560d99a8d13b2228b85e6019b6e09e556209dfb8c37b78a11"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1ddf14031a3882f684b8642cb74eea3af93a2be68893901b2b387c5fd92a03ec"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b683e5fd7f74fb66e89a1ed16076dbab3f8e9f34c18b1979ded614fe10cdc4d9"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2bde29cc44fa81c0a0c8686992c3080b37c488df167a371500b2a43ce9f026d1"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4919899577ba37f505aaebdf6e7dc812d55e8f097331312db7f1aab18767cce8"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:9c94f7cc91ab16b36ba5ce476f1904c91d6c92441f01cd61a8e2729442d6fcf5"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ae1e96785696b543394a4e3f15f3f225d44f3c55dafe3f206493031419fedf95"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-win32.whl", hash = "sha256:c670f4773f2f6f1957ff8a3962c7dd12e4be54d05839b216cb7fd70b5a1df394"},
|
||||
{file = "regex-2022.10.31-cp37-cp37m-win_amd64.whl", hash = "sha256:8e0caeff18b96ea90fc0eb6e3bdb2b10ab5b01a95128dfeccb64a7238decf5f0"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:131d4be09bea7ce2577f9623e415cab287a3c8e0624f778c1d955ec7c281bd4d"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e613a98ead2005c4ce037c7b061f2409a1a4e45099edb0ef3200ee26ed2a69a8"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052b670fafbe30966bbe5d025e90b2a491f85dfe5b2583a163b5e60a85a321ad"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa62a07ac93b7cb6b7d0389d8ef57ffc321d78f60c037b19dfa78d6b17c928ee"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5352bea8a8f84b89d45ccc503f390a6be77917932b1c98c4cdc3565137acc714"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20f61c9944f0be2dc2b75689ba409938c14876c19d02f7585af4460b6a21403e"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29c04741b9ae13d1e94cf93fca257730b97ce6ea64cfe1eba11cf9ac4e85afb6"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:543883e3496c8b6d58bd036c99486c3c8387c2fc01f7a342b760c1ea3158a318"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7a8b43ee64ca8f4befa2bea4083f7c52c92864d8518244bfa6e88c751fa8fff"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6a9a19bea8495bb419dc5d38c4519567781cd8d571c72efc6aa959473d10221a"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6ffd55b5aedc6f25fd8d9f905c9376ca44fcf768673ffb9d160dd6f409bfda73"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4bdd56ee719a8f751cf5a593476a441c4e56c9b64dc1f0f30902858c4ef8771d"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ca88da1bd78990b536c4a7765f719803eb4f8f9971cc22d6ca965c10a7f2c4c"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-win32.whl", hash = "sha256:5a260758454580f11dd8743fa98319bb046037dfab4f7828008909d0aa5292bc"},
|
||||
{file = "regex-2022.10.31-cp38-cp38-win_amd64.whl", hash = "sha256:5e6a5567078b3eaed93558842346c9d678e116ab0135e22eb72db8325e90b453"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5217c25229b6a85049416a5c1e6451e9060a1edcf988641e309dbe3ab26d3e49"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4bf41b8b0a80708f7e0384519795e80dcb44d7199a35d52c15cc674d10b3081b"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf0da36a212978be2c2e2e2d04bdff46f850108fccc1851332bcae51c8907cc"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d403d781b0e06d2922435ce3b8d2376579f0c217ae491e273bab8d092727d244"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a37d51fa9a00d265cf73f3de3930fa9c41548177ba4f0faf76e61d512c774690"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4f781ffedd17b0b834c8731b75cce2639d5a8afe961c1e58ee7f1f20b3af185"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d243b36fbf3d73c25e48014961e83c19c9cc92530516ce3c43050ea6276a2ab7"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:370f6e97d02bf2dd20d7468ce4f38e173a124e769762d00beadec3bc2f4b3bc4"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:597f899f4ed42a38df7b0e46714880fb4e19a25c2f66e5c908805466721760f5"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7dbdce0c534bbf52274b94768b3498abdf675a691fec5f751b6057b3030f34c1"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:22960019a842777a9fa5134c2364efaed5fbf9610ddc5c904bd3a400973b0eb8"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7f5a3ffc731494f1a57bd91c47dc483a1e10048131ffb52d901bfe2beb6102e8"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7ef6b5942e6bfc5706301a18a62300c60db9af7f6368042227ccb7eeb22d0892"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-win32.whl", hash = "sha256:395161bbdbd04a8333b9ff9763a05e9ceb4fe210e3c7690f5e68cedd3d65d8e1"},
|
||||
{file = "regex-2022.10.31-cp39-cp39-win_amd64.whl", hash = "sha256:957403a978e10fb3ca42572a23e6f7badff39aa1ce2f4ade68ee452dc6807692"},
|
||||
{file = "regex-2022.10.31.tar.gz", hash = "sha256:a3a98921da9a1bf8457aeee6a551948a83601689e5ecdd736894ea9bbec77e83"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
|
||||
{file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
|
||||
]
|
||||
rich = [
|
||||
{file = "rich-12.6.0-py3-none-any.whl", hash = "sha256:a4eb26484f2c82589bd9a17c73d32a010b1e29d89f1604cd9bf3a2097b81bb5e"},
|
||||
{file = "rich-12.6.0.tar.gz", hash = "sha256:ba3a3775974105c221d31141f2c116f4fd65c5ceb0698657a11e9f295ec93fd0"},
|
||||
]
|
||||
six = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
soupsieve = [
|
||||
{file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"},
|
||||
{file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"},
|
||||
]
|
||||
typing-extensions = [
|
||||
{file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
|
||||
{file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
|
||||
]
|
||||
urllib3 = [
|
||||
{file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"},
|
||||
{file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"},
|
||||
]
|
||||
wcwidth = [
|
||||
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
|
||||
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
|
||||
]
|
||||
wikitextparser = [
|
||||
{file = "wikitextparser-0.51.1-py3-none-any.whl", hash = "sha256:f7da75a6607a5ff31f858dc1322bf204aec6b8a508ec777fbb2e722c2a53d5d9"},
|
||||
{file = "wikitextparser-0.51.1.tar.gz", hash = "sha256:d3eee1c18de0f2184d15f9ff1d9ad8dfd4f5b2ce50e7de4190409ca7bc848c11"},
|
||||
]
|
28
pyproject.toml
Normal file
28
pyproject.toml
Normal file
|
@ -0,0 +1,28 @@
|
|||
[tool.poetry]
|
||||
name = "masto-ld"
|
||||
version = "0.1.0"
|
||||
description = "A bot for prefixing and using linked data from Mastodon"
|
||||
authors = ["sneakers-the-rat <JLSaunders987@gmail.com>"]
|
||||
license = "AGPL-3.0"
|
||||
readme = "README.md"
|
||||
packages = [{include = "masto_ld"}]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
pydantic = {extras = ["dotenv", "email"], version = "^1.10.2"}
|
||||
mastodon-py = "^1.5.2"
|
||||
pyparsing = "^3.0.9"
|
||||
rich = "^12.6.0"
|
||||
beautifulsoup4 = "^4.11.1"
|
||||
lxml = "^4.9.1"
|
||||
pypandoc = "^1.10"
|
||||
requests = "^2.28.1"
|
||||
wikitextparser = "^0.51.1"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
masto_ld = 'masto_ld.main:masto_ld'
|
||||
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
Loading…
Reference in a new issue