Browse Source

move exclude definition to own file

closes #18
master
René Wagner 3 weeks ago
parent
commit
5c9e5267cf
  1. 3
      gus/build_index.py
  2. 213
      gus/crawl.py
  3. 197
      gus/excludes.py
  4. 2
      gus/lib/index_statistics.py
  5. 89
      poetry.lock

3
gus/build_index.py

@ -5,7 +5,8 @@ from datetime import datetime, timedelta
from urllib.parse import uses_relative, uses_netloc
from . import constants
from gus.crawl import EXCLUDED_URL_PREFIXES, should_skip
from gus.crawl import should_skip
from gus.excludes import EXCLUDED_URL_PREFIXES
from gus.lib.db_model import init_db, Page
from gus.lib.gemini import GeminiResource
from gus.lib.index_statistics import (

213
gus/crawl.py

@ -18,6 +18,7 @@ from urllib.parse import urljoin, uses_relative, uses_netloc
# import feedparser
import peewee
from gus.excludes import EXCLUDED_URL_PREFIXES, EXCLUDED_URL_PATHS
from . import constants
from gus.lib.db_model import init_db, Page, Link, Crawl
from gus.lib.gemini import GeminiResource, GeminiRobotFileParser
@ -28,213 +29,15 @@ import gus.lib.logging
uses_relative.append("gemini")
uses_netloc.append("gemini")
EXCLUDED_URL_PATTERN = re.compile(
r"^gemini://(\d{6}\.ch|almp\d{4}\.app|.*/_(revert|history)/).*",
flags=re.IGNORECASE
)
# These are checked against normalized_url, so they should be
# prepended with the gemini:// protocol, be all lowercased, and
# not have the port specified if it is 1965.
EXCLUDED_URL_PREFIXES = [
"gemini://localhost",
"gemini://example.org",
"gemini://example.com",
"gemini://www.youtube.com/",
"gemini://gemini.conman.org/test",
"gemini://gemini.circumlunar.space/users/fgaz/calculator/",
# all combinations of a tictactoe board
"gemini://tictactoe.lanterne.chilliet.eu",
# serving big files and slooow capsule -> takes to long to crawl
"gemini://kamalatta.ddnss.de/",
# Mastodon proxy
"gemini://mastogem.picasoft.net",
# ASCII art with emulated modem speed
"gemini://ansi.hrtk.in/",
"gemini://matrix.kiwifarms.net",
# ZachDeCooks songs
"gemini://songs.zachdecook.com/song.gmi.php/",
"gemini://songs.zachdecook.com/chord.svg/",
# kwiecien gemcast
"gemini://kwiecien.us/gemcast/",
# OmarPolos BSD ports
'gemini://gemini.omarpolo.com/cgi/gempkg',
# breaks crawl due to recursion overflow
"gemini://cadence.moe/chapo/",
"gemini://nixo.xyz/reply/",
"gemini://nixo.xyz/notify",
"gemini://gemini.thebackupbox.net/queryresponse",
"gemini://gem.garichankar.com/share_audio",
# mastodon mirror - too big to crawl
"gemini://vps01.rdelaage.ovh/",
# various failing resources on runjimmyrunrunyoufuckerrun.com
"gemini://runjimmyrunrunyoufuckerrun.com/fonts/",
"gemini://runjimmyrunrunyoufuckerrun.com/tmp/",
# Internal
"gemini://gus.guru/search/",
"gemini://gus.guru/v/search/",
"gemini://gus.guru/search?",
"gemini://gus.guru/v/search?",
"gemini://gus.guru/add-seed?",
"gemini://gus.guru/backlinks?",
"gemini://gus.guru/threads",
# Houston
"gemini://houston.coder.town/search?",
"gemini://houston.coder.town/search/",
# Geddit
"gemini://geddit.pitr.ca/post?",
"gemini://geddit.pitr.ca/c/",
"gemini://geddit.glv.one/post?",
"gemini://geddit.glv.one/c/",
# Marmaladefoo calculator
"gemini://gemini.marmaladefoo.com/cgi-bin/calc.cgi?",
# Individual weather pages
"gemini://acidic.website/cgi-bin/weather.tcl?",
"gemini://caolan.uk/weather/",
# Alex Schroeder's problematic stuff
"gemini://vault.transjovian.org/",
"gemini://transjovian.org/",
"gemini://alexschroeder.ch/",
"gemini://alexschroeder.ch:1967",
"gemini://communitywiki.org:1966/",
"gemini://communitywiki.org/",
"gemini://alexschroeder.ch/image_external",
"gemini://alexschroeder.ch/html/",
"gemini://alexschroeder.ch/diff/",
"gemini://alexschroeder.ch/history/",
"gemini://alexschroeder.ch/http",
"gemini://alexschroeder.ch/https",
"gemini://alexschroeder.ch/tag/",
"gemini://alexschroeder.ch/raw/",
"gemini://alexschroeder.ch/map/",
"gemini://alexschroeder.ch/do/comment",
"gemini://alexschroeder.ch/do/rc",
"gemini://alexschroeder.ch/do/rss",
"gemini://alexschroeder.ch/do/new",
"gemini://alexschroeder.ch/do/more",
"gemini://alexschroeder.ch/do/tags",
"gemini://alexschroeder.ch/do/match",
"gemini://alexschroeder.ch/do/search",
"gemini://alexschroeder.ch:1965/do/gallery/",
# communitywiki's problematic stuff
"gemini://communitywiki.org:1966/image_external",
"gemini://communitywiki.org:1966/html/",
"gemini://communitywiki.org:1966/diff/",
"gemini://communitywiki.org:1966/history/",
"gemini://communitywiki.org:1966/http",
"gemini://communitywiki.org:1966/https",
"gemini://communitywiki.org:1966/tag/",
"gemini://communitywiki.org:1966/raw/",
"gemini://communitywiki.org:1966/map/",
"gemini://communitywiki.org:1966/do/comment",
"gemini://communitywiki.org:1966/do/rc",
"gemini://communitywiki.org:1966/do/rss",
"gemini://communitywiki.org:1966/do/new",
"gemini://communitywiki.org:1966/do/more",
"gemini://communitywiki.org:1966/do/tags",
"gemini://communitywiki.org:1966/do/match",
"gemini://communitywiki.org:1966/do/search",
# mozz mailing list linkscraper
"gemini://mozz.us/files/gemini-links.gmi",
"gemini://gem.benscraft.info/mailing-list",
# gemini.techrights.org
"gemini://gemini.techrights.org/",
# youtube mirror
"gemini://pon.ix.tc/cgi-bin/youtube.cgi?",
"gemini://pon.ix.tc/youtube/",
# news mirrors - not our business
"gemini://guardian.shit.cx/",
"gemini://simplynews.metalune.xyz",
"gemini://illegaldrugs.net/cgi-bin/news.php?",
# wikipedia proxy
"gemini://wp.pitr.ca/",
"gemini://wp.glv.one/",
"gemini://wikipedia.geminet.org/",
# client torture test
"gemini://egsam.pitr.ca/",
"gemini://egsam.glv.one/",
# mozz's chat
"gemini://chat.mozz.us/stream",
"gemini://chat.mozz.us/submit",
# gopher proxy
"gemini://80h.dev/agena/",
# susa.net
"gemini://gemini.susa.net/cgi-bin/search?",
"gemini://gemini.susa.net/cgi-bin/twitter?",
"gemini://gemini.susa.net/cgi-bin/vim-search?",
"gemini://pboyd.io/cgi-bin/guestbook.pl,",
"gemini://gemini.spam.works/textfiles/",
"gemini://gemini.spam.works/mirrors/textfiles/",
# streams that never end...
"gemini://gemini.thebackupbox.net/radio",
"gemini://higeki.jp/radio",
# list of ~30000 stations, crawling takes too long
"gemini://gemini.tunerapp.org/stations/",
"gemini://tunerapp.org/stations/",
# this page inexplicably breaks both build_index, as well as elpher
# when I browse to it... I think it might have some weird encoding
# issues in its content or something, but that's a problem for a
# different day
"gemini://gemini.spam.works/users/dvn/archive/",
"gemini://gem.denarii.cloud/chaindata.zip",
# full web proxy
"gemini://drewdevault.com/cgi-bin/web.sh?",
# killing crawl, I think maybe because it's too big
"gemini://gem.denarii.cloud/pichaindata.zip",
# these threads seem to expire
"gemini://dioskouroi.xyz/thread",
# french news mirrors, there's just too much
"gemini://jpfox.fr/rss/",
]
EXCLUDED_URL_PATHS = [
"favicon.ico",
"favicon.txt",
"robots.txt",
"rss.txt",
"rss.xml",
]
CRAWL_DELAYS = {
"alexschroeder.ch": 5000,
"communitywiki.org": 5000,
}
EXCLUDED_URL_PATTERN = re.compile(
r"^gemini://(\d{6}\.ch|almp\d{4}\.app|.*/_(revert|history)/).*",
flags=re.IGNORECASE
)
def index_binary(resource, response):
logging.debug(
@ -425,15 +228,15 @@ def index_content(resource, response):
def should_skip(resource):
should_skip = False
for excluded_prefix in EXCLUDED_URL_PREFIXES:
for excluded_prefix in excludes.EXCLUDED_URL_PREFIXES:
if resource.normalized_url.startswith(excluded_prefix):
should_skip = True
break
for excluded_path in EXCLUDED_URL_PATHS:
for excluded_path in excludes.EXCLUDED_URL_PATHS:
if resource.urlsplit.path.lower().endswith(excluded_path):
should_skip = True
break
m = EXCLUDED_URL_PATTERN.match(resource.normalized_url)
m = excludes.EXCLUDED_URL_PATTERN.match(resource.normalized_url)
if m:
should_skip = True
return should_skip

197
gus/excludes.py

@ -0,0 +1,197 @@
# These are checked against normalized_url, so they should be
# prepended with the gemini:// protocol, be all lowercased, and
# not have the port specified if it is 1965.
EXCLUDED_URL_PREFIXES = [
"gemini://localhost",
"gemini://example.org",
"gemini://example.com",
"gemini://www.youtube.com/",
"gemini://gemini.conman.org/test",
"gemini://gemini.circumlunar.space/users/fgaz/calculator/",
# all combinations of a tictactoe board
"gemini://tictactoe.lanterne.chilliet.eu",
# serving big files and slooow capsule -> takes to long to crawl
"gemini://kamalatta.ddnss.de/",
# Mastodon proxy
"gemini://mastogem.picasoft.net",
# ASCII art with emulated modem speed
"gemini://ansi.hrtk.in/",
"gemini://matrix.kiwifarms.net",
# ZachDeCooks songs
"gemini://songs.zachdecook.com/song.gmi.php/",
"gemini://songs.zachdecook.com/chord.svg/",
# kwiecien gemcast
"gemini://kwiecien.us/gemcast/",
# OmarPolos BSD ports
'gemini://gemini.omarpolo.com/cgi/gempkg',
# breaks crawl due to recursion overflow
"gemini://cadence.moe/chapo/",
"gemini://nixo.xyz/reply/",
"gemini://nixo.xyz/notify",
"gemini://gemini.thebackupbox.net/queryresponse",
"gemini://gem.garichankar.com/share_audio",
# mastodon mirror - too big to crawl
"gemini://vps01.rdelaage.ovh/",
# various failing resources on runjimmyrunrunyoufuckerrun.com
"gemini://runjimmyrunrunyoufuckerrun.com/fonts/",
"gemini://runjimmyrunrunyoufuckerrun.com/tmp/",
# Internal
"gemini://gus.guru/search/",
"gemini://gus.guru/v/search/",
"gemini://gus.guru/search?",
"gemini://gus.guru/v/search?",
"gemini://gus.guru/add-seed?",
"gemini://gus.guru/backlinks?",
"gemini://gus.guru/threads",
# Houston
"gemini://houston.coder.town/search?",
"gemini://houston.coder.town/search/",
# Geddit
"gemini://geddit.pitr.ca/post?",
"gemini://geddit.pitr.ca/c/",
"gemini://geddit.glv.one/post?",
"gemini://geddit.glv.one/c/",
# Marmaladefoo calculator
"gemini://gemini.marmaladefoo.com/cgi-bin/calc.cgi?",
# Individual weather pages
"gemini://acidic.website/cgi-bin/weather.tcl?",
"gemini://caolan.uk/weather/",
# Alex Schroeder's problematic stuff
"gemini://vault.transjovian.org/",
"gemini://transjovian.org/",
"gemini://alexschroeder.ch/",
"gemini://alexschroeder.ch:1967",
"gemini://communitywiki.org:1966/",
"gemini://communitywiki.org/",
"gemini://alexschroeder.ch/image_external",
"gemini://alexschroeder.ch/html/",
"gemini://alexschroeder.ch/diff/",
"gemini://alexschroeder.ch/history/",
"gemini://alexschroeder.ch/http",
"gemini://alexschroeder.ch/https",
"gemini://alexschroeder.ch/tag/",
"gemini://alexschroeder.ch/raw/",
"gemini://alexschroeder.ch/map/",
"gemini://alexschroeder.ch/do/comment",
"gemini://alexschroeder.ch/do/rc",
"gemini://alexschroeder.ch/do/rss",
"gemini://alexschroeder.ch/do/new",
"gemini://alexschroeder.ch/do/more",
"gemini://alexschroeder.ch/do/tags",
"gemini://alexschroeder.ch/do/match",
"gemini://alexschroeder.ch/do/search",
"gemini://alexschroeder.ch:1965/do/gallery/",
# communitywiki's problematic stuff
"gemini://communitywiki.org:1966/image_external",
"gemini://communitywiki.org:1966/html/",
"gemini://communitywiki.org:1966/diff/",
"gemini://communitywiki.org:1966/history/",
"gemini://communitywiki.org:1966/http",
"gemini://communitywiki.org:1966/https",
"gemini://communitywiki.org:1966/tag/",
"gemini://communitywiki.org:1966/raw/",
"gemini://communitywiki.org:1966/map/",
"gemini://communitywiki.org:1966/do/comment",
"gemini://communitywiki.org:1966/do/rc",
"gemini://communitywiki.org:1966/do/rss",
"gemini://communitywiki.org:1966/do/new",
"gemini://communitywiki.org:1966/do/more",
"gemini://communitywiki.org:1966/do/tags",
"gemini://communitywiki.org:1966/do/match",
"gemini://communitywiki.org:1966/do/search",
# mozz mailing list linkscraper
"gemini://mozz.us/files/gemini-links.gmi",
"gemini://gem.benscraft.info/mailing-list",
# gemini.techrights.org
"gemini://gemini.techrights.org/",
# youtube mirror
"gemini://pon.ix.tc/cgi-bin/youtube.cgi?",
"gemini://pon.ix.tc/youtube/",
# news mirrors - not our business
"gemini://guardian.shit.cx/",
"gemini://simplynews.metalune.xyz",
"gemini://illegaldrugs.net/cgi-bin/news.php?",
"gemini://rawtext.club/~sloum/geminews",
# wikipedia proxy
"gemini://wp.pitr.ca/",
"gemini://wp.glv.one/",
"gemini://wikipedia.geminet.org/",
# client torture test
"gemini://egsam.pitr.ca/",
"gemini://egsam.glv.one/",
# mozz's chat
"gemini://chat.mozz.us/stream",
"gemini://chat.mozz.us/submit",
# gopher proxy
"gemini://80h.dev/agena/",
# susa.net
"gemini://gemini.susa.net/cgi-bin/search?",
"gemini://gemini.susa.net/cgi-bin/twitter?",
"gemini://gemini.susa.net/cgi-bin/vim-search?",
"gemini://pboyd.io/cgi-bin/guestbook.pl,",
"gemini://gemini.spam.works/textfiles/",
"gemini://gemini.spam.works/mirrors/textfiles/",
# streams that never end...
"gemini://gemini.thebackupbox.net/radio",
"gemini://higeki.jp/radio",
# list of ~30000 stations, crawling takes too long
"gemini://gemini.tunerapp.org/stations/",
"gemini://tunerapp.org/stations/",
# this page inexplicably breaks both build_index, as well as elpher
# when I browse to it... I think it might have some weird encoding
# issues in its content or something, but that's a problem for a
# different day
"gemini://gemini.spam.works/users/dvn/archive/",
"gemini://gem.denarii.cloud/chaindata.zip",
# full web proxy
"gemini://drewdevault.com/cgi-bin/web.sh?",
# killing crawl, I think maybe because it's too big
"gemini://gem.denarii.cloud/pichaindata.zip",
# these threads seem to expire
"gemini://dioskouroi.xyz/thread",
# french news mirrors, there's just too much
"gemini://jpfox.fr/rss/",
]
EXCLUDED_URL_PATHS = [
"favicon.ico",
"favicon.txt",
"robots.txt",
"rss.txt",
"rss.xml",
]

2
gus/lib/index_statistics.py

@ -3,7 +3,7 @@ from datetime import datetime
from peewee import fn, SQL
from gus.crawl import EXCLUDED_URL_PREFIXES
from gus.excludes import EXCLUDED_URL_PREFIXES
from gus.lib.db_model import Page, Crawl

89
poetry.lock

@ -92,7 +92,7 @@ pycparser = "*"
[[package]]
name = "click"
version = "8.0.0"
version = "8.0.1"
description = "Composable command line interface toolkit"
category = "dev"
optional = false
@ -100,6 +100,7 @@ python-versions = ">=3.6"
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
[[package]]
name = "colorama"
@ -138,7 +139,7 @@ test = ["pytest (>=6.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pret
[[package]]
name = "decorator"
version = "5.0.7"
version = "5.0.9"
description = "Decorators for Humans"
category = "dev"
optional = false
@ -310,7 +311,7 @@ i18n = ["Babel (>=0.8)"]
[[package]]
name = "markupsafe"
version = "2.0.0"
version = "2.0.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "main"
optional = false
@ -329,7 +330,7 @@ traitlets = "*"
[[package]]
name = "more-itertools"
version = "8.7.0"
version = "8.8.0"
description = "More routines for operating on iterables, beyond itertools"
category = "dev"
optional = false
@ -743,8 +744,8 @@ cffi = [
{file = "cffi-1.14.5.tar.gz", hash = "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"},
]
click = [
{file = "click-8.0.0-py3-none-any.whl", hash = "sha256:e90e62ced43dc8105fb9a26d62f0d9340b5c8db053a814e25d95c19873ae87db"},
{file = "click-8.0.0.tar.gz", hash = "sha256:7d8c289ee437bcb0316820ccee14aefcb056e58d31830ecab8e47eda6540e136"},
{file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"},
{file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"},
]
colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
@ -769,8 +770,8 @@ cryptography = [
{file = "cryptography-3.4.7.tar.gz", hash = "sha256:3d10de8116d25649631977cb37da6cbdd2d6fa0e0281d014a5b7d337255ca713"},
]
decorator = [
{file = "decorator-5.0.7-py3-none-any.whl", hash = "sha256:945d84890bb20cc4a2f4a31fc4311c0c473af65ea318617f13a7257c9a58bc98"},
{file = "decorator-5.0.7.tar.gz", hash = "sha256:6f201a6c4dac3d187352661f508b9364ec8091217442c9478f1f83c003a0f060"},
{file = "decorator-5.0.9-py3-none-any.whl", hash = "sha256:6e5c199c16f7a9f0e3a61a4a54b3d27e7dad0dbdde92b944426cb20914376323"},
{file = "decorator-5.0.9.tar.gz", hash = "sha256:72ecfba4320a893c53f9706bebb2d55c270c1e51a28789361aa93e4a21319ed5"},
]
feedparser = [
{file = "feedparser-5.2.1.tar.bz2", hash = "sha256:ce875495c90ebd74b179855449040003a1beb40cd13d5f037a0654251e260b02"},
@ -818,48 +819,48 @@ jinja2 = [
{file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"},
]
markupsafe = [
{file = "MarkupSafe-2.0.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2efaeb1baff547063bad2b2893a8f5e9c459c4624e1a96644bbba08910ae34e0"},
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:441ce2a8c17683d97e06447fcbccbdb057cbf587c78eb75ae43ea7858042fe2c"},
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:45535241baa0fc0ba2a43961a1ac7562ca3257f46c4c3e9c0de38b722be41bd1"},
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:90053234a6479738fd40d155268af631c7fca33365f964f2208867da1349294b"},
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3b54a9c68995ef4164567e2cd1a5e16db5dac30b2a50c39c82db8d4afaf14f63"},
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:f58b5ba13a5689ca8317b98439fccfbcc673acaaf8241c1869ceea40f5d585bf"},
{file = "MarkupSafe-2.0.0-cp36-cp36m-win32.whl", hash = "sha256:a00dce2d96587651ef4fa192c17e039e8cfab63087c67e7d263a5533c7dad715"},
{file = "MarkupSafe-2.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:007dc055dbce5b1104876acee177dbfd18757e19d562cd440182e1f492e96b95"},
{file = "MarkupSafe-2.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a08cd07d3c3c17cd33d9e66ea9dee8f8fc1c48e2d11bd88fd2dc515a602c709b"},
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:3c352ff634e289061711608f5e474ec38dbaa21e3e168820d53d5f4015e5b91b"},
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:32200f562daaab472921a11cbb63780f1654552ae49518196fc361ed8e12e901"},
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:fef86115fdad7ae774720d7103aa776144cf9b66673b4afa9bcaa7af990ed07b"},
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e79212d09fc0e224d20b43ad44bb0a0a3416d1e04cf6b45fed265114a5d43d20"},
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:79b2ae94fa991be023832e6bcc00f41dbc8e5fe9d997a02db965831402551730"},
{file = "MarkupSafe-2.0.0-cp37-cp37m-win32.whl", hash = "sha256:3261fae28155e5c8634dd7710635fe540a05b58f160cef7713c7700cb9980e66"},
{file = "MarkupSafe-2.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e4570d16f88c7f3032ed909dc9e905a17da14a1c4cfd92608e3fda4cb1208bbd"},
{file = "MarkupSafe-2.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f806bfd0f218477d7c46a11d3e52dc7f5fdfaa981b18202b7dc84bbc287463b"},
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e77e4b983e2441aff0c0d07ee711110c106b625f440292dfe02a2f60c8218bd6"},
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:031bf79a27d1c42f69c276d6221172417b47cb4b31cdc73d362a9bf5a1889b9f"},
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:83cf0228b2f694dcdba1374d5312f2277269d798e65f40344964f642935feac1"},
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4cc563836f13c57f1473bc02d1e01fc37bab70ad4ee6be297d58c1d66bc819bf"},
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d00a669e4a5bec3ee6dbeeeedd82a405ced19f8aeefb109a012ea88a45afff96"},
{file = "MarkupSafe-2.0.0-cp38-cp38-win32.whl", hash = "sha256:161d575fa49395860b75da5135162481768b11208490d5a2143ae6785123e77d"},
{file = "MarkupSafe-2.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:58bc9fce3e1557d463ef5cee05391a05745fd95ed660f23c1742c711712c0abb"},
{file = "MarkupSafe-2.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3fb47f97f1d338b943126e90b79cad50d4fcfa0b80637b5a9f468941dbbd9ce5"},
{file = "MarkupSafe-2.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dab0c685f21f4a6c95bfc2afd1e7eae0033b403dd3d8c1b6d13a652ada75b348"},
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:664832fb88b8162268928df233f4b12a144a0c78b01d38b81bdcf0fc96668ecb"},
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:df561f65049ed3556e5b52541669310e88713fdae2934845ec3606f283337958"},
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:24bbc3507fb6dfff663af7900a631f2aca90d5a445f272db5fc84999fa5718bc"},
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:87de598edfa2230ff274c4de7fcf24c73ffd96208c8e1912d5d0fee459767d75"},
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a19d39b02a24d3082856a5b06490b714a9d4179321225bbf22809ff1e1887cc8"},
{file = "MarkupSafe-2.0.0-cp39-cp39-win32.whl", hash = "sha256:4aca81a687975b35e3e80bcf9aa93fe10cd57fac37bf18b2314c186095f57e05"},
{file = "MarkupSafe-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:70820a1c96311e02449591cbdf5cd1c6a34d5194d5b55094ab725364375c9eb2"},
{file = "MarkupSafe-2.0.0.tar.gz", hash = "sha256:4fae0677f712ee090721d8b17f412f1cbceefbf0dc180fe91bab3232f38b4527"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
{file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
{file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
{file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
]
matplotlib-inline = [
{file = "matplotlib-inline-0.1.2.tar.gz", hash = "sha256:f41d5ff73c9f5385775d5c0bc13b424535c8402fe70ea8210f93e11f3683993e"},
{file = "matplotlib_inline-0.1.2-py3-none-any.whl", hash = "sha256:5cf1176f554abb4fa98cb362aa2b55c500147e4bdbb07e3fda359143e1da0811"},
]
more-itertools = [
{file = "more-itertools-8.7.0.tar.gz", hash = "sha256:c5d6da9ca3ff65220c3bfd2a8db06d698f05d4d2b9be57e1deb2be5a45019713"},
{file = "more_itertools-8.7.0-py3-none-any.whl", hash = "sha256:5652a9ac72209ed7df8d9c15daf4e1aa0e3d2ccd3c87f8265a0673cd9cbc9ced"},
{file = "more-itertools-8.8.0.tar.gz", hash = "sha256:83f0308e05477c68f56ea3a888172c78ed5d5b3c282addb67508e7ba6c8f813a"},
{file = "more_itertools-8.8.0-py3-none-any.whl", hash = "sha256:2cf89ec599962f2ddc4d568a05defc40e0a587fbc10d5989713638864c36be4d"},
]
packaging = [
{file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},

Loading…
Cancel
Save