From a9a8f6d5db383bbb4e9c830bae98dcad1258958d Mon Sep 17 00:00:00 2001 From: James Ward Date: Wed, 18 Mar 2020 22:59:37 -0400 Subject: [PATCH] improve incremental sync support updates of schema and rows --- notion_docs_sync/__init__.py | 35 ++++++++++++++++++++++++++++------- notion_docs_sync/markdown.py | 26 +++++++------------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/notion_docs_sync/__init__.py b/notion_docs_sync/__init__.py index 74cf2c6..bf82623 100644 --- a/notion_docs_sync/__init__.py +++ b/notion_docs_sync/__init__.py @@ -1,6 +1,7 @@ import logging import os from random import choice +from collections import OrderedDict from argparse import ArgumentParser from notion.client import NotionClient @@ -94,6 +95,19 @@ def block_matches_markdown_block(block, markdown_block_type, **markdown_block): return True +def sync_collection_schema(collection, expected_schema): + existing_schema = collection.get('schema') + + # The schemas must match! + if existing_schema == expected_schema: + return + + logger.info(f"Updating schema of {collection.id}") + + # If they don't, try to make them match. + collection.set('schema', expected_schema) + + def sync_collection_rows(block, collection_schema, collection_rows): if block.collection is None: logger.info(f"Creating a new collection for {block.id}") @@ -102,12 +116,17 @@ def sync_collection_rows(block, collection_schema, collection_rows): block.collection = client.get_collection( # Low-level use of the API # TODO: Update when notion-py provides a better interface for this - client.create_record("collection", parent=block, schema=collection_schema) + client.create_record("collection", parent=block, schema={"title": {"text": "_", "type": "text"}}) ) block.views.add_new(view_type="table") - # TODO: Compare collection schema and update the collection if it's not matching. + collection_schema_ids = ['title'] + + for i in range(len(collection_schema) - 1): + collection_schema_ids.append('x' + format(i, '0>4x')) + + sync_collection_schema(block.collection, dict(zip(collection_schema_ids, collection_schema))) existing_rows = block.collection.get_rows() @@ -122,12 +141,14 @@ def sync_collection_rows(block, collection_schema, collection_rows): except StopIteration: row_block = block.collection.add_row() - for idx, prop_name in enumerate(prop["name"] for prop in collection_schema.values()): - prop_name = prop_name.lower() # The actual prop name in notion-py is lowercase - prop_val = row[idx] + if len(row) > len(collection_schema_ids): + row = row[:len(collection_schema_ids)] + + row = zip(collection_schema_ids, row) - if getattr(row_block, prop_name) != prop_val: - setattr(row_block, prop_name, prop_val) + for schema_id, prop_value in row: + if row_block.get_property(schema_id) != prop_value: + row_block.set_property(schema_id, prop_value) def sync_markdown_blocks_to_block(markdown_blocks, block): diff --git a/notion_docs_sync/markdown.py b/notion_docs_sync/markdown.py index 863890f..1044ae4 100644 --- a/notion_docs_sync/markdown.py +++ b/notion_docs_sync/markdown.py @@ -1,14 +1,11 @@ import logging -import random import re import collections from notion.block import CodeBlock, DividerBlock, HeaderBlock, SubheaderBlock, \ SubsubheaderBlock, QuoteBlock, TextBlock, NumberedListBlock, \ BulletedListBlock, ImageBlock, CollectionViewBlock import mistletoe -import string from mistletoe.base_renderer import BaseRenderer -from mistletoe.span_token import Image, Link logger = logging.getLogger(__name__) @@ -231,22 +228,13 @@ def render_list_item(self, token): } def render_table(self, token): - header_row = self.render(token.header) #Header is a single row - rows = [self.render(r) for r in token.children] #don't use renderMultiple because it flattens - - def random_column_id(): - return ''.join(random.choices(string.ascii_letters + string.digits, k=4)) - - # The schema is basically special identifiers + the type of property to put into Notion. - schema = { random_column_id() : { 'name' : header_row[r], 'type': 'text' }for r in range(len(header_row) - 1) } - - # However, The last one needs to be named 'Title' and is type title - schema.update({ - 'title' : { - 'name': header_row[-1], - 'type': 'title' - } - }) + header_row = self.render(token.header) + rows = [self.render(r) for r in token.children] + + schema = [] + + for row in header_row: + schema.append({"name": row, "type": "text"}) return { 'type': CollectionViewBlock,