From 5070ec2ac7be39f61ae2e2d15b40474739fd937d Mon Sep 17 00:00:00 2001 From: Tony Rewin Date: Tue, 23 Nov 2021 10:16:42 +0300 Subject: [PATCH] migration fixes --- README.md | 2 +- migrate.py | 657 +++++++++++++++--------------- migration/tables/content_items.py | 56 +-- poetry.lock | 312 +++++++------- 4 files changed, 530 insertions(+), 497 deletions(-) diff --git a/README.md b/README.md index 4d5878ca..8a749e00 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# discours-backend-next +# discoursio-api Tech stack: diff --git a/migrate.py b/migrate.py index 3e15f5b2..5eb77c91 100644 --- a/migrate.py +++ b/migrate.py @@ -1,5 +1,6 @@ ''' cmd managed migration ''' import json +import pprint import base64 import re import frontmatter @@ -15,343 +16,353 @@ from dateutil.parser import parse as date_parse from orm.base import local_session from orm import User - +print = pprint.pprint IMG_REGEX = r"\!\[(.*?)\]\((data\:image\/(png|jpeg|jpg);base64\,(.*?))\)" OLD_DATE = '2016-03-05 22:22:00.350000' +def extract_images(article): + ''' extract b64 encoded images from markdown in article body ''' + body = article['body'] + images = [] + matches = re.finditer(IMG_REGEX, body, re.IGNORECASE | re.MULTILINE) + for i, match in enumerate(matches, start=1): + ext = match.group(3) + link = '/static/upload/image-' + \ + article['old_id'] + str(i) + '.' + ext + img = match.group(4) + if img not in images: + open('..' + link, 'wb').write(base64.b64decode(img)) + images.append(img) + body = body.replace(match.group(2), link) + print(link) + article['body'] = body + return article + + +def users(users_by_oid, users_by_slug, users_data): + ''' migrating users first ''' + # limiting + limit = len(users_data) + if len(sys.argv) > 2: limit = int(sys.argv[2]) + print('migrating %d users...' % limit) + counter = 0 + for entry in users_data: + oid = entry['_id'] + user = migrateUser(entry) + users_by_oid[oid] = user # full + del user['password'] + del user['notifications'] + # del user['oauth'] + del user['emailConfirmed'] + del user['username'] + del user['email'] + users_by_slug[user['slug']] = user # public + counter += 1 + export_authors = dict(sorted(users_by_slug.items(), key=lambda item: item[1]['rating'])[-10:]) + try: + open('migration/data/users.old_id.json', 'w').write(json.dumps(users_by_oid, cls=DateTimeEncoder)) # NOTE: by old_id + open('migration/data/users.slug.json', 'w').write(json.dumps(users_by_slug, cls=DateTimeEncoder)) # NOTE: by slug + print(str(len(users_by_slug.items())) + ' users migrated') + except Exception: + print('json dump error') + print(users_by_oid) + + +def topics(export_topics, topics_by_slug, topics_by_cat, topics_by_tag, cats_data, tags_data): + ''' topics from categories and tags ''' + # limiting + limit = len(cats_data) + len(tags_data) + if len(sys.argv) > 2: limit = int(sys.argv[2]) + print('migrating %d topics...' % limit) + counter = 0 + for cat in cats_data: + old_id = cat["createdBy"] + # cat["createdBy"] = user_id_map[old_id] + try: topic = migrateCategory(cat) + except Exception as e: raise e + topics_by_cat[topic['cat_id']] = topic + topics_by_slug[topic['slug']] = topic + counter += 1 + for tag in tags_data: + old_id = tag["createdBy"] + tag["createdBy"] = user_id_map.get(old_id, 0) + topic = migrateTag(tag) + topics_by_tag[topic['tag_id']] = topic + if not topics_by_slug.get(topic['slug']): topics_by_slug[topic['slug']] = topic + counter += 1 + export_topics = dict(topics_by_slug.items()) # sorted(topics_by_slug.items(), key=lambda item: str(item[1]['createdAt']))) # NOTE: sorting does not work :) + open('migration/data/topics.slug.json','w').write(json.dumps(topics_by_slug, + cls=DateTimeEncoder, + indent=4, + sort_keys=True, + ensure_ascii=False)) + + open('migration/data/topics.cat_id.json','w').write(json.dumps(topics_by_cat, + cls=DateTimeEncoder, + indent=4, + sort_keys=True, + ensure_ascii=False)) + +def shouts(content_data, shouts_by_slug, shouts_by_oid): + ''' migrating content items one by one ''' + # limiting + limit = len(content_data) + if len(sys.argv) > 2: limit = int(sys.argv[2]) + print('migrating %d content items...' % limit) + counter = 0 + discours_author = 0 + errored = [] + + # limiting + try: limit = int(sys.argv[2]) if len(sys.argv) > 2 else len(content_data) + except ValueError: limit = len(content_data) + + if not topics_by_cat: + with local_session() as session: + topics = session.query(Topic).all() + print("loaded %s topics" % len(topics)) + for topic in topics: + topics_by_cat[topic.cat_id] = topic + + for entry in content_data[:limit]: + try: + shout = migrateShout(entry, users_by_oid, topics_by_cat) + author = shout['authors'][0] + shout['authors'] = [ author.id, ] + shouts_by_slug[shout['slug']] = shout + shouts_by_oid[entry['_id']] = shout + line = str(counter+1) + ': ' + shout['slug'] + " @" + str(author.slug) + counter += 1 + if author.slug == 'discours': discours_author += 1 + print(line) + # open('./shouts.id.log', 'a').write(line + '\n') + except Exception as e: + print(entry['_id']) + errored.append(entry) + raise e + open('migration/data/shouts.old_id.json','w').write(json.dumps(shouts_by_oid, cls=DateTimeEncoder)) + open('migration/data/shouts.slug.json','w').write(json.dumps(shouts_by_slug, cls=DateTimeEncoder)) + print(str(counter) + '/' + str(len(content_data)) + ' content items were migrated') + print(str(discours_author) + ' authored by @discours') + +def export_shouts(shouts_by_slug, export_articles, export_authors, content_dict): + # update what was just migrated or load json again + if len(export_authors.keys()) == 0: + export_authors = json.loads(open('../src/data/authors.json').read()) + print(str(len(export_authors.items())) + ' exported authors loaded') + if len(export_articles.keys()) == 0: + export_articles = json.loads(open('../src/data/articles.json').read()) + print(str(len(export_articles.items())) + ' exported articles loaded') + + # limiting + limit = 33 + if len(sys.argv) > 2: limit = int(sys.argv[2]) + print('exporting %d articles to json...' % limit) + + # filter + export_list = [i for i in shouts_by_slug.items() if i[1]['layout'] == 'article'] + export_list = sorted(export_list, key=lambda item: item[1]['createdAt'] or OLD_DATE, reverse=True) + print(str(len(export_list)) + ' filtered') + export_list = export_list[:limit or len(export_list)] + + for (slug, article) in export_list: + if article['layout'] == 'article': + export_slug(slug, export_articles, export_authors, content_dict) + +def export_body(article, content_dict): + article = extract_images(article) + metadata = get_metadata(article) + content = frontmatter.dumps(frontmatter.Post(article['body'], **metadata)) + open('../content/discours.io/'+slug+'.md', 'w').write(content) + open('../content/discours.io/'+slug+'.html', 'w').write(content_dict[article['old_id']]['body']) + +def export_slug(slug, export_articles, export_authors, content_dict): + print('exporting %s ' % slug) + if export_authors == {}: + export_authors = json.loads(open('../src/data/authors.json').read()) + print(str(len(export_authors.items())) + ' exported authors loaded') + if export_articles == {}: + export_articles = json.loads(open('../src/data/articles.json').read()) + print(str(len(export_articles.items())) + ' exported articles loaded') + + shout = shouts_by_slug.get(slug, False) + assert shout, 'no data error' + author = users_by_slug.get(shout['authors'][0]['slug'], None) + export_authors.update({shout['authors'][0]['slug']: author}) + export_articles.update({shout['slug']: shout}) + export_body(shout, content_dict) + comments([slug, ]) + +def comments(sluglist, export_comments, export_articles, shouts_by_slug, content_dict): + ''' migrating comments on content items one ''' + if len(sluglist) == 0: + export_articles = json.loads(open('../src/data/articles.json').read()) + print(str(len(export_articles.items())) + ' articles were exported before') + if len(sluglist) == 0: sluglist = list(export_articles.keys()) + + if len(sluglist) > 0: + print('exporting comments for: ') + print(' '.join(sluglist)) + for slug in sluglist: + shout = shouts_by_slug[slug] + old_id = shout['old_id'] + content_item = content_dict.get(old_id, {}) + if content_item.get('commentedAt', False): + comments = [ migrateComment(c) for c in comments_by_post.get(old_id, []) ] + if len(comments) > 0: + export_comments[slug] = comments + sys.stdout.write('.') + else: + + print('exporting comments for top 10 commented articles...') + comments_by_shoutslug = {} + for content_item in content_data: + old_id = content_item['_id'] + if content_item.get('commentedAt', False): + comments = [ migrateComment(c) for c in comments_by_post.get(old_id, []) ] + if len(comments) > 0: + shout = shouts_by_oid.get(old_id, { 'slug': 'abandoned-comments' }) + comments_by_shoutslug[shout['slug']] = comments + + top = dict(sorted(comments_by_shoutslug.items(), reverse=True, key=lambda c: len(c[1]))[:10]) + export_comments.update(top) + + print(str(len(export_comments.keys())) + ' articls with comments exported\n') + + +def export_finish(export_articles = {}, export_authors = {}, export_topics = {}, export_comments = {}): + open('../src/data/authors.json', 'w').write(json.dumps(export_authors, + cls=DateTimeEncoder, + indent=4, + sort_keys=True, + ensure_ascii=False)) + print(str(len(export_authors.items())) + ' authors exported') + open('../src/data/topics.json', 'w').write(json.dumps(export_topics, + cls=DateTimeEncoder, + indent=4, + sort_keys=True, + ensure_ascii=False)) + print(str(len(export_topics.keys())) + ' topics exported') + + open('../src/data/articles.json', 'w').write(json.dumps(export_articles, + cls=DateTimeEncoder, + indent=4, + sort_keys=True, + ensure_ascii=False)) + print(str(len(export_articles.items())) + ' articles exported') + open('../src/data/comments.json', 'w').write(json.dumps(export_comments, + cls=DateTimeEncoder, + indent=4, + sort_keys=True, + ensure_ascii=False)) + print(str(len(export_comments.items())) + ' exported articles with comments') + + if __name__ == '__main__': - import sys + import sys - users_data = json.loads(open('migration/data/users.json').read()) - # users_dict = { x['_id']: x for x in users_data } # by id - print(str(len(users_data)) + ' users loaded') - users_by_oid = {} - users_by_slug = {} + if len(sys.argv) > 1: + cmd = sys.argv[1] + if cmd == "bson": + # decode bson + from migration import bson2json + bson2json.json_tables() + else: - with local_session() as session: - default_user = session.query(User).filter(User.id == 0).first() - if not default_user: - default_user = User.create(id = 0, email = "discours@discours.io", username = "discours", slug = "default", old_id = 0) + # preparing data - user_id_map = {} - with local_session() as session: - users = session.query(User).all() - for user in users: - user_id_map[user.old_id] = user.id - users_by_oid[user.old_id] = vars(user) + users_data = json.loads(open('migration/data/users.json').read()) + # users_dict = { x['_id']: x for x in users_data } # by id + print(str(len(users_data)) + ' users loaded') + users_by_oid = {} + users_by_slug = {} - tags_data = json.loads(open('migration/data/tags.json').read()) - print(str(len(tags_data)) + ' tags loaded') + with local_session() as session: + default_user = session.query(User).filter(User.id == 0).first() + if not default_user: + default_user = User.create(id = 0, email = "discours@discours.io", username = "discours", slug = "default", old_id = 0) - cats_data = json.loads(open('migration/data/content_item_categories.json').read()) - print(str(len(cats_data)) + ' cats loaded') - topics_by_cat = {} - topics_by_tag = {} - topics_by_slug = {} + user_id_map = {} + with local_session() as session: + users_list = session.query(User).all() + for user in users_list: + user_id_map[user.old_id] = user.id + users_by_oid[user.old_id] = vars(user) - content_data = json.loads(open('migration/data/content_items.json').read()) - content_dict = { x['_id']: x for x in content_data } - print(str(len(content_data)) + ' content items loaded') - shouts_by_slug = {} - shouts_by_oid = {} + tags_data = json.loads(open('migration/data/tags.json').read()) + print(str(len(tags_data)) + ' tags loaded') - comments_data = json.loads(open('migration/data/comments.json').read()) - print(str(len(comments_data)) + ' comments loaded') - comments_by_post = {} + cats_data = json.loads(open('migration/data/content_item_categories.json').read()) + print(str(len(cats_data)) + ' cats loaded') + topics_by_cat = {} + topics_by_tag = {} + topics_by_slug = {} - # sort comments by old posts ids - for old_comment in comments_data: - cid = old_comment['contentItem'] - comments_by_post[cid] = comments_by_post.get(cid, []) - if not old_comment.get('deletedAt', True): - comments_by_post[cid].append(old_comment) - print(str(len(comments_by_post.keys())) + ' articles with comments') + content_data = json.loads(open('migration/data/content_items.json').read()) + content_dict = { x['_id']: x for x in content_data } + print(str(len(content_data)) + ' content items loaded') + shouts_by_slug = {} + shouts_by_oid = {} - export_articles = {} # slug: shout - export_authors = {} # slug: user - export_comments = {} # shout-slug: comment[] (list) - export_topics = {} # slug: topic + comments_data = json.loads(open('migration/data/comments.json').read()) + print(str(len(comments_data)) + ' comments loaded') + comments_by_post = {} + # sort comments by old posts ids + for old_comment in comments_data: + cid = old_comment['contentItem'] + comments_by_post[cid] = comments_by_post.get(cid, []) + if not old_comment.get('deletedAt', True): + comments_by_post[cid].append(old_comment) + print(str(len(comments_by_post.keys())) + ' articles with comments') + export_articles = {} # slug: shout + export_authors = {} # slug: user + export_comments = {} # shout-slug: comment[] (list) + export_topics = {} # slug: topic - def extract_images(article): - ''' extract b64 encoded images from markdown in article body ''' - body = article['body'] - images = [] - matches = re.finditer(IMG_REGEX, body, re.IGNORECASE | re.MULTILINE) - for i, match in enumerate(matches, start=1): - ext = match.group(3) - link = '/static/upload/image-' + \ - article['old_id'] + str(i) + '.' + ext - img = match.group(4) - if img not in images: - open('..' + link, 'wb').write(base64.b64decode(img)) - images.append(img) - body = body.replace(match.group(2), link) - print(link) - article['body'] = body - return article + ##################### COMMANDS ##########################3 - - def users(users_by_oid, users_by_slug, users_data): - ''' migrating users first ''' - # limiting - limit = len(users_data) - if len(sys.argv) > 2: limit = int(sys.argv[2]) - print('migrating %d users...' % limit) - counter = 0 - for entry in users_data: - oid = entry['_id'] - user = migrateUser(entry) - users_by_oid[oid] = user # full - del user['password'] - del user['notifications'] - # del user['oauth'] - del user['emailConfirmed'] - del user['username'] - del user['email'] - users_by_slug[user['slug']] = user # public - counter += 1 - export_authors = dict(sorted(users_by_slug.items(), key=lambda item: item[1]['rating'])[-10:]) - open('migration/data/users.old_id.json', 'w').write(json.dumps(users_by_oid, cls=DateTimeEncoder)) # NOTE: by old_id - open('migration/data/users.slug.json', 'w').write(json.dumps(users_by_slug, cls=DateTimeEncoder)) # NOTE: by old_id - print(str(len(users_by_slug.items())) + ' users migrated') - - - def topics(export_topics, topics_by_slug, topics_by_cat, topics_by_tag, cats_data, tags_data): - ''' topics from categories and tags ''' - # limiting - limit = len(cats_data) + len(tags_data) - if len(sys.argv) > 2: limit = int(sys.argv[2]) - print('migrating %d topics...' % limit) - counter = 0 - for cat in cats_data: - old_id = cat["createdBy"] - # cat["createdBy"] = user_id_map[old_id] - try: topic = migrateCategory(cat) - except Exception as e: raise e - topics_by_cat[topic['cat_id']] = topic - topics_by_slug[topic['slug']] = topic - counter += 1 - for tag in tags_data: - old_id = tag["createdBy"] - tag["createdBy"] = user_id_map.get(old_id, 0) - topic = migrateTag(tag) - topics_by_tag[topic['tag_id']] = topic - if not topics_by_slug.get(topic['slug']): topics_by_slug[topic['slug']] = topic - counter += 1 - export_topics = dict(topics_by_slug.items()) # sorted(topics_by_slug.items(), key=lambda item: str(item[1]['createdAt']))) # NOTE: sorting does not work :) - open('migration/data/topics.slug.json','w').write(json.dumps(topics_by_slug, - cls=DateTimeEncoder, - indent=4, - sort_keys=True, - ensure_ascii=False)) - - open('migration/data/topics.cat_id.json','w').write(json.dumps(topics_by_cat, - cls=DateTimeEncoder, - indent=4, - sort_keys=True, - ensure_ascii=False)) - - def shouts(content_data, shouts_by_slug, shouts_by_oid): - ''' migrating content items one by one ''' - # limiting - limit = len(content_data) - if len(sys.argv) > 2: limit = int(sys.argv[2]) - print('migrating %d content items...' % limit) - counter = 0 - discours_author = 0 - errored = [] - - # limiting - try: limit = int(sys.argv[2]) if len(sys.argv) > 2 else len(content_data) - except ValueError: limit = len(content_data) - - if not topics_by_cat: - with local_session() as session: - topics = session.query(Topic).all() - print("loaded %s topics" % len(topics)) - for topic in topics: - topics_by_cat[topic.cat_id] = topic - - for entry in content_data[:limit]: - try: - shout = migrateShout(entry, users_by_oid, topics_by_cat) - author = shout['authors'][0] - shout['authors'] = [ author.id, ] - shouts_by_slug[shout['slug']] = shout - shouts_by_oid[entry['_id']] = shout - line = str(counter+1) + ': ' + shout['slug'] + " @" + str(author.slug) - counter += 1 - if author.slug == 'discours': discours_author += 1 - print(line) - # open('./shouts.id.log', 'a').write(line + '\n') - except Exception as e: - print(entry['_id']) - errored.append(entry) - raise e - open('migration/data/shouts.old_id.json','w').write(json.dumps(shouts_by_oid, cls=DateTimeEncoder)) - open('migration/data/shouts.slug.json','w').write(json.dumps(shouts_by_slug, cls=DateTimeEncoder)) - print(str(counter) + '/' + str(len(content_data)) + ' content items were migrated') - print(str(discours_author) + ' authored by @discours') - - def export_shouts(shouts_by_slug, export_articles, export_authors, content_dict): - # update what was just migrated or load json again - if len(export_authors.keys()) == 0: - export_authors = json.loads(open('../src/data/authors.json').read()) - print(str(len(export_authors.items())) + ' exported authors loaded') - if len(export_articles.keys()) == 0: - export_articles = json.loads(open('../src/data/articles.json').read()) - print(str(len(export_articles.items())) + ' exported articles loaded') - - # limiting - limit = 33 - if len(sys.argv) > 2: limit = int(sys.argv[2]) - print('exporting %d articles to json...' % limit) - - # filter - export_list = [i for i in shouts_by_slug.items() if i[1]['layout'] == 'article'] - export_list = sorted(export_list, key=lambda item: item[1]['createdAt'] or OLD_DATE, reverse=True) - print(str(len(export_list)) + ' filtered') - export_list = export_list[:limit or len(export_list)] - - for (slug, article) in export_list: - if article['layout'] == 'article': - export_slug(slug, export_articles, export_authors, content_dict) - - def export_body(article, content_dict): - article = extract_images(article) - metadata = get_metadata(article) - content = frontmatter.dumps(frontmatter.Post(article['body'], **metadata)) - open('../content/discours.io/'+slug+'.md', 'w').write(content) - open('../content/discours.io/'+slug+'.html', 'w').write(content_dict[article['old_id']]['body']) - - def export_slug(slug, export_articles, export_authors, content_dict): - print('exporting %s ' % slug) - if export_authors == {}: - export_authors = json.loads(open('../src/data/authors.json').read()) - print(str(len(export_authors.items())) + ' exported authors loaded') - if export_articles == {}: - export_articles = json.loads(open('../src/data/articles.json').read()) - print(str(len(export_articles.items())) + ' exported articles loaded') - - shout = shouts_by_slug.get(slug, False) - assert shout, 'no data error' - author = users_by_slug.get(shout['authors'][0]['slug'], None) - export_authors.update({shout['authors'][0]['slug']: author}) - export_articles.update({shout['slug']: shout}) - export_body(shout, content_dict) - comments([slug, ]) - - def comments(sluglist, export_comments, export_articles, shouts_by_slug, content_dict): - ''' migrating comments on content items one ''' - if len(sluglist) == 0: - export_articles = json.loads(open('../src/data/articles.json').read()) - print(str(len(export_articles.items())) + ' articles were exported before') - if len(sluglist) == 0: sluglist = list(export_articles.keys()) - - if len(sluglist) > 0: - print('exporting comments for: ') - print(' '.join(sluglist)) - for slug in sluglist: - shout = shouts_by_slug[slug] - old_id = shout['old_id'] - content_item = content_dict.get(old_id, {}) - if content_item.get('commentedAt', False): - comments = [ migrateComment(c) for c in comments_by_post.get(old_id, []) ] - if len(comments) > 0: - export_comments[slug] = comments - sys.stdout.write('.') - else: - - print('exporting comments for top 10 commented articles...') - comments_by_shoutslug = {} - for content_item in content_data: - old_id = content_item['_id'] - if content_item.get('commentedAt', False): - comments = [ migrateComment(c) for c in comments_by_post.get(old_id, []) ] - if len(comments) > 0: - shout = shouts_by_oid.get(old_id, { 'slug': 'abandoned-comments' }) - comments_by_shoutslug[shout['slug']] = comments - - top = dict(sorted(comments_by_shoutslug.items(), reverse=True, key=lambda c: len(c[1]))[:10]) - export_comments.update(top) - - print(str(len(export_comments.keys())) + ' articls with comments exported\n') - - - def export_finish(export_articles = {}, export_authors = {}, export_topics = {}, export_comments = {}): - open('../src/data/authors.json', 'w').write(json.dumps(export_authors, - cls=DateTimeEncoder, - indent=4, - sort_keys=True, - ensure_ascii=False)) - print(str(len(export_authors.items())) + ' authors exported') - open('../src/data/topics.json', 'w').write(json.dumps(export_topics, - cls=DateTimeEncoder, - indent=4, - sort_keys=True, - ensure_ascii=False)) - print(str(len(export_topics.keys())) + ' topics exported') - - open('../src/data/articles.json', 'w').write(json.dumps(export_articles, - cls=DateTimeEncoder, - indent=4, - sort_keys=True, - ensure_ascii=False)) - print(str(len(export_articles.items())) + ' articles exported') - open('../src/data/comments.json', 'w').write(json.dumps(export_comments, - cls=DateTimeEncoder, - indent=4, - sort_keys=True, - ensure_ascii=False)) - print(str(len(export_comments.items())) + ' exported articles with comments') - - if len(sys.argv) > 1: - cmd = sys.argv[1] - if cmd == "users": - users(users_by_oid, users_by_slug, users_data) - elif cmd == "topics": - topics(export_topics, topics_by_slug, topics_by_cat, topics_by_tag, cats_data, tags_data) - elif cmd == "shouts": - with local_session() as session: - community = session.query(Community).filter(Community.id == 0).first() - if not community: - Community.create(**{ - 'id' : 0, - 'slug': 'discours.io', - 'name': 'Дискурс', - 'pic': 'https://discours.io/images/logo-min.svg', - 'createdBy': '0', - 'createdAt': date_parse(OLD_DATE) - }) - shouts(content_data, shouts_by_slug, shouts_by_oid) # NOTE: listens limit - elif cmd == "comments": - for comment in comments_data: - migrateComment(comment) - elif cmd == "export_shouts": - export_shouts(shouts_by_slug, export_articles, export_authors, content_dict) - elif cmd == "all": - users(users_by_oid, users_by_slug, users_data) - topics(export_topics, topics_by_slug, topics_by_cat, topics_by_tag, cats_data, tags_data) - shouts(content_data, shouts_by_slug, shouts_by_oid) - cl = sys.argv[2] if len(sys.argv) > 2 else 10 - topOids = sorted([ c[0] for c in comments_by_post.items()], reverse=True, key=lambda i: len(i[1]))[-cl:] - topSlugs = [ shouts_by_oid[oid]['slug'] for oid in topOids ] - comments(topSlugs, export_comments, export_articles, shouts_by_slug, content_dict) - elif cmd == "bson": - from migration import bson2json - bson2json.json_tables() - elif cmd == 'slug': - export_slug(sys.argv[2], export_articles, export_authors, content_dict) - #export_finish(export_articles, export_authors, export_topics, export_comments) - else: - print(''' - usage: python migrate.py bson - \n.. \ttopics - \n.. \tusers - \n.. \tshouts - \n.. \texport_shouts - \n.. \tslug - \n.. \tall - ''') + if cmd == "users": + users(users_by_oid, users_by_slug, users_data) + elif cmd == "topics": + topics(export_topics, topics_by_slug, topics_by_cat, topics_by_tag, cats_data, tags_data) + elif cmd == "shouts": + with local_session() as session: + community = session.query(Community).filter(Community.id == 0).first() + if not community: + Community.create(**{ + 'id' : 0, + 'slug': 'discours.io', + 'name': 'Дискурс', + 'pic': 'https://discours.io/images/logo-min.svg', + 'createdBy': '0', + 'createdAt': date_parse(OLD_DATE) + }) + shouts(content_data, shouts_by_slug, shouts_by_oid) # NOTE: listens limit + elif cmd == "comments": + for comment in comments_data: + migrateComment(comment) + elif cmd == "export_shouts": + export_shouts(shouts_by_slug, export_articles, export_authors, content_dict) + elif cmd == "all": + users(users_by_oid, users_by_slug, users_data) + topics(export_topics, topics_by_slug, topics_by_cat, topics_by_tag, cats_data, tags_data) + shouts(content_data, shouts_by_slug, shouts_by_oid) + cl = sys.argv[2] if len(sys.argv) > 2 else 10 + topOids = sorted([ c[0] for c in comments_by_post.items()], reverse=True, key=lambda i: len(i[1]))[-cl:] + topSlugs = [ shouts_by_oid[oid]['slug'] for oid in topOids ] + comments(topSlugs, export_comments, export_articles, shouts_by_slug, content_dict) + elif cmd == 'slug': + export_slug(sys.argv[2], export_articles, export_authors, content_dict) + #export_finish(export_articles, export_authors, export_topics, export_comments) + else: + print(''' + usage: python migrate.py bson + \n.. \ttopics + \n.. \tusers + \n.. \tshouts + \n.. \texport_shouts + \n.. \tslug + \n.. \tall + ''') diff --git a/migration/tables/content_items.py b/migration/tables/content_items.py index ba5082e5..d9e5e470 100644 --- a/migration/tables/content_items.py +++ b/migration/tables/content_items.py @@ -37,7 +37,7 @@ def get_metadata(r): metadata['authors'] = r.get('authors') metadata['createdAt'] = r.get('createdAt', ts) metadata['layout'] = r['layout'] - metadata['topics'] = [topic.slug for topic in r['topics']] + metadata['topics'] = [topic['slug'] for topic in r['topics']] if r.get('cover', False): metadata['cover'] = r.get('cover') return metadata @@ -199,32 +199,34 @@ def migrate(entry, users_by_oid, topics_by_oid): print(userdata) assert user, 'could not get a user' - shout_dict['authors'] = [ user, ] - try: s = Shout.create(**shout_dict) - except Exception as e: raise e - - with local_session() as session: - shout_dict['id'] = s.id - # shout ratings - shout_dict['ratings'] = [] - for shout_rating_old in entry.get('ratings',[]): - rater = session.query(User).filter(User.old_id == shout_rating_old['createdBy']).first() - if rater: - shout_rating_dict = { - 'value': shout_rating_old['value'], - 'rater_id': rater.id, - 'shout_id': s.id - } - cts = shout_rating_old.get('createdAt') - if cts: shout_rating_dict['rater_id'] = date_parse(cts) - try: shout_rating = ShoutRating.create(**shout_rating_dict) - except sqlalchemy.exc.IntegrityError: pass - shout_dict['ratings'].append(shout_rating_dict) - # shout topics - shout_dict['topics'] = [] - for topic in r['topics']: - ShoutTopic.create(**{ 'shout': s.id, 'topic': topic.id }) - shout_dict['topics'].append(topic.slug) + shout_dict['authors'] = [ user, ] + try: + with local_session() as session: + s = Shout.create(**shout_dict) + if s: + # shout ratings + shout_dict['ratings'] = [] + for shout_rating_old in entry.get('ratings',[]): + rater = session.query(User).filter(User.old_id == shout_rating_old['createdBy']).first() + if rater: + shout_rating_dict = { + 'value': shout_rating_old['value'], + 'rater_id': rater.id, + 'shout_id': s.id + } + cts = shout_rating_old.get('createdAt') + if cts: shout_rating_dict['rater_id'] = date_parse(cts) + try: shout_rating = ShoutRating.create(**shout_rating_dict) + except sqlalchemy.exc.IntegrityError: pass + shout_dict['ratings'].append(shout_rating_dict) + # shout topics + shout_dict['id'] = s.id + shout_dict['topics'] = [] + for topic in r['topics']: + ShoutTopic.create(**{ 'shout': s.id, 'topic': topic['id'] }) + shout_dict['topics'].append(topic['slug']) + except Exception as e: + raise e except Exception as e: if not shout_dict['body']: r['body'] = 'body moved' raise e diff --git a/poetry.lock b/poetry.lock index b5bba006..6c5a32d4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -32,20 +32,18 @@ trio = ["trio (>=0.16)"] [[package]] name = "ariadne" -version = "0.13.0" +version = "0.3.0" description = "Ariadne is a Python library for implementing GraphQL servers." category = "main" optional = false python-versions = "*" [package.dependencies] -graphql-core = ">=3.1.0" -starlette = "<0.15" +graphql-core-next = ">=1.0.1" +starlette = ">=0.11.4" +typing = ">=3.6.0" typing-extensions = ">=3.6.0" -[package.extras] -asgi-file-uploads = ["python-multipart (>=0.0.5)"] - [[package]] name = "asgiref" version = "3.4.1" @@ -59,11 +57,14 @@ tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] [[package]] name = "async-timeout" -version = "3.0.1" +version = "4.0.1" description = "Timeout context manager for asyncio programs" category = "main" optional = false -python-versions = ">=3.5.3" +python-versions = ">=3.6" + +[package.dependencies] +typing-extensions = ">=3.6.5" [[package]] name = "authlib" @@ -168,7 +169,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "cryptography" -version = "35.0.0" +version = "36.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false @@ -179,16 +180,16 @@ cffi = ">=1.12" [package.extras] docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] -docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] sdist = ["setuptools_rust (>=0.11.4)"] ssh = ["bcrypt (>=3.1.5)"] test = ["pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] [[package]] -name = "graphql-core" -version = "3.1.6" -description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." +name = "graphql-core-next" +version = "1.1.1" +description = "GraphQL-core-next is a Python port of GraphQL.js, the JavaScript reference implementation for GraphQL." category = "main" optional = false python-versions = ">=3.6,<4" @@ -222,7 +223,7 @@ python-versions = ">=3.5" [[package]] name = "httpcore" -version = "0.13.7" +version = "0.14.3" description = "A minimal low-level HTTP client." category = "main" optional = false @@ -230,6 +231,7 @@ python-versions = ">=3.6" [package.dependencies] anyio = ">=3.0.0,<4.0.0" +certifi = "*" h11 = ">=0.11,<0.13" sniffio = ">=1.0.0,<2.0.0" @@ -238,7 +240,7 @@ http2 = ["h2 (>=3,<5)"] [[package]] name = "httpx" -version = "0.20.0" +version = "0.21.1" description = "The next generation HTTP client." category = "main" optional = false @@ -247,7 +249,7 @@ python-versions = ">=3.6" [package.dependencies] certifi = "*" charset-normalizer = "*" -httpcore = ">=0.13.3,<0.14.0" +httpcore = ">=0.14.0,<0.15.0" rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} sniffio = "*" @@ -288,7 +290,7 @@ totp = ["cryptography"] [[package]] name = "psycopg2" -version = "2.9.1" +version = "2.9.2" description = "psycopg2 - Python-PostgreSQL Database Adapter" category = "main" optional = false @@ -296,7 +298,7 @@ python-versions = ">=3.6" [[package]] name = "psycopg2-binary" -version = "2.9.1" +version = "2.9.2" description = "psycopg2 - Python-PostgreSQL Database Adapter" category = "main" optional = false @@ -304,7 +306,7 @@ python-versions = ">=3.6" [[package]] name = "pycparser" -version = "2.20" +version = "2.21" description = "C parser in Python" category = "main" optional = false @@ -423,7 +425,7 @@ python-versions = ">=3.5" [[package]] name = "soupsieve" -version = "2.2.1" +version = "2.3.1" description = "A modern CSS selector implementation for Beautiful Soup." category = "main" optional = false @@ -431,7 +433,7 @@ python-versions = ">=3.6" [[package]] name = "sqlalchemy" -version = "1.4.26" +version = "1.4.27" description = "Database Abstraction Library" category = "main" optional = false @@ -463,14 +465,17 @@ sqlcipher = ["sqlcipher3-binary"] [[package]] name = "starlette" -version = "0.14.2" +version = "0.17.1" description = "The little ASGI library that shines." category = "main" optional = false python-versions = ">=3.6" +[package.dependencies] +anyio = ">=3.0.0,<4" + [package.extras] -full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] +full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] [[package]] name = "transliterate" @@ -484,12 +489,20 @@ python-versions = "*" six = ">=1.1.0" [[package]] -name = "typing-extensions" -version = "3.10.0.2" -description = "Backported and Experimental Type Hints for Python 3.5+" +name = "typing" +version = "3.7.4.3" +description = "Type Hints for Python" category = "main" optional = false -python-versions = "*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "typing-extensions" +version = "4.0.0" +description = "Backported and Experimental Type Hints for Python 3.6+" +category = "main" +optional = false +python-versions = ">=3.6" [[package]] name = "urllib3" @@ -535,16 +548,16 @@ anyio = [ {file = "anyio-3.3.4.tar.gz", hash = "sha256:67da67b5b21f96b9d3d65daa6ea99f5d5282cb09f50eb4456f8fb51dffefc3ff"}, ] ariadne = [ - {file = "ariadne-0.13.0-py3-none-any.whl", hash = "sha256:56bc3609a0512920f06e9312f8ea6db3c8e4a7cd77f31fbed388f5dba6d589c0"}, - {file = "ariadne-0.13.0.tar.gz", hash = "sha256:e00abd7eb5869b59a638f1e3a7743445bf387236048cf1b0eb9d7c506dcd37c5"}, + {file = "ariadne-0.3.0-py3-none-any.whl", hash = "sha256:c4b30b6138c7a9b8f890e80aed1303ae82deef70c3b7c5f218f7b2d620e046e8"}, + {file = "ariadne-0.3.0.tar.gz", hash = "sha256:01ed4572ff9ee24c1b06f932e5516bcc2e2ba23d129fb5a0e9fe4a732eae74ad"}, ] asgiref = [ {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, ] async-timeout = [ - {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, - {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, + {file = "async-timeout-4.0.1.tar.gz", hash = "sha256:b930cb161a39042f9222f6efb7301399c87eeab394727ec5437924a36d6eef51"}, + {file = "async_timeout-4.0.1-py3-none-any.whl", hash = "sha256:a22c0b311af23337eb05fcf05a8b51c3ea53729d46fb5460af62bee033cec690"}, ] authlib = [ {file = "Authlib-0.15.5-py2.py3-none-any.whl", hash = "sha256:ecf4a7a9f2508c0bb07e93a752dd3c495cfaffc20e864ef0ffc95e3f40d2abaf"}, @@ -629,30 +642,30 @@ colorama = [ {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] cryptography = [ - {file = "cryptography-35.0.0-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:d57e0cdc1b44b6cdf8af1d01807db06886f10177469312fbde8f44ccbb284bc9"}, - {file = "cryptography-35.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:ced40344e811d6abba00295ced98c01aecf0c2de39481792d87af4fa58b7b4d6"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:54b2605e5475944e2213258e0ab8696f4f357a31371e538ef21e8d61c843c28d"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7b7ceeff114c31f285528ba8b390d3e9cfa2da17b56f11d366769a807f17cbaa"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d69645f535f4b2c722cfb07a8eab916265545b3475fdb34e0be2f4ee8b0b15e"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2d0e0acc20ede0f06ef7aa58546eee96d2592c00f450c9acb89c5879b61992"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:07bb7fbfb5de0980590ddfc7f13081520def06dc9ed214000ad4372fb4e3c7f6"}, - {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7eba2cebca600a7806b893cb1d541a6e910afa87e97acf2021a22b32da1df52d"}, - {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:18d90f4711bf63e2fb21e8c8e51ed8189438e6b35a6d996201ebd98a26abbbe6"}, - {file = "cryptography-35.0.0-cp36-abi3-win32.whl", hash = "sha256:c10c797ac89c746e488d2ee92bd4abd593615694ee17b2500578b63cad6b93a8"}, - {file = "cryptography-35.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:7075b304cd567694dc692ffc9747f3e9cb393cc4aa4fb7b9f3abd6f5c4e43588"}, - {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a688ebcd08250eab5bb5bca318cc05a8c66de5e4171a65ca51db6bd753ff8953"}, - {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99915d6ab265c22873f1b4d6ea5ef462ef797b4140be4c9d8b179915e0985c6"}, - {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:928185a6d1ccdb816e883f56ebe92e975a262d31cc536429041921f8cb5a62fd"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ebeddd119f526bcf323a89f853afb12e225902a24d29b55fe18dd6fcb2838a76"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22a38e96118a4ce3b97509443feace1d1011d0571fae81fc3ad35f25ba3ea999"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb80e8a1f91e4b7ef8b33041591e6d89b2b8e122d787e87eeb2b08da71bb16ad"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:abb5a361d2585bb95012a19ed9b2c8f412c5d723a9836418fab7aaa0243e67d2"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1ed82abf16df40a60942a8c211251ae72858b25b7421ce2497c2eb7a1cee817c"}, - {file = "cryptography-35.0.0.tar.gz", hash = "sha256:9933f28f70d0517686bd7de36166dda42094eac49415459d9bdf5e7df3e0086d"}, + {file = "cryptography-36.0.0-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:97199a13b772e74cdcdb03760c32109c808aff7cd49c29e9cf4b7754bb725d1d"}, + {file = "cryptography-36.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:494106e9cd945c2cadfce5374fa44c94cfadf01d4566a3b13bb487d2e6c7959e"}, + {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6fbbbb8aab4053fa018984bb0e95a16faeb051dd8cca15add2a27e267ba02b58"}, + {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:684993ff6f67000a56454b41bdc7e015429732d65a52d06385b6e9de6181c71e"}, + {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c702855cd3174666ef0d2d13dcc879090aa9c6c38f5578896407a7028f75b9f"}, + {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d91bc9f535599bed58f6d2e21a2724cb0c3895bf41c6403fe881391d29096f1d"}, + {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:b17d83b3d1610e571fedac21b2eb36b816654d6f7496004d6a0d32f99d1d8120"}, + {file = "cryptography-36.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:8982c19bb90a4fa2aad3d635c6d71814e38b643649b4000a8419f8691f20ac44"}, + {file = "cryptography-36.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:24469d9d33217ffd0ce4582dfcf2a76671af115663a95328f63c99ec7ece61a4"}, + {file = "cryptography-36.0.0-cp36-abi3-win32.whl", hash = "sha256:f6a5a85beb33e57998dc605b9dbe7deaa806385fdf5c4810fb849fcd04640c81"}, + {file = "cryptography-36.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:2deab5ec05d83ddcf9b0916319674d3dae88b0e7ee18f8962642d3cde0496568"}, + {file = "cryptography-36.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2049f8b87f449fc6190350de443ee0c1dd631f2ce4fa99efad2984de81031681"}, + {file = "cryptography-36.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a776bae1629c8d7198396fd93ec0265f8dd2341c553dc32b976168aaf0e6a636"}, + {file = "cryptography-36.0.0-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:aa94d617a4cd4cdf4af9b5af65100c036bce22280ebb15d8b5262e8273ebc6ba"}, + {file = "cryptography-36.0.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:5c49c9e8fb26a567a2b3fa0343c89f5d325447956cc2fc7231c943b29a973712"}, + {file = "cryptography-36.0.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ef216d13ac8d24d9cd851776662f75f8d29c9f2d05cdcc2d34a18d32463a9b0b"}, + {file = "cryptography-36.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:231c4a69b11f6af79c1495a0e5a85909686ea8db946935224b7825cfb53827ed"}, + {file = "cryptography-36.0.0-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:f92556f94e476c1b616e6daec5f7ddded2c082efa7cee7f31c7aeda615906ed8"}, + {file = "cryptography-36.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d73e3a96c38173e0aa5646c31bf8473bc3564837977dd480f5cbeacf1d7ef3a3"}, + {file = "cryptography-36.0.0.tar.gz", hash = "sha256:52f769ecb4ef39865719aedc67b4b7eae167bafa48dbc2a26dd36fa56460507f"}, ] -graphql-core = [ - {file = "graphql-core-3.1.6.tar.gz", hash = "sha256:e65975b6a13878f9113a1fa5320760585b522d139944e005936b1b8358d0651a"}, - {file = "graphql_core-3.1.6-py3-none-any.whl", hash = "sha256:c78d09596d347e1cffd266c5384abfedf43ed1eae08729773bebb3d527fe5a14"}, +graphql-core-next = [ + {file = "GraphQL-core-next-1.1.1.tar.gz", hash = "sha256:76b52e7f654d8fc6abefc8583ebfd869a3939590813110ad27c0c0908b7d0659"}, + {file = "GraphQL_core_next-1.1.1-py3-none-any.whl", hash = "sha256:254187ad5f5acdfd521429d87fd3c05896dc1b74ddcb30b1fa37905dc1dc7c13"}, ] greenlet = [ {file = "greenlet-1.1.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6"}, @@ -715,12 +728,12 @@ html2text = [ {file = "html2text-2020.1.16.tar.gz", hash = "sha256:e296318e16b059ddb97f7a8a1d6a5c1d7af4544049a01e261731d2d5cc277bbb"}, ] httpcore = [ - {file = "httpcore-0.13.7-py3-none-any.whl", hash = "sha256:369aa481b014cf046f7067fddd67d00560f2f00426e79569d99cb11245134af0"}, - {file = "httpcore-0.13.7.tar.gz", hash = "sha256:036f960468759e633574d7c121afba48af6419615d36ab8ede979f1ad6276fa3"}, + {file = "httpcore-0.14.3-py3-none-any.whl", hash = "sha256:9a98d2416b78976fc5396ff1f6b26ae9885efbb3105d24eed490f20ab4c95ec1"}, + {file = "httpcore-0.14.3.tar.gz", hash = "sha256:d10162a63265a0228d5807964bd964478cbdb5178f9a2eedfebb2faba27eef5d"}, ] httpx = [ - {file = "httpx-0.20.0-py3-none-any.whl", hash = "sha256:33af5aad9bdc82ef1fc89219c1e36f5693bf9cd0ebe330884df563445682c0f8"}, - {file = "httpx-0.20.0.tar.gz", hash = "sha256:09606d630f070d07f9ff28104fbcea429ea0014c1e89ac90b4d8de8286c40e7b"}, + {file = "httpx-0.21.1-py3-none-any.whl", hash = "sha256:208e5ef2ad4d105213463cfd541898ed9d11851b346473539a8425e644bb7c66"}, + {file = "httpx-0.21.1.tar.gz", hash = "sha256:02af20df486b78892a614a7ccd4e4e86a5409ec4981ab0e422c579a887acad83"}, ] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, @@ -735,55 +748,59 @@ passlib = [ {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, ] psycopg2 = [ - {file = "psycopg2-2.9.1-cp36-cp36m-win32.whl", hash = "sha256:7f91312f065df517187134cce8e395ab37f5b601a42446bdc0f0d51773621854"}, - {file = "psycopg2-2.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:830c8e8dddab6b6716a4bf73a09910c7954a92f40cf1d1e702fb93c8a919cc56"}, - {file = "psycopg2-2.9.1-cp37-cp37m-win32.whl", hash = "sha256:89409d369f4882c47f7ea20c42c5046879ce22c1e4ea20ef3b00a4dfc0a7f188"}, - {file = "psycopg2-2.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7640e1e4d72444ef012e275e7b53204d7fab341fb22bc76057ede22fe6860b25"}, - {file = "psycopg2-2.9.1-cp38-cp38-win32.whl", hash = "sha256:079d97fc22de90da1d370c90583659a9f9a6ee4007355f5825e5f1c70dffc1fa"}, - {file = "psycopg2-2.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:2c992196719fadda59f72d44603ee1a2fdcc67de097eea38d41c7ad9ad246e62"}, - {file = "psycopg2-2.9.1-cp39-cp39-win32.whl", hash = "sha256:2087013c159a73e09713294a44d0c8008204d06326006b7f652bef5ace66eebb"}, - {file = "psycopg2-2.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:bf35a25f1aaa8a3781195595577fcbb59934856ee46b4f252f56ad12b8043bcf"}, - {file = "psycopg2-2.9.1.tar.gz", hash = "sha256:de5303a6f1d0a7a34b9d40e4d3bef684ccc44a49bbe3eb85e3c0bffb4a131b7c"}, + {file = "psycopg2-2.9.2-cp310-cp310-win32.whl", hash = "sha256:6796ac614412ce374587147150e56d03b7845c9e031b88aacdcadc880e81bb38"}, + {file = "psycopg2-2.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:dfc32db6ce9ecc35a131320888b547199f79822b028934bb5b332f4169393e15"}, + {file = "psycopg2-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:77d09a79f9739b97099d2952bbbf18eaa4eaf825362387acbb9552ec1b3fa228"}, + {file = "psycopg2-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f65cba7924363e0d2f416041b48ff69d559548f2cb168ff972c54e09e1e64db8"}, + {file = "psycopg2-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:b8816c6410fa08d2a022e4e38d128bae97c1855e176a00493d6ec62ccd606d57"}, + {file = "psycopg2-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:26322c3f114de1f60c1b0febf8fdd595c221b4f624524178f515d07350a71bd1"}, + {file = "psycopg2-2.9.2-cp38-cp38-win32.whl", hash = "sha256:77b9105ef37bc005b8ffbcb1ed6d8685bb0e8ce84773738aa56421a007ec5a7a"}, + {file = "psycopg2-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:91c7fd0fe9e6c118e8ff5b665bc3445781d3615fa78e131d0b4f8c85e8ca9ec8"}, + {file = "psycopg2-2.9.2-cp39-cp39-win32.whl", hash = "sha256:a761b60da0ecaf6a9866985bcde26327883ac3cdb90535ab68b8d784f02b05ef"}, + {file = "psycopg2-2.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:fd7ddab7d6afee4e21c03c648c8b667b197104713e57ec404d5b74097af21e31"}, + {file = "psycopg2-2.9.2.tar.gz", hash = "sha256:a84da9fa891848e0270e8e04dcca073bc9046441eeb47069f5c0e36783debbea"}, ] psycopg2-binary = [ - {file = "psycopg2-binary-2.9.1.tar.gz", hash = "sha256:b0221ca5a9837e040ebf61f48899926b5783668b7807419e4adae8175a31f773"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:24b0b6688b9f31a911f2361fe818492650795c9e5d3a1bc647acbd7440142a4f"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:542875f62bc56e91c6eac05a0deadeae20e1730be4c6334d8f04c944fcd99759"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:661509f51531ec125e52357a489ea3806640d0ca37d9dada461ffc69ee1e7b6e"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:d92272c7c16e105788efe2cfa5d680f07e34e0c29b03c1908f8636f55d5f915a"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:736b8797b58febabb85494142c627bd182b50d2a7ec65322983e71065ad3034c"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aef9aee84ec78af51107181d02fe8773b100b01c5dfde351184ad9223eab3698"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c3fb684e9abfc47218d3784c7b4c47c8587951ea4dd5bc38b6636ac57f616"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:995fc41ebda5a7a663a254a1dcac52638c3e847f48307b5416ee373da15075d7"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:fbb42a541b1093385a2d8c7eec94d26d30437d0e77c1d25dae1dcc46741a385e"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-win32.whl", hash = "sha256:20f1ab44d8c352074e2d7ca67dc00843067788791be373e67a0911998787ce7d"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f6fac64a38f6768e7bc7b035b9e10d8a538a9fadce06b983fb3e6fa55ac5f5ce"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:1e3a362790edc0a365385b1ac4cc0acc429a0c0d662d829a50b6ce743ae61b5a"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8559617b1fcf59a9aedba2c9838b5b6aa211ffedecabca412b92a1ff75aac1a"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a36c7eb6152ba5467fb264d73844877be8b0847874d4822b7cf2d3c0cb8cdcb0"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:2f62c207d1740b0bde5c4e949f857b044818f734a3d57f1d0d0edc65050532ed"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:cfc523edecddaef56f6740d7de1ce24a2fdf94fd5e704091856a201872e37f9f"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-win32.whl", hash = "sha256:1e85b74cbbb3056e3656f1cc4781294df03383127a8114cbc6531e8b8367bf1e"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1473c0215b0613dd938db54a653f68251a45a78b05f6fc21af4326f40e8360a2"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:35c4310f8febe41f442d3c65066ca93cccefd75013df3d8c736c5b93ec288140"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c13d72ed6af7fd2c8acbd95661cf9477f94e381fce0792c04981a8283b52917"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14db1752acdd2187d99cb2ca0a1a6dfe57fc65c3281e0f20e597aac8d2a5bd90"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:aed4a9a7e3221b3e252c39d0bf794c438dc5453bc2963e8befe9d4cd324dff72"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:da113b70f6ec40e7d81b43d1b139b9db6a05727ab8be1ee559f3a69854a69d34"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-win32.whl", hash = "sha256:4235f9d5ddcab0b8dbd723dca56ea2922b485ea00e1dafacf33b0c7e840b3d32"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:988b47ac70d204aed01589ed342303da7c4d84b56c2f4c4b8b00deda123372bf"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:7360647ea04db2e7dff1648d1da825c8cf68dc5fbd80b8fb5b3ee9f068dcd21a"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca86db5b561b894f9e5f115d6a159fff2a2570a652e07889d8a383b5fae66eb4"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ced67f1e34e1a450cdb48eb53ca73b60aa0af21c46b9b35ac3e581cf9f00e31"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:0f2e04bd2a2ab54fa44ee67fe2d002bb90cee1c0f1cc0ebc3148af7b02034cbd"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:3242b9619de955ab44581a03a64bdd7d5e470cc4183e8fcadd85ab9d3756ce7a"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-win32.whl", hash = "sha256:0b7dae87f0b729922e06f85f667de7bf16455d411971b2043bbd9577af9d1975"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:b4d7679a08fea64573c969f6994a2631908bb2c0e69a7235648642f3d2e39a68"}, + {file = "psycopg2-binary-2.9.2.tar.gz", hash = "sha256:234b1f48488b2f86aac04fb00cb04e5e9bcb960f34fa8a8e41b73149d581a93b"}, + {file = "psycopg2_binary-2.9.2-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:c0e1fb7097ded2cc44d9037cfc68ad86a30341261492e7de95d180e534969fb2"}, + {file = "psycopg2_binary-2.9.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:717525cdc97b23182ff6f470fb5bf6f0bc796b5a7000c6f6699d6679991e4a5e"}, + {file = "psycopg2_binary-2.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3865d0cd919349c45603bd7e80249a382c5ecf8106304cfd153282adf9684b6a"}, + {file = "psycopg2_binary-2.9.2-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:daf6b5c62eb738872d61a1fa740d7768904911ba5a7e055ed72169d379b58beb"}, + {file = "psycopg2_binary-2.9.2-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:3ac83656ff4fbe7f2a956ab085e3eb1d678df54759965d509bdd6a06ce520d49"}, + {file = "psycopg2_binary-2.9.2-cp310-cp310-win32.whl", hash = "sha256:a04cfa231e7d9b63639e62166a4051cb47ca599fa341463fa3e1c48585fcee64"}, + {file = "psycopg2_binary-2.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:c6e16e085fe6dc6c099ee0be56657aa9ad71027465ef9591d302ba230c404c7e"}, + {file = "psycopg2_binary-2.9.2-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:53912199abb626a7249c662e72b70b4f57bf37f840599cec68625171435790dd"}, + {file = "psycopg2_binary-2.9.2-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:029e09a892b9ebc3c77851f69ce0720e1b72a9c6850460cee49b14dfbf9ccdd2"}, + {file = "psycopg2_binary-2.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db1b03c189f85b8df29030ad32d521dd7dcb862fd5f8892035314f5b886e70ce"}, + {file = "psycopg2_binary-2.9.2-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:2eecbdc5fa5886f2dd6cc673ce4291cc0fb8900965315268960ad9c2477f8276"}, + {file = "psycopg2_binary-2.9.2-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:a77e98c68b0e6c51d4d6a994d22b30e77276cbd33e4aabdde03b9ad3a2c148aa"}, + {file = "psycopg2_binary-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:bf31e6fdb4ec1f6d98a07f48836508ed6edd19b48b13bbf168fbc1bd014b4ca2"}, + {file = "psycopg2_binary-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f9c37ecb173d76cf49e519133fd70851b8f9c38b6b8c1cb7fcfc71368d4cc6fc"}, + {file = "psycopg2_binary-2.9.2-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:a507db7758953b1b170c4310691a1a89877029b1e11b08ba5fc8ae3ddb35596b"}, + {file = "psycopg2_binary-2.9.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e4bbcfb403221ea1953f3e0a85cef00ed15c1683a66cf35c956a7e37c33a4c4"}, + {file = "psycopg2_binary-2.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4dff0f15af6936c6fe6da7067b4216edbbe076ad8625da819cc066591b1133c"}, + {file = "psycopg2_binary-2.9.2-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:8d2aafe46eb87742425ece38130510fbb035787ee89a329af299029c4d9ae318"}, + {file = "psycopg2_binary-2.9.2-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:37c8f00f7a2860bac9f7a54f03c243fc1dd9b367e5b2b52f5a02e5f4e9d8c49b"}, + {file = "psycopg2_binary-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:ef97578fab5115e3af4334dd3376dea3c3a79328a3314b21ec7ced02920b916d"}, + {file = "psycopg2_binary-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7e6bd4f532c2cd297b81114526176b240109a1c52020adca69c3f3226c65dc18"}, + {file = "psycopg2_binary-2.9.2-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:eeee7b18c51d02e49bf1984d7af26e8843fe68e31fa1cbab5366ebdfa1c89ade"}, + {file = "psycopg2_binary-2.9.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:497372cc76e6cbce2f51b37be141f360a321423c03eb9be45524b1d123f4cd11"}, + {file = "psycopg2_binary-2.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671699aff57d22a245b7f4bba89e3de97dc841c5e98bd7f685429b2b20eca47"}, + {file = "psycopg2_binary-2.9.2-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:b9d45374ba98c1184df9cce93a0b766097544f8bdfcd5de83ff10f939c193125"}, + {file = "psycopg2_binary-2.9.2-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:a1852c5bef7e5f52bd43fde5eda610d4df0fb2efc31028150933e84b4140d47a"}, + {file = "psycopg2_binary-2.9.2-cp38-cp38-win32.whl", hash = "sha256:108b0380969ddab7c8ef2a813a57f87b308b2f88ec15f1a1e7b653964a3cfb25"}, + {file = "psycopg2_binary-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:14427437117f38e65f71db65d8eafd0e86837be456567798712b8da89db2b2dd"}, + {file = "psycopg2_binary-2.9.2-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:578c279cd1ce04f05ae0912530ece00bab92854911808e5aec27588aba87e361"}, + {file = "psycopg2_binary-2.9.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2dea4deac3dd3687e32daeb0712ee96c535970dfdded37a11de6a21145ab0e"}, + {file = "psycopg2_binary-2.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b592f09ff18cfcc9037b9a976fcd62db48cae9dbd5385f2471d4c2ba40c52b4d"}, + {file = "psycopg2_binary-2.9.2-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:3a320e7a804f3886a599fea507364aaafbb8387027fffcdfbd34d96316c806c7"}, + {file = "psycopg2_binary-2.9.2-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:7585ca73dcfe326f31fafa8f96e6bb98ea9e9e46c7a1924ec8101d797914ae27"}, + {file = "psycopg2_binary-2.9.2-cp39-cp39-win32.whl", hash = "sha256:9c0aaad07941419926b9bd00171e49fe6b06e42e5527fb91671e137fe6c93d77"}, + {file = "psycopg2_binary-2.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:aa2847d8073951dbc84c4f8b32c620764db3c2eb0d99a04835fecfab7d04816e"}, ] pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pydantic = [ {file = "pydantic-1.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739"}, @@ -873,59 +890,62 @@ sniffio = [ {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, ] soupsieve = [ - {file = "soupsieve-2.2.1-py3-none-any.whl", hash = "sha256:c2c1c2d44f158cdbddab7824a9af8c4f83c76b1e23e049479aa432feb6c4c23b"}, - {file = "soupsieve-2.2.1.tar.gz", hash = "sha256:052774848f448cf19c7e959adf5566904d525f33a3f8b6ba6f6f8f26ec7de0cc"}, + {file = "soupsieve-2.3.1-py3-none-any.whl", hash = "sha256:1a3cca2617c6b38c0343ed661b1fa5de5637f257d4fe22bd9f1338010a1efefb"}, + {file = "soupsieve-2.3.1.tar.gz", hash = "sha256:b8d49b1cd4f037c7082a9683dfa1801aa2597fb11c3a1155b7a5b94829b4f1f9"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.4.26-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c2f2114b0968a280f94deeeaa31cfbac9175e6ac7bd3058b3ce6e054ecd762b3"}, - {file = "SQLAlchemy-1.4.26-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91efbda4e6d311812f23996242bad7665c1392209554f8a31ec6db757456db5c"}, - {file = "SQLAlchemy-1.4.26-cp27-cp27m-win32.whl", hash = "sha256:de996756d894a2d52c132742e3b6d64ecd37e0919ddadf4dc3981818777c7e67"}, - {file = "SQLAlchemy-1.4.26-cp27-cp27m-win_amd64.whl", hash = "sha256:463ef692259ff8189be42223e433542347ae17e33f91c1013e9c5c64e2798088"}, - {file = "SQLAlchemy-1.4.26-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c757ba1279b85b3460e72e8b92239dae6f8b060a75fb24b3d9be984dd78cfa55"}, - {file = "SQLAlchemy-1.4.26-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:c24c01dcd03426a5fe5ee7af735906bec6084977b9027a3605d11d949a565c01"}, - {file = "SQLAlchemy-1.4.26-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c46f013ff31b80cbe36410281675e1fb4eaf3e25c284fd8a69981c73f6fa4cb4"}, - {file = "SQLAlchemy-1.4.26-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fb2aa74a6e3c2cebea38dd21633671841fbe70ea486053cba33d68e3e22ccc0a"}, - {file = "SQLAlchemy-1.4.26-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad7e403fc1e3cb76e802872694e30d6ca6129b9bc6ad4e7caa48ca35f8a144f8"}, - {file = "SQLAlchemy-1.4.26-cp310-cp310-win32.whl", hash = "sha256:7ef421c3887b39c6f352e5022a53ac18de8387de331130481cb956b2d029cad6"}, - {file = "SQLAlchemy-1.4.26-cp310-cp310-win_amd64.whl", hash = "sha256:908fad32c53b17aad12d722379150c3c5317c422437e44032256a77df1746292"}, - {file = "SQLAlchemy-1.4.26-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:1ef37c9ec2015ce2f0dc1084514e197f2f199d3dc3514190db7620b78e6004c8"}, - {file = "SQLAlchemy-1.4.26-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:090536fd23bf49077ee94ff97142bc5ee8bad24294c3d7c8d5284267c885dde7"}, - {file = "SQLAlchemy-1.4.26-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e700d48056475d077f867e6a36e58546de71bdb6fdc3d34b879e3240827fefab"}, - {file = "SQLAlchemy-1.4.26-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:295b90efef1278f27fe27d94a45460ae3c17f5c5c2b32c163e29c359740a1599"}, - {file = "SQLAlchemy-1.4.26-cp36-cp36m-win32.whl", hash = "sha256:cc6b21f19bc9d4cd77cbcba5f3b260436ce033f1053cea225b6efea2603d201e"}, - {file = "SQLAlchemy-1.4.26-cp36-cp36m-win_amd64.whl", hash = "sha256:ba84026e84379326bbf2f0c50792f2ae56ab9c01937df5597b6893810b8ca369"}, - {file = "SQLAlchemy-1.4.26-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f1e97c5f36b94542f72917b62f3a2f92be914b2cf33b80fa69cede7529241d2a"}, - {file = "SQLAlchemy-1.4.26-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c185c928e2638af9bae13acc3f70e0096eac76471a1101a10f96b80666b8270"}, - {file = "SQLAlchemy-1.4.26-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bca660b76672e15d70a7dba5e703e1ce451a0257b6bd2028e62b0487885e8ae9"}, - {file = "SQLAlchemy-1.4.26-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff8f91a7b1c4a1c7772caa9efe640f2768828897044748f2458b708f1026e2d4"}, - {file = "SQLAlchemy-1.4.26-cp37-cp37m-win32.whl", hash = "sha256:a95bf9c725012dcd7ea3cac16bf647054e0d62b31d67467d228338e6a163e4ff"}, - {file = "SQLAlchemy-1.4.26-cp37-cp37m-win_amd64.whl", hash = "sha256:07ac4461a1116b317519ddf6f34bcb00b011b5c1370ebeaaf56595504ffc7e84"}, - {file = "SQLAlchemy-1.4.26-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:5039faa365e7522a8eb4736a54afd24a7e75dcc33b81ab2f0e6c456140f1ad64"}, - {file = "SQLAlchemy-1.4.26-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e8ef103eaa72a857746fd57dda5b8b5961e8e82a528a3f8b7e2884d8506f0b7"}, - {file = "SQLAlchemy-1.4.26-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:31f4426cfad19b5a50d07153146b2bcb372a279975d5fa39f98883c0ef0f3313"}, - {file = "SQLAlchemy-1.4.26-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2feb028dc75e13ba93456a42ac042b255bf94dbd692bf80b47b22653bb25ccf8"}, - {file = "SQLAlchemy-1.4.26-cp38-cp38-win32.whl", hash = "sha256:2ce42ad1f59eb85c55c44fb505f8854081ee23748f76b62a7f569cfa9b6d0604"}, - {file = "SQLAlchemy-1.4.26-cp38-cp38-win_amd64.whl", hash = "sha256:dbf588ab09e522ac2cbd010919a592c6aae2f15ccc3cd9a96d01c42fbc13f63e"}, - {file = "SQLAlchemy-1.4.26-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:a6506c17b0b6016656783232d0bdd03fd333f1f654d51a14d93223f953903646"}, - {file = "SQLAlchemy-1.4.26-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a882dedb9dfa6f33524953c3e3d72bcf518a5defd6d5863150a821928b19ad3"}, - {file = "SQLAlchemy-1.4.26-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1dee515578d04bc80c4f9a8c8cfe93f455db725059e885f1b1da174d91c4d077"}, - {file = "SQLAlchemy-1.4.26-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c0c5f54560a92691d54b0768d67b4d3159e514b426cfcb1258af8c195577e8f"}, - {file = "SQLAlchemy-1.4.26-cp39-cp39-win32.whl", hash = "sha256:b86f762cee3709722ab4691981958cbec475ea43406a6916a7ec375db9cbd9e9"}, - {file = "SQLAlchemy-1.4.26-cp39-cp39-win_amd64.whl", hash = "sha256:5c6774b34782116ad9bdec61c2dbce9faaca4b166a0bc8e7b03c2b870b121d94"}, - {file = "SQLAlchemy-1.4.26.tar.gz", hash = "sha256:6bc7f9d7d90ef55e8c6db1308a8619cd8f40e24a34f759119b95e7284dca351a"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:6afa9e4e63f066e0fd90a21db7e95e988d96127f52bfb298a0e9bec6999357a9"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec1c908fa721f2c5684900cc8ff75555b1a5a2ae4f5a5694eb0e37a5263cea44"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27m-win32.whl", hash = "sha256:0438bccc16349db2d5203598be6073175ce16d4e53b592d6e6cef880c197333e"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27m-win_amd64.whl", hash = "sha256:435b1980c1333ffe3ab386ad28d7b209590b0fa83ea8544d853e7a22f957331b"}, + {file = "SQLAlchemy-1.4.27-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:486f7916ef77213103467924ef25f5ea1055ae901f385fe4d707604095fdf6a9"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:d81c84c9d2523b3ea20f8e3aceea68615768a7464c0f9a9899600ce6592ec570"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5881644fc51af7b232ab8d64f75c0f32295dfe88c2ee188023795cdbd4cf99b"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:24828c5e74882cf41516740c0b150702bee4c6817d87d5c3d3bafef2e6896f80"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7d0a1b1258efff7d7f2e6cfa56df580d09ba29d35a1e3f604f867e1f685feb2"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-win32.whl", hash = "sha256:aadc6d1e58e14010ae4764d1ba1fd0928dbb9423b27a382ea3a1444f903f4084"}, + {file = "SQLAlchemy-1.4.27-cp310-cp310-win_amd64.whl", hash = "sha256:9134e5810262203388b203c2022bbcbf1a22e89861eef9340e772a73dd9076fa"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:fa52534076394af7315306a8701b726a6521b591d95e8f4e5121c82f94790e8d"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2717ceae35e71de1f58b0d1ee7e773d3aab5c403c6e79e8d262277c7f7f95269"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2e93624d186ea7a738ada47314701c8830e0e4b021a6bce7fbe6f39b87ee1516"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:987fe2f84ceaf744fa0e48805152abe485a9d7002c9923b18a4b2529c7bff218"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-win32.whl", hash = "sha256:2146ef996181e3d4dd20eaf1d7325eb62d6c8aa4dc1677c1872ddfa8561a47d9"}, + {file = "SQLAlchemy-1.4.27-cp36-cp36m-win_amd64.whl", hash = "sha256:ad8ec6b69d03e395db48df8991aa15fce3cd23e378b73e01d46a26a6efd5c26d"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:52f23a76544ed29573c0f3ee41f0ca1aedbab3a453102b60b540cc6fa55448ad"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd421a14edf73cfe01e8f51ed8966294ee3b3db8da921cacc88e497fd6e977af"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:10230364479429437f1b819a8839f1edc5744c018bfeb8d01320930f97695bc9"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78943451ab3ffd0e27876f9cea2b883317518b418f06b90dadf19394534637e9"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-win32.whl", hash = "sha256:a81e40dfa50ed3c472494adadba097640bfcf43db160ed783132045eb2093cb1"}, + {file = "SQLAlchemy-1.4.27-cp37-cp37m-win_amd64.whl", hash = "sha256:015511c52c650eebf1059ed8a21674d9d4ae567ebfd80fc73f8252faccd71864"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:cc49fb8ff103900c20e4a9c53766c82a7ebbc183377fb357a8298bad216e9cdd"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9369f927f4d19b58322cfea8a51710a3f7c47a0e7f3398d94a4632760ecd74f6"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6510f4a5029643301bdfe56b61e806093af2101d347d485c42a5535847d2c699"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:771eca9872b47a629010665ff92de1c248a6979b8d1603daced37773d6f6e365"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-win32.whl", hash = "sha256:4d1d707b752137e6bf45720648e1b828d5e4881d690df79cca07f7217ea06365"}, + {file = "SQLAlchemy-1.4.27-cp38-cp38-win_amd64.whl", hash = "sha256:c035184af4e58e154b0977eea52131edd096e0754a88f7d5a847e7ccb3510772"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:bac949be7579fed824887eed6672f44b7c4318abbfb2004b2c6968818b535a2f"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ac8306e04275d382d6393e557047b0a9d7ddf9f7ca5da9b3edbd9323ea75bd9"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8327e468b1775c0dfabc3d01f39f440585bf4d398508fcbbe2f0d931c502337d"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b02eee1577976acb4053f83d32b7826424f8b9f70809fa756529a52c6537eda4"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-win32.whl", hash = "sha256:5beeff18b4e894f6cb73c8daf2c0d8768844ef40d97032bb187d75b1ec8de24b"}, + {file = "SQLAlchemy-1.4.27-cp39-cp39-win_amd64.whl", hash = "sha256:8dbe5f639e6d035778ebf700be6d573f82a13662c3c2c3aa0f1dba303b942806"}, + {file = "SQLAlchemy-1.4.27.tar.gz", hash = "sha256:d768359daeb3a86644f3854c6659e4496a3e6bba2b4651ecc87ce7ad415b320c"}, ] starlette = [ - {file = "starlette-0.14.2-py3-none-any.whl", hash = "sha256:3c8e48e52736b3161e34c9f0e8153b4f32ec5d8995a3ee1d59410d92f75162ed"}, - {file = "starlette-0.14.2.tar.gz", hash = "sha256:7d49f4a27f8742262ef1470608c59ddbc66baf37c148e938c7038e6bc7a998aa"}, + {file = "starlette-0.17.1-py3-none-any.whl", hash = "sha256:26a18cbda5e6b651c964c12c88b36d9898481cd428ed6e063f5f29c418f73050"}, + {file = "starlette-0.17.1.tar.gz", hash = "sha256:57eab3cc975a28af62f6faec94d355a410634940f10b30d68d31cb5ec1b44ae8"}, ] transliterate = [ {file = "transliterate-1.10.2-py2.py3-none-any.whl", hash = "sha256:010a5021bf6021689c4fade0985f3f7b3db1f2f16a48a09a56797f171c08ed42"}, {file = "transliterate-1.10.2.tar.gz", hash = "sha256:bc608e0d48e687db9c2b1d7ea7c381afe0d1849cad216087d8e03d8d06a57c85"}, ] +typing = [ + {file = "typing-3.7.4.3-py2-none-any.whl", hash = "sha256:283d868f5071ab9ad873e5e52268d611e851c870a2ba354193026f2dfb29d8b5"}, + {file = "typing-3.7.4.3.tar.gz", hash = "sha256:1187fb9c82fd670d10aa07bbb6cfcfe4bdda42d6fab8d5134f04e8c4d0b71cc9"}, +] typing-extensions = [ - {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, - {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, - {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, + {file = "typing_extensions-4.0.0-py3-none-any.whl", hash = "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9"}, + {file = "typing_extensions-4.0.0.tar.gz", hash = "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed"}, ] urllib3 = [ {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"},