move pandoc around, make async+lru_cached'd
parent
b6f44bcd45
commit
d6870b6040
|
@ -15,7 +15,7 @@ version = "0.1.0"
|
|||
description = "The Arcology is a Multi-domain Web Site Engine for Org Roam Files"
|
||||
authors = ["Ryan Rix <code@whatthefuck.computer>"]
|
||||
|
||||
include = ["static", "templates"]
|
||||
include = ["static", "templates", "pandoc"]
|
||||
#+end_src
|
||||
|
||||
#+begin_src toml :tangle pyproject.toml
|
||||
|
@ -49,6 +49,7 @@ asyncinotify = "^2.0.2"
|
|||
transitions = "^0.8.11"
|
||||
graphviz = "^0.19.1"
|
||||
pygraphviz = "^1.9"
|
||||
async-lru = "^1.0.3"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
ipdb = "^0.13"
|
||||
|
|
|
@ -65,7 +65,7 @@ async def render_page_from_key(request: Request, key: str, engine, site) -> Opti
|
|||
:ROAM_ALIASES: "Arcology Atom Generator"
|
||||
:END:
|
||||
|
||||
This similarly renders an ATOM feed using the [[id:arcology/atom-gen][Arcology Atom Generator]]:
|
||||
This similarly renders an ATOM feed using the [[id:arcology/atom-gen][Arcology Atom Generator]]. Note that =pypandoc= doesn't support user-defined templates, and so i'm shelling out to =pandoc= directly. Probably shouldn't have reached for that thing in the first place! oh well.
|
||||
|
||||
#+begin_src python :tangle arcology/routing/util.py :mkdirp yes
|
||||
import re
|
||||
|
@ -75,7 +75,43 @@ from arcology.html import rewrite_html
|
|||
from arcology.key import ArcologyKey
|
||||
from arcology.parse import parse_sexp, print_sexp
|
||||
from arcology.arroyo import Page
|
||||
#+end_src
|
||||
|
||||
This is pretty straightforward, except I stick an [[https://docs.python.org/3/library/functools.html#functools.lru_cache][LRU cache]] in the middle of it so that feed readers aren't constantly invoking Pandoc.
|
||||
|
||||
#+begin_src python :tangle arcology/routing/util.py :mkdirp yes
|
||||
from async_lru import alru_cache
|
||||
|
||||
class ExportException(BaseException):
|
||||
code: int
|
||||
stderr: str
|
||||
|
||||
@alru_cache(maxsize=64)
|
||||
async def export_pandoc(file: str) -> str:
|
||||
proc = await asyncio.create_subprocess_shell(
|
||||
f"pandoc {file} --lua-filter=./arcology/pandoc/make-atom.lua --template=./arcology/pandoc/atom.xml -s",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if proc.returncode == 0:
|
||||
return stdout.decode()
|
||||
else:
|
||||
raise ExportExeption(code=proc.returncode, stderr=stderr)
|
||||
|
||||
async def render_feed_from_file(request: Request, file: str, engine, site) -> Optional[Response]:
|
||||
with Session(engine) as session:
|
||||
p = Page.from_file(file, session)
|
||||
if p is None:
|
||||
raise HTTPException(status_code=404, detail="Feed not found.")
|
||||
try:
|
||||
xml = await export_pandoc(file)
|
||||
except ExportException as e:
|
||||
raise HTTPException(status_code=500, detail=f"pandoc exited {e.code} w/ {e.stderr}")
|
||||
|
||||
return hydrate_feed(file, xml, session)
|
||||
#+end_src
|
||||
|
||||
#+begin_src python :tangle arcology/routing/util.py :mkdirp yes
|
||||
def hydrate_feed(filename: str, xml: str, session) -> str:
|
||||
page = Page.from_file(filename, session)
|
||||
def feed_page_replacement_fn(match):
|
||||
|
@ -87,27 +123,11 @@ def hydrate_feed(filename: str, xml: str, session) -> str:
|
|||
out_xml = re.sub(r'{ARCOLOGY_FEED_PAGE}', akey.to_url(), out_xml)
|
||||
out_xml = rewrite_html(out_xml, session)
|
||||
return out_xml
|
||||
|
||||
async def render_feed_from_file(request: Request, file: str, engine, site) -> Optional[Response]:
|
||||
with Session(engine) as session:
|
||||
p = Page.from_file(file, session)
|
||||
if p is None:
|
||||
raise HTTPException(status_code=404, detail="Feed not found.")
|
||||
proc = await asyncio.create_subprocess_shell(
|
||||
f"pandoc {file} --lua-filter=./pandoc/make-atom.lua --template=./pandoc/atom.xml -s -V feedid={p.key}",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if proc.returncode == 0:
|
||||
return hydrate_feed(file, stdout.decode(), session)
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f"pandoc exited {proc.returncode} w/ {stderr}")
|
||||
# can't use pypandoc here, just use asyncio.create_subprocess_shell and do it yourself https://docs.python.org/3/library/asyncio-subprocess.html
|
||||
#+end_src
|
||||
|
||||
I had some real trouble figuring out how to get Pandoc to spit out [[https://validator.w3.org/feed/docs/atom.html][ATOM feeds]] and this is not "technically compliant" but I can do it with a combination of a [[https://pandoc.org/lua-filters.html][Lua filter]] which extracts headings' metadata in to variables which a [[https://pandoc.org/MANUAL.html#templates][custom template]] then renders out:
|
||||
|
||||
#+begin_src lua :tangle pandoc/make-atom.lua :mkdirp yes
|
||||
#+begin_src lua :tangle arcology/pandoc/make-atom.lua :mkdirp yes
|
||||
local utils = require 'pandoc.utils'
|
||||
|
||||
local entries = {}
|
||||
|
@ -162,7 +182,7 @@ return {
|
|||
|
||||
The template is basically unremarkable, but has the same issues that the HTML files have: they need to have their [[id:arcology/arroyo/hydrate][ID links fixed]].
|
||||
|
||||
#+begin_src xml :tangle pandoc/atom.xml
|
||||
#+begin_src xml :tangle arcology/pandoc/atom.xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
|
||||
|
@ -194,7 +214,7 @@ $endfor$
|
|||
And this can be confirmed to work with e.g. [[id:20220523T154158.992219][The Lion's Rear Site Feed]]:
|
||||
|
||||
#+begin_src shell :results verbatim :exports both
|
||||
pandoc ../thelionsrear_updates.org --lua-filter=pandoc/make-atom.lua --template=./pandoc/atom.xml -s -V feedid=https://thelionsrear.com
|
||||
pandoc ../thelionsrear_updates.org --lua-filter=arcology/pandoc/make-atom.lua --template=arcology/pandoc/atom.xml -s
|
||||
#+end_src
|
||||
|
||||
* NEXT This routing split between local and prod doesn't work because the routes aren't domain aware. and very greedy.
|
||||
|
@ -213,7 +233,7 @@ The "global" public router should be more tightened down than the [[id:20211219T
|
|||
from typing import Optional
|
||||
from fastapi import FastAPI, Request
|
||||
from sqlmodel import Session
|
||||
from fastapi.responses import HTMLResponse, FileResponse
|
||||
from fastapi.responses import HTMLResponse, FileResponse, Response
|
||||
|
||||
import arcology.sites as sites
|
||||
from arcology.routing.util import render_page_from_key, render_feed_from_file
|
||||
|
@ -230,6 +250,11 @@ def decorate_app(app: FastAPI) -> FastAPI:
|
|||
async def robots_txt(request: Request):
|
||||
return "arcology/static/robots.txt"
|
||||
|
||||
@app.get("/{sub_key:path}.xml", response_class=Response, name="base-route")
|
||||
async def feed_route(request: Request, sub_key: str):
|
||||
sub_key += ".xml" # dark laughter
|
||||
return Response(content=(await public_router(request, sub_key)), media_type="application/atom+xml")
|
||||
|
||||
@app.get("/{sub_key:path}", response_class=HTMLResponse, name="base-route")
|
||||
@app.get("/{sub_key:path}/", response_class=HTMLResponse, name="base-route")
|
||||
async def public_router(request: Request, sub_key: str):
|
||||
|
|
|
@ -21,7 +21,7 @@ This version of the Arcology is the most well-defined yet, I feel like I am boil
|
|||
- Arcology uses a databases generated with Arroyo: [[id:arcology/arroyo-page][Arroyo Arcology Generator]] containing:
|
||||
- [[id:arcology/arroyo][An Arroyo Module]] which extracts metadata from my org-mode files and persists them in a SQLite database
|
||||
- [[id:arcology/arroyo/sqlmodel][SQLModels]] for the metadata tables in the Arroyo database centered around the [[id:arcology/arroyo/page][Arcology Page which]] represents a single org-mode document with an Arcology publishing keyword.
|
||||
- Arcology queries the metadata and prints HTML presentations of the documents with a [[id:arcology/fastapi][FastAPI server]].
|
||||
- Arcology queries the metadata and prints HTML presentations of the documents with a [[id:arcology/fastapi][FastAPI server]] and a somewhat hacky encapsulation of the [[id:arcology/routing][Routing Logic]] including Pandoc HTML generation and post-processing.
|
||||
- An Arcology presents multiple [[id:20211219T144255.001827][Sites]], each with their own design language and content themes.
|
||||
- Arroyo's database is encoded with s-expressions, so [[id:20210922T085933.741529][=sexpdata= python package]] is used to parse these
|
||||
- [[id:20211218T222408.578567][=inotify= and a watchdog service]] will be used to wait for files to be sent to the [[id:20211120T220054.226284][Wobserver]] via [[id:cce/syncthing][Syncthing]]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from typing import Optional
|
||||
from fastapi import FastAPI, Request
|
||||
from sqlmodel import Session
|
||||
from fastapi.responses import HTMLResponse, FileResponse
|
||||
from fastapi.responses import HTMLResponse, FileResponse, Response
|
||||
|
||||
import arcology.sites as sites
|
||||
from arcology.routing.util import render_page_from_key, render_feed_from_file
|
||||
|
@ -18,6 +18,11 @@ def decorate_app(app: FastAPI) -> FastAPI:
|
|||
async def robots_txt(request: Request):
|
||||
return "arcology/static/robots.txt"
|
||||
|
||||
@app.get("/{sub_key:path}.xml", response_class=Response, name="base-route")
|
||||
async def feed_route(request: Request, sub_key: str):
|
||||
sub_key += ".xml" # dark laughter
|
||||
return Response(content=(await public_router(request, sub_key)), media_type="application/atom+xml")
|
||||
|
||||
@app.get("/{sub_key:path}", response_class=HTMLResponse, name="base-route")
|
||||
@app.get("/{sub_key:path}/", response_class=HTMLResponse, name="base-route")
|
||||
async def public_router(request: Request, sub_key: str):
|
||||
|
|
|
@ -39,6 +39,36 @@ from arcology.key import ArcologyKey
|
|||
from arcology.parse import parse_sexp, print_sexp
|
||||
from arcology.arroyo import Page
|
||||
|
||||
from async_lru import alru_cache
|
||||
|
||||
class ExportException(BaseException):
|
||||
code: int
|
||||
stderr: str
|
||||
|
||||
@alru_cache(maxsize=64)
|
||||
async def export_pandoc(file: str) -> str:
|
||||
proc = await asyncio.create_subprocess_shell(
|
||||
f"pandoc {file} --lua-filter=./arcology/pandoc/make-atom.lua --template=./arcology/pandoc/atom.xml -s",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if proc.returncode == 0:
|
||||
return stdout.decode()
|
||||
else:
|
||||
raise ExportExeption(code=proc.returncode, stderr=stderr)
|
||||
|
||||
async def render_feed_from_file(request: Request, file: str, engine, site) -> Optional[Response]:
|
||||
with Session(engine) as session:
|
||||
p = Page.from_file(file, session)
|
||||
if p is None:
|
||||
raise HTTPException(status_code=404, detail="Feed not found.")
|
||||
try:
|
||||
xml = await export_pandoc(file)
|
||||
except ExportException as e:
|
||||
raise HTTPException(status_code=500, detail=f"pandoc exited {e.code} w/ {e.stderr}")
|
||||
|
||||
return hydrate_feed(file, xml, session)
|
||||
|
||||
def hydrate_feed(filename: str, xml: str, session) -> str:
|
||||
page = Page.from_file(filename, session)
|
||||
def feed_page_replacement_fn(match):
|
||||
|
@ -50,19 +80,3 @@ def hydrate_feed(filename: str, xml: str, session) -> str:
|
|||
out_xml = re.sub(r'{ARCOLOGY_FEED_PAGE}', akey.to_url(), out_xml)
|
||||
out_xml = rewrite_html(out_xml, session)
|
||||
return out_xml
|
||||
|
||||
async def render_feed_from_file(request: Request, file: str, engine, site) -> Optional[Response]:
|
||||
with Session(engine) as session:
|
||||
p = Page.from_file(file, session)
|
||||
if p is None:
|
||||
raise HTTPException(status_code=404, detail="Feed not found.")
|
||||
proc = await asyncio.create_subprocess_shell(
|
||||
f"pandoc {file} --lua-filter=./pandoc/make-atom.lua --template=./pandoc/atom.xml -s -V feedid={p.key}",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if proc.returncode == 0:
|
||||
return hydrate_feed(file, stdout.decode(), session)
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail=f"pandoc exited {proc.returncode} w/ {stderr}")
|
||||
# can't use pypandoc here, just use asyncio.create_subprocess_shell and do it yourself https://docs.python.org/3/library/asyncio-subprocess.html
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[[package]]
|
||||
name = "anyio"
|
||||
version = "3.5.0"
|
||||
version = "3.6.1"
|
||||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -12,7 +12,7 @@ sniffio = ">=1.1"
|
|||
|
||||
[package.extras]
|
||||
doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"]
|
||||
test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"]
|
||||
test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"]
|
||||
trio = ["trio (>=0.16)"]
|
||||
|
||||
[[package]]
|
||||
|
@ -25,7 +25,7 @@ python-versions = "*"
|
|||
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.5.1"
|
||||
version = "3.5.2"
|
||||
description = "ASGI specs, helper code, and adapters"
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -48,9 +48,17 @@ six = "*"
|
|||
[package.extras]
|
||||
test = ["astroid", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "async-lru"
|
||||
version = "1.0.3"
|
||||
description = "Simple lru_cache for asyncio"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "asyncinotify"
|
||||
version = "2.0.2"
|
||||
version = "2.0.3"
|
||||
description = "A simple optionally-async python inotify library, focused on simplicity of use and operation, and leveraging modern Python features"
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -339,8 +347,8 @@ tests = ["pytest"]
|
|||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "1.9.0"
|
||||
description = "Data validation and settings management using python 3.6 type hinting"
|
||||
version = "1.9.1"
|
||||
description = "Data validation and settings management using python type hints"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6.1"
|
||||
|
@ -370,7 +378,7 @@ python-versions = ">=3.8"
|
|||
|
||||
[[package]]
|
||||
name = "pypandoc"
|
||||
version = "1.8"
|
||||
version = "1.8.1"
|
||||
description = "Thin wrapper for pandoc."
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -496,14 +504,14 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
|||
|
||||
[[package]]
|
||||
name = "traitlets"
|
||||
version = "5.2.0"
|
||||
description = "Traitlets Python configuration system"
|
||||
version = "5.2.1.post0"
|
||||
description = ""
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
test = ["pytest", "pre-commit"]
|
||||
test = ["pre-commit", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "transitions"
|
||||
|
@ -555,28 +563,32 @@ python-versions = "*"
|
|||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "fcaaf4b0bbd718619d3d202fc8eba03bd2c961daa9f665758c8124755ea83b53"
|
||||
content-hash = "52475a9aa337b0381350de9e0c053f9083b90fd283f5bdfc955ba54d9c29b5f3"
|
||||
|
||||
[metadata.files]
|
||||
anyio = [
|
||||
{file = "anyio-3.5.0-py3-none-any.whl", hash = "sha256:b5fa16c5ff93fa1046f2eeb5bbff2dad4d3514d6cda61d02816dba34fa8c3c2e"},
|
||||
{file = "anyio-3.5.0.tar.gz", hash = "sha256:a0aeffe2fb1fdf374a8e4b471444f0f3ac4fb9f5a5b542b48824475e0042a5a6"},
|
||||
{file = "anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"},
|
||||
{file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"},
|
||||
]
|
||||
appnope = [
|
||||
{file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
|
||||
{file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
|
||||
]
|
||||
asgiref = [
|
||||
{file = "asgiref-3.5.1-py3-none-any.whl", hash = "sha256:45a429524fba18aba9d512498b19d220c4d628e75b40cf5c627524dbaebc5cc1"},
|
||||
{file = "asgiref-3.5.1.tar.gz", hash = "sha256:fddeea3c53fa99d0cdb613c3941cc6e52d822491fc2753fba25768fb5bf4e865"},
|
||||
{file = "asgiref-3.5.2-py3-none-any.whl", hash = "sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4"},
|
||||
{file = "asgiref-3.5.2.tar.gz", hash = "sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424"},
|
||||
]
|
||||
asttokens = [
|
||||
{file = "asttokens-2.0.5-py2.py3-none-any.whl", hash = "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c"},
|
||||
{file = "asttokens-2.0.5.tar.gz", hash = "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5"},
|
||||
]
|
||||
async-lru = [
|
||||
{file = "async-lru-1.0.3.tar.gz", hash = "sha256:c2cb9b2915eb14e6cf3e717154b40f715bf90e596d73623677affd0d1fbcd32a"},
|
||||
{file = "async_lru-1.0.3-py3-none-any.whl", hash = "sha256:ea692c303feb6211ff260d230dae1583636f13e05c9ae616eada77855b7f415c"},
|
||||
]
|
||||
asyncinotify = [
|
||||
{file = "asyncinotify-2.0.2-py3-none-any.whl", hash = "sha256:26fa85d282df0066ab423cd96754d7ea07e6013d8a69a51e573303dbd0d2dff6"},
|
||||
{file = "asyncinotify-2.0.2.tar.gz", hash = "sha256:867cc056d88fc07aa8b3d1dc5b9c3c911cdd6130a4df5f67beb1fdecfd37b164"},
|
||||
{file = "asyncinotify-2.0.3-py3-none-any.whl", hash = "sha256:51532a1709327c35f5eeeb6d00e345e641a48364984af4aea3784adb61ea2ed7"},
|
||||
{file = "asyncinotify-2.0.3.tar.gz", hash = "sha256:a14baf680a3d3e1cf54e082ab56f56c475d59d3644cfc25c00c460e56d9bbdf7"},
|
||||
]
|
||||
backcall = [
|
||||
{file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
|
||||
|
@ -765,41 +777,41 @@ pure-eval = [
|
|||
{file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"},
|
||||
]
|
||||
pydantic = [
|
||||
{file = "pydantic-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb23bcc093697cdea2708baae4f9ba0e972960a835af22560f6ae4e7e47d33f5"},
|
||||
{file = "pydantic-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1d5278bd9f0eee04a44c712982343103bba63507480bfd2fc2790fa70cd64cf4"},
|
||||
{file = "pydantic-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab624700dc145aa809e6f3ec93fb8e7d0f99d9023b713f6a953637429b437d37"},
|
||||
{file = "pydantic-1.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8d7da6f1c1049eefb718d43d99ad73100c958a5367d30b9321b092771e96c25"},
|
||||
{file = "pydantic-1.9.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3c3b035103bd4e2e4a28da9da7ef2fa47b00ee4a9cf4f1a735214c1bcd05e0f6"},
|
||||
{file = "pydantic-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3011b975c973819883842c5ab925a4e4298dffccf7782c55ec3580ed17dc464c"},
|
||||
{file = "pydantic-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:086254884d10d3ba16da0588604ffdc5aab3f7f09557b998373e885c690dd398"},
|
||||
{file = "pydantic-1.9.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0fe476769acaa7fcddd17cadd172b156b53546ec3614a4d880e5d29ea5fbce65"},
|
||||
{file = "pydantic-1.9.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8e9dcf1ac499679aceedac7e7ca6d8641f0193c591a2d090282aaf8e9445a46"},
|
||||
{file = "pydantic-1.9.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1e4c28f30e767fd07f2ddc6f74f41f034d1dd6bc526cd59e63a82fe8bb9ef4c"},
|
||||
{file = "pydantic-1.9.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c86229333cabaaa8c51cf971496f10318c4734cf7b641f08af0a6fbf17ca3054"},
|
||||
{file = "pydantic-1.9.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:c0727bda6e38144d464daec31dff936a82917f431d9c39c39c60a26567eae3ed"},
|
||||
{file = "pydantic-1.9.0-cp36-cp36m-win_amd64.whl", hash = "sha256:dee5ef83a76ac31ab0c78c10bd7d5437bfdb6358c95b91f1ba7ff7b76f9996a1"},
|
||||
{file = "pydantic-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9c9bdb3af48e242838f9f6e6127de9be7063aad17b32215ccc36a09c5cf1070"},
|
||||
{file = "pydantic-1.9.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ee7e3209db1e468341ef41fe263eb655f67f5c5a76c924044314e139a1103a2"},
|
||||
{file = "pydantic-1.9.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b6037175234850ffd094ca77bf60fb54b08b5b22bc85865331dd3bda7a02fa1"},
|
||||
{file = "pydantic-1.9.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b2571db88c636d862b35090ccf92bf24004393f85c8870a37f42d9f23d13e032"},
|
||||
{file = "pydantic-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8b5ac0f1c83d31b324e57a273da59197c83d1bb18171e512908fe5dc7278a1d6"},
|
||||
{file = "pydantic-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bbbc94d0c94dd80b3340fc4f04fd4d701f4b038ebad72c39693c794fd3bc2d9d"},
|
||||
{file = "pydantic-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e0896200b6a40197405af18828da49f067c2fa1f821491bc8f5bde241ef3f7d7"},
|
||||
{file = "pydantic-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bdfdadb5994b44bd5579cfa7c9b0e1b0e540c952d56f627eb227851cda9db77"},
|
||||
{file = "pydantic-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:574936363cd4b9eed8acdd6b80d0143162f2eb654d96cb3a8ee91d3e64bf4cf9"},
|
||||
{file = "pydantic-1.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c556695b699f648c58373b542534308922c46a1cda06ea47bc9ca45ef5b39ae6"},
|
||||
{file = "pydantic-1.9.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f947352c3434e8b937e3aa8f96f47bdfe6d92779e44bb3f41e4c213ba6a32145"},
|
||||
{file = "pydantic-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5e48ef4a8b8c066c4a31409d91d7ca372a774d0212da2787c0d32f8045b1e034"},
|
||||
{file = "pydantic-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:96f240bce182ca7fe045c76bcebfa0b0534a1bf402ed05914a6f1dadff91877f"},
|
||||
{file = "pydantic-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:815ddebb2792efd4bba5488bc8fde09c29e8ca3227d27cf1c6990fc830fd292b"},
|
||||
{file = "pydantic-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c5b77947b9e85a54848343928b597b4f74fc364b70926b3c4441ff52620640c"},
|
||||
{file = "pydantic-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c68c3bc88dbda2a6805e9a142ce84782d3930f8fdd9655430d8576315ad97ce"},
|
||||
{file = "pydantic-1.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a79330f8571faf71bf93667d3ee054609816f10a259a109a0738dac983b23c3"},
|
||||
{file = "pydantic-1.9.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f5a64b64ddf4c99fe201ac2724daada8595ada0d102ab96d019c1555c2d6441d"},
|
||||
{file = "pydantic-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a733965f1a2b4090a5238d40d983dcd78f3ecea221c7af1497b845a9709c1721"},
|
||||
{file = "pydantic-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cc6a4cb8a118ffec2ca5fcb47afbacb4f16d0ab8b7350ddea5e8ef7bcc53a16"},
|
||||
{file = "pydantic-1.9.0-py3-none-any.whl", hash = "sha256:085ca1de245782e9b46cefcf99deecc67d418737a1fd3f6a4f511344b613a5b3"},
|
||||
{file = "pydantic-1.9.0.tar.gz", hash = "sha256:742645059757a56ecd886faf4ed2441b9c0cd406079c2b4bee51bcc3fbcd510a"},
|
||||
{file = "pydantic-1.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8098a724c2784bf03e8070993f6d46aa2eeca031f8d8a048dff277703e6e193"},
|
||||
{file = "pydantic-1.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c320c64dd876e45254bdd350f0179da737463eea41c43bacbee9d8c9d1021f11"},
|
||||
{file = "pydantic-1.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18f3e912f9ad1bdec27fb06b8198a2ccc32f201e24174cec1b3424dda605a310"},
|
||||
{file = "pydantic-1.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11951b404e08b01b151222a1cb1a9f0a860a8153ce8334149ab9199cd198131"},
|
||||
{file = "pydantic-1.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8bc541a405423ce0e51c19f637050acdbdf8feca34150e0d17f675e72d119580"},
|
||||
{file = "pydantic-1.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e565a785233c2d03724c4dc55464559639b1ba9ecf091288dd47ad9c629433bd"},
|
||||
{file = "pydantic-1.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:a4a88dcd6ff8fd47c18b3a3709a89adb39a6373f4482e04c1b765045c7e282fd"},
|
||||
{file = "pydantic-1.9.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:447d5521575f18e18240906beadc58551e97ec98142266e521c34968c76c8761"},
|
||||
{file = "pydantic-1.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:985ceb5d0a86fcaa61e45781e567a59baa0da292d5ed2e490d612d0de5796918"},
|
||||
{file = "pydantic-1.9.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:059b6c1795170809103a1538255883e1983e5b831faea6558ef873d4955b4a74"},
|
||||
{file = "pydantic-1.9.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d12f96b5b64bec3f43c8e82b4aab7599d0157f11c798c9f9c528a72b9e0b339a"},
|
||||
{file = "pydantic-1.9.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ae72f8098acb368d877b210ebe02ba12585e77bd0db78ac04a1ee9b9f5dd2166"},
|
||||
{file = "pydantic-1.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:79b485767c13788ee314669008d01f9ef3bc05db9ea3298f6a50d3ef596a154b"},
|
||||
{file = "pydantic-1.9.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:494f7c8537f0c02b740c229af4cb47c0d39840b829ecdcfc93d91dcbb0779892"},
|
||||
{file = "pydantic-1.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0f047e11febe5c3198ed346b507e1d010330d56ad615a7e0a89fae604065a0e"},
|
||||
{file = "pydantic-1.9.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:969dd06110cb780da01336b281f53e2e7eb3a482831df441fb65dd30403f4608"},
|
||||
{file = "pydantic-1.9.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:177071dfc0df6248fd22b43036f936cfe2508077a72af0933d0c1fa269b18537"},
|
||||
{file = "pydantic-1.9.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9bcf8b6e011be08fb729d110f3e22e654a50f8a826b0575c7196616780683380"},
|
||||
{file = "pydantic-1.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a955260d47f03df08acf45689bd163ed9df82c0e0124beb4251b1290fa7ae728"},
|
||||
{file = "pydantic-1.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9ce157d979f742a915b75f792dbd6aa63b8eccaf46a1005ba03aa8a986bde34a"},
|
||||
{file = "pydantic-1.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0bf07cab5b279859c253d26a9194a8906e6f4a210063b84b433cf90a569de0c1"},
|
||||
{file = "pydantic-1.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d93d4e95eacd313d2c765ebe40d49ca9dd2ed90e5b37d0d421c597af830c195"},
|
||||
{file = "pydantic-1.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1542636a39c4892c4f4fa6270696902acb186a9aaeac6f6cf92ce6ae2e88564b"},
|
||||
{file = "pydantic-1.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a9af62e9b5b9bc67b2a195ebc2c2662fdf498a822d62f902bf27cccb52dbbf49"},
|
||||
{file = "pydantic-1.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fe4670cb32ea98ffbf5a1262f14c3e102cccd92b1869df3bb09538158ba90fe6"},
|
||||
{file = "pydantic-1.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:9f659a5ee95c8baa2436d392267988fd0f43eb774e5eb8739252e5a7e9cf07e0"},
|
||||
{file = "pydantic-1.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b83ba3825bc91dfa989d4eed76865e71aea3a6ca1388b59fc801ee04c4d8d0d6"},
|
||||
{file = "pydantic-1.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1dd8fecbad028cd89d04a46688d2fcc14423e8a196d5b0a5c65105664901f810"},
|
||||
{file = "pydantic-1.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02eefd7087268b711a3ff4db528e9916ac9aa18616da7bca69c1871d0b7a091f"},
|
||||
{file = "pydantic-1.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7eb57ba90929bac0b6cc2af2373893d80ac559adda6933e562dcfb375029acee"},
|
||||
{file = "pydantic-1.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4ce9ae9e91f46c344bec3b03d6ee9612802682c1551aaf627ad24045ce090761"},
|
||||
{file = "pydantic-1.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:72ccb318bf0c9ab97fc04c10c37683d9eea952ed526707fabf9ac5ae59b701fd"},
|
||||
{file = "pydantic-1.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:61b6760b08b7c395975d893e0b814a11cf011ebb24f7d869e7118f5a339a82e1"},
|
||||
{file = "pydantic-1.9.1-py3-none-any.whl", hash = "sha256:4988c0f13c42bfa9ddd2fe2f569c9d54646ce84adc5de84228cfe83396f3bd58"},
|
||||
{file = "pydantic-1.9.1.tar.gz", hash = "sha256:1ed987c3ff29fff7fd8c3ea3a3ea877ad310aae2ef9889a119e22d3f2db0691a"},
|
||||
]
|
||||
pygments = [
|
||||
{file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"},
|
||||
|
@ -809,7 +821,8 @@ pygraphviz = [
|
|||
{file = "pygraphviz-1.9.zip", hash = "sha256:fa18f7c6cea28341a4e466ed0cf05682b0a68288afe8dd7c9426782f7c1ae01c"},
|
||||
]
|
||||
pypandoc = [
|
||||
{file = "pypandoc-1.8.tar.gz", hash = "sha256:f985ffdf0144e78b0b4809ea0595a279c2bd8c02b94d485c860c02777f3bd406"},
|
||||
{file = "pypandoc-1.8.1-py3-none-any.whl", hash = "sha256:3d7eda399f9169f16106362c55a8f12f30ab0575cfd2cdc6e1856b214cc4c38c"},
|
||||
{file = "pypandoc-1.8.1.tar.gz", hash = "sha256:8c1b651d338e8441843b991835f59d561a8473cfe63f0126d330fdb3cb518809"},
|
||||
]
|
||||
sexpdata = [
|
||||
{file = "sexpdata-0.0.3.tar.gz", hash = "sha256:1ac827a616c5e87ebb60fd6686fb86f8a166938c645f4089d92de3ffbdd494e0"},
|
||||
|
@ -881,8 +894,8 @@ toml = [
|
|||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||
]
|
||||
traitlets = [
|
||||
{file = "traitlets-5.2.0-py3-none-any.whl", hash = "sha256:9dd4025123fbe018a2092b2ad6984792f53ea3362c698f37473258b1fa97b0bc"},
|
||||
{file = "traitlets-5.2.0.tar.gz", hash = "sha256:60474f39bf1d39a11e0233090b99af3acee93bbc2281777e61dd8c87da8a0014"},
|
||||
{file = "traitlets-5.2.1.post0-py3-none-any.whl", hash = "sha256:f44b708d33d98b0addb40c29d148a761f44af740603a8fd0e2f8b5b27cf0f087"},
|
||||
{file = "traitlets-5.2.1.post0.tar.gz", hash = "sha256:70815ecb20ec619d1af28910ade523383be13754283aef90528eb3d47b77c5db"},
|
||||
]
|
||||
transitions = [
|
||||
{file = "transitions-0.8.11-py2.py3-none-any.whl", hash = "sha256:9525dd9b708b0a54bb4562a06a483d237e75c94547ba9831c81c6872d0ea1522"},
|
||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
description = "The Arcology is a Multi-domain Web Site Engine for Org Roam Files"
|
||||
authors = ["Ryan Rix <code@whatthefuck.computer>"]
|
||||
|
||||
include = ["static", "templates"]
|
||||
include = ["static", "templates", "pandoc"]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
@ -25,6 +25,7 @@ asyncinotify = "^2.0.2"
|
|||
transitions = "^0.8.11"
|
||||
graphviz = "^0.19.1"
|
||||
pygraphviz = "^1.9"
|
||||
async-lru = "^1.0.3"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
ipdb = "^0.13"
|
||||
|
|
Loading…
Reference in New Issue