more changes

This commit is contained in:
Izalia Mae 2021-11-16 18:55:29 -05:00
parent 695d8dc50f
commit f03c698ac2
7 changed files with 100 additions and 13 deletions

View file

@ -3,6 +3,7 @@ import json, mimetypes
from datetime import datetime, timezone from datetime import datetime, timezone
from functools import partial from functools import partial
from typing import Union from typing import Union
from xml.etree.ElementTree import fromstring
from .dotdict import DotDict from .dotdict import DotDict
from .misc import DateString, Url, boolean from .misc import DateString, Url, boolean
@ -482,3 +483,72 @@ class WellknownNodeinfo(DotDict):
'href': path 'href': path
}) })
class Hostmeta(str):
def __new__(cls, text):
return str.__new__(cls, text)
@classmethod
def new(cls, domain):
return cls(f'<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" template="https://{domain}/.well-known/webfinger?resource={{uri}}"/></XRD>')
@property
def link(self):
return Url(fromstring(self)[0].attrib['template'])
class Webfinger(DotDict):
@property
def profile(self):
for link in self.links:
if link['rel'] == 'http://webfinger.net/rel/profile-page':
return link['href']
@property
def actor(self):
for link in self.links:
if link['rel'] == 'self':
return link['href']
@property
def fullname(self):
return self.subject[5:]
@property
def handle(self):
return self.fullname.split('@')[0]
@property
def domain(self):
return self.fullname.split('@')[1]
@classmethod
def new(cls, handle, domain, actor, profile=None):
data = cls(
subject = f'acct:{handle}@{domain}',
aliases = [actor],
links = [
{
'rel': 'self',
'type': 'application/activity+json',
'href': actor
}
]
)
if profile:
data.aliases.append(profile)
data.links.append({
'rel': 'http://webfinger.net/rel/profile-page',
'type': 'text/html',
'href': profile
})
return data

View file

@ -105,7 +105,7 @@ class BaseCache(OrderedDict):
self[key]['timestamp'] = timestamp + self.ttl self[key]['timestamp'] = timestamp + self.ttl
self.move_to_end(key) self.move_to_end(key)
return item.data return item
## This doesn't work for some reason ## This doesn't work for some reason

View file

@ -43,8 +43,8 @@ class PasswordHasher:
def get_config(self, key): def get_config(self, key):
key = self.aliases.get(key, key) key = self.aliases.get(key, key)
self[key] value = self.config[key]
return self.get(key) / 1024 if key == 'memory_cost' else self.get(key) return value / 1024 if key == 'memory_cost' else value
def set_config(self, key, value): def set_config(self, key, value):

View file

@ -114,6 +114,9 @@ class ApplicationBase:
async def handle_request(self, request, response, path=None): async def handle_request(self, request, response, path=None):
if request.host not in self.cfg.hosts and not request.path.startswith('/framework'):
raise error.NotFound(f'Host not handled on this server: {request.host}')
handler = self.get_route(path or request.path, request.method) handler = self.get_route(path or request.path, request.method)
await self.handle_middleware(request) await self.handle_middleware(request)

View file

@ -43,6 +43,11 @@ class Config(BaseConfig):
self.default_headers['server'] = f'{self.name}/{__version__}' self.default_headers['server'] = f'{self.name}/{__version__}'
@property
def hosts(self):
return (self.host, self.web_host, *self.alt_hosts)
def parse_value(self, key, value): def parse_value(self, key, value):
if self._startup: if self._startup:
return value return value

View file

@ -132,7 +132,7 @@ def set_default_client(client=None):
@lru_cache(maxsize=512) @lru_cache(maxsize=512)
def fetch_actor(url): def fetch_actor(url):
if not Client: if not Client:
raise ValueError('Please set global client with "SetRequestsClient(client)"') raise ValueError('Please set global client with "HttpUrllibClient.set_global()"')
url = url.split('#')[0] url = url.split('#')[0]
headers = {'Accept': 'application/activity+json'} headers = {'Accept': 'application/activity+json'}
@ -165,7 +165,7 @@ def fetch_actor(url):
@lru_cache(maxsize=512) @lru_cache(maxsize=512)
def fetch_instance(domain): def fetch_instance(domain):
if not Client: if not Client:
raise ValueError('Please set global client with "SetRequestsClient(client)"') raise ValueError('Please set global client with "HttpUrllibClient.set_global()"')
headers = {'Accept': 'application/json'} headers = {'Accept': 'application/json'}
resp = Client.request(f'https://{domain}/api/v1/instance', headers=headers) resp = Client.request(f'https://{domain}/api/v1/instance', headers=headers)
@ -184,7 +184,7 @@ def fetch_instance(domain):
@lru_cache(maxsize=512) @lru_cache(maxsize=512)
def fetch_nodeinfo(domain): def fetch_nodeinfo(domain):
if not Client: if not Client:
raise ValueError('Please set global client with HttpRequestsClient.set_global()') raise ValueError('Please set global client with HttpUrllibClient.set_global()')
webfinger = Client.request(f'https://{domain}/.well-known/nodeinfo') webfinger = Client.request(f'https://{domain}/.well-known/nodeinfo')
webfinger_data = DotDict(webfinger.body) webfinger_data = DotDict(webfinger.body)
@ -201,7 +201,7 @@ def fetch_nodeinfo(domain):
@lru_cache(maxsize=512) @lru_cache(maxsize=512)
def fetch_webfinger_account(handle, domain): def fetch_webfinger_account(handle, domain):
if not Client: if not Client:
raise ValueError('Please set global client with HttpRequestsClient.set_global()') raise ValueError('Please set global client with HttpUrllibClient.set_global()')
data = DefaultDotDict() data = DefaultDotDict()
webfinger = Client.request(f'https://{domain}/.well-known/webfinger?resource=acct:{handle}@{domain}') webfinger = Client.request(f'https://{domain}/.well-known/webfinger?resource=acct:{handle}@{domain}')

View file

@ -321,6 +321,7 @@ def prompt(prompt, default=None, valtype=str, options=[], password=False):
prompt += '\n' prompt += '\n'
if options: if options:
options = [str(opt) for opt in options]
opt = '/'.join(options) opt = '/'.join(options)
prompt += f'[{opt}]' prompt += f'[{opt}]'
@ -442,7 +443,7 @@ def time_function(func, *args, passes=1, use_gc=True, **kwargs):
return timer.timeit(1) return timer.timeit(1)
def time_function_pprint(func, *args, passes=5, use_gc=True, floatlen=3, **kwargs): def time_function_pprint(func, *args, passes=5, use_gc=True, floatout=True, **kwargs):
'''Run a function and print out the time it took for each pass, the average and total '''Run a function and print out the time it took for each pass, the average and total
Arguments: Arguments:
@ -451,25 +452,33 @@ def time_function_pprint(func, *args, passes=5, use_gc=True, floatlen=3, **kwarg
kwargs (dict(str:various)): The keyword arguments to be passed to the timed function kwargs (dict(str:various)): The keyword arguments to be passed to the timed function
passes (int): How many times the timed function should be run passes (int): How many times the timed function should be run
use_gc (bool): If True, keep garbage collection enabled use_gc (bool): If True, keep garbage collection enabled
floatlen (int): The amount of decimal places each result should have
Return: Return:
None: The data gets printed to stdout None: The data gets printed to stdout
''' '''
parse_time = lambda num: f'{round(num, floatlen)}s'
times = [] times = []
for idx in range(0, passes): for idx in range(0, passes):
passtime = time_function(func, *args, **kwargs, passes=1, use_gc=use_gc) passtime = time_function(func, *args, **kwargs, passes=1, use_gc=use_gc)
times.append(passtime) times.append(passtime)
print(f'Pass {idx+1}: {parse_time(passtime)}')
if not floatout:
print(f'Pass {idx+1}: {passtime:.0f}')
else:
print(f'Pass {idx+1}: {passtime:.8f}')
average = statistics.fmean(times) average = statistics.fmean(times)
print('-----------------') print('-----------------')
print(f'Average: {parse_time(average)}') if not floatout:
print(f'Total: {parse_time(sum(times))}') print(f'Average: {average:.0f}')
print(f'Total: {sum(times):.0f}')
else:
print(f'Average: {average:.8f}')
print(f'Total: {sum(times):.8f}')
def timestamp(dtobj=None, utc=False): def timestamp(dtobj=None, utc=False):