Skip to content

Blocks

Wrapper for Notion API blocks.

Blocks are the base for all Notion content.

Block

Bases: DataRecord, TypedObject

A standard block object in Notion.

Calling the block will expose the nested data in the object.

Source code in src/notional/blocks.py
123
124
125
126
127
class Block(DataRecord, TypedObject, object="block"):
    """A standard block object in Notion.

    Calling the block will expose the nested data in the object.
    """

Bookmark

Bases: Block

A bookmark block in Notion.

Source code in src/notional/blocks.py
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
class Bookmark(Block, type="bookmark"):
    """A bookmark block in Notion."""

    class _NestedData(GenericObject):
        url: str = None
        caption: Optional[List[RichTextObject]] = None

    bookmark: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, url):
        """Compose a new `Bookmark` block from a specific URL."""
        return Bookmark(bookmark=Bookmark._NestedData(url=url))

    @property
    def URL(self):
        """Return the URL contained in this `Bookmark` block."""
        return self.bookmark.url

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.bookmark and self.bookmark.url:
            return f"<{self.bookmark.url}>"

        return ""

Markdown property

Return the contents of this block as markdown text.

URL property

Return the URL contained in this Bookmark block.

__compose__(url) classmethod

Compose a new Bookmark block from a specific URL.

Source code in src/notional/blocks.py
521
522
523
524
@classmethod
def __compose__(cls, url):
    """Compose a new `Bookmark` block from a specific URL."""
    return Bookmark(bookmark=Bookmark._NestedData(url=url))

Breadcrumb

Bases: Block

A breadcrumb block in Notion.

Source code in src/notional/blocks.py
475
476
477
478
479
480
481
class Breadcrumb(Block, type="breadcrumb"):
    """A breadcrumb block in Notion."""

    class _NestedData(GenericObject):
        pass

    breadcrumb: _NestedData = _NestedData()

BulletedListItem

Bases: TextBlock, WithChildrenMixin

A bulleted list item in Notion.

Source code in src/notional/blocks.py
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
class BulletedListItem(TextBlock, WithChildrenMixin, type="bulleted_list_item"):
    """A bulleted list item in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        children: Optional[List[Block]] = None
        color: FullColor = FullColor.DEFAULT

    bulleted_list_item: _NestedData = _NestedData()

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.bulleted_list_item and self.bulleted_list_item.rich_text:
            return f"- {markdown(*self.bulleted_list_item.rich_text)}"

        return ""

Markdown property

Return the contents of this block as markdown text.

Callout

Bases: TextBlock, WithChildrenMixin

A callout block in Notion.

Source code in src/notional/blocks.py
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
class Callout(TextBlock, WithChildrenMixin, type="callout"):
    """A callout block in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        children: Optional[List[Block]] = None
        icon: Optional[Union[FileObject, EmojiObject]] = None
        color: FullColor = FullColor.GRAY_BACKGROUND

    callout: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, text, emoji=None, color=FullColor.GRAY_BACKGROUND):
        """Compose a `Callout` block from the given text, emoji and color."""

        if emoji is not None:
            emoji = EmojiObject[emoji]

        nested = Callout._NestedData(icon=emoji, color=color)

        callout = cls(callout=nested)
        callout.concat(text)

        return callout

__compose__(text, emoji=None, color=FullColor.GRAY_BACKGROUND) classmethod

Compose a Callout block from the given text, emoji and color.

Source code in src/notional/blocks.py
347
348
349
350
351
352
353
354
355
356
357
358
359
@classmethod
def __compose__(cls, text, emoji=None, color=FullColor.GRAY_BACKGROUND):
    """Compose a `Callout` block from the given text, emoji and color."""

    if emoji is not None:
        emoji = EmojiObject[emoji]

    nested = Callout._NestedData(icon=emoji, color=color)

    callout = cls(callout=nested)
    callout.concat(text)

    return callout

ChildDatabase

Bases: Block

A child database block in Notion.

Source code in src/notional/blocks.py
616
617
618
619
620
621
622
class ChildDatabase(Block, type="child_database"):
    """A child database block in Notion."""

    class _NestedData(GenericObject):
        title: str = None

    child_database: _NestedData = _NestedData()

ChildPage

Bases: Block

A child page block in Notion.

Source code in src/notional/blocks.py
607
608
609
610
611
612
613
class ChildPage(Block, type="child_page"):
    """A child page block in Notion."""

    class _NestedData(GenericObject):
        title: str = None

    child_page: _NestedData = _NestedData()

Code

Bases: TextBlock

A code block in Notion.

Source code in src/notional/blocks.py
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
class Code(TextBlock, type="code"):
    """A code block in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        caption: List[RichTextObject] = []
        language: CodingLanguage = CodingLanguage.PLAIN_TEXT

    code: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, text, lang=CodingLanguage.PLAIN_TEXT):
        """Compose a `Code` block from the given text and language."""
        block = super().__compose__(text)
        block.code.language = lang
        return block

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        lang = self.code.language.value if self.code and self.code.language else ""

        # FIXME this is not the standard way to represent code blocks in markdown...

        if self.code and self.code.rich_text:
            return f"```{lang}\n{markdown(*self.code.rich_text)}\n```"

        return ""

Markdown property

Return the contents of this block as markdown text.

__compose__(text, lang=CodingLanguage.PLAIN_TEXT) classmethod

Compose a Code block from the given text and language.

Source code in src/notional/blocks.py
315
316
317
318
319
320
@classmethod
def __compose__(cls, text, lang=CodingLanguage.PLAIN_TEXT):
    """Compose a `Code` block from the given text and language."""
    block = super().__compose__(text)
    block.code.language = lang
    return block

Column

Bases: Block, WithChildrenMixin

A column block in Notion.

Source code in src/notional/blocks.py
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
class Column(Block, WithChildrenMixin, type="column"):
    """A column block in Notion."""

    class _NestedData(GenericObject):
        # note that children will not be populated when getting this block
        # https://developers.notion.com/changelog/column-list-and-column-support
        children: Optional[List[Block]] = None

    column: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, *blocks):
        """Create a new `Column` block with the given blocks as children."""
        col = cls()

        for block in blocks:
            col.append(block)

        return col

__compose__(*blocks) classmethod

Create a new Column block with the given blocks as children.

Source code in src/notional/blocks.py
635
636
637
638
639
640
641
642
643
@classmethod
def __compose__(cls, *blocks):
    """Create a new `Column` block with the given blocks as children."""
    col = cls()

    for block in blocks:
        col.append(block)

    return col

ColumnList

Bases: Block, WithChildrenMixin

A column list block in Notion.

Source code in src/notional/blocks.py
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
class ColumnList(Block, WithChildrenMixin, type="column_list"):
    """A column list block in Notion."""

    class _NestedData(GenericObject):
        # note that children will not be populated when getting this block
        # https://developers.notion.com/changelog/column-list-and-column-support
        children: Optional[List[Column]] = None

    column_list: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, *columns):
        """Create a new `Column` block with the given blocks as children."""
        cols = cls()

        for col in columns:
            cols.append(col)

        return cols

__compose__(*columns) classmethod

Create a new Column block with the given blocks as children.

Source code in src/notional/blocks.py
656
657
658
659
660
661
662
663
664
@classmethod
def __compose__(cls, *columns):
    """Create a new `Column` block with the given blocks as children."""
    cols = cls()

    for col in columns:
        cols.append(col)

    return cols

DataRecord

Bases: NotionObject

The base type for all Notion API records.

Source code in src/notional/blocks.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class DataRecord(NotionObject):
    """The base type for all Notion API records."""

    id: UUID = None

    parent: ParentRef = None
    has_children: bool = False

    archived: bool = False

    created_time: datetime = None
    created_by: User = None

    last_edited_time: datetime = None
    last_edited_by: User = None

Database

Bases: DataRecord

A database record type.

Source code in src/notional/blocks.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class Database(DataRecord, object="database"):
    """A database record type."""

    title: List[RichTextObject] = None
    url: str = None
    icon: Optional[Union[FileObject, EmojiObject]] = None
    cover: Optional[FileObject] = None
    properties: Dict[str, PropertyObject] = {}
    description: Optional[List[RichTextObject]] = None
    is_inline: bool = False

    @property
    def Title(self):
        """Return the title of this database as plain text."""
        if self.title is None or len(self.title) == 0:
            return None

        return plain_text(*self.title)

Title property

Return the title of this database as plain text.

Divider

Bases: Block

A divider block in Notion.

Source code in src/notional/blocks.py
455
456
457
458
459
460
461
462
463
class Divider(Block, type="divider"):
    """A divider block in Notion."""

    divider: Any = {}

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""
        return "---"

Markdown property

Return the contents of this block as markdown text.

Embed

Bases: Block

An embed block in Notion.

Source code in src/notional/blocks.py
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
class Embed(Block, type="embed"):
    """An embed block in Notion."""

    class _NestedData(GenericObject):
        url: str = None

    embed: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, url):
        """Create a new `Embed` block from the given URL."""
        return Embed(embed=Embed._NestedData(url=url))

    @property
    def URL(self):
        """Return the URL contained in this `Embed` block."""
        return self.embed.url

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.embed and self.embed.url:
            return f"<{self.embed.url}>"

        return ""

Markdown property

Return the contents of this block as markdown text.

URL property

Return the URL contained in this Embed block.

__compose__(url) classmethod

Create a new Embed block from the given URL.

Source code in src/notional/blocks.py
492
493
494
495
@classmethod
def __compose__(cls, url):
    """Create a new `Embed` block from the given URL."""
    return Embed(embed=Embed._NestedData(url=url))

Equation

Bases: Block

An equation block in Notion.

Source code in src/notional/blocks.py
569
570
571
572
573
574
575
576
577
578
579
580
class Equation(Block, type="equation"):
    """An equation block in Notion."""

    class _NestedData(GenericObject):
        expression: str = None

    equation: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, expr):
        """Create a new `Equation` block from the given expression."""
        return LinkPreview(equation=Equation._NestedData(expression=expr))

__compose__(expr) classmethod

Create a new Equation block from the given expression.

Source code in src/notional/blocks.py
577
578
579
580
@classmethod
def __compose__(cls, expr):
    """Create a new `Equation` block from the given expression."""
    return LinkPreview(equation=Equation._NestedData(expression=expr))

File

Bases: Block

A file block in Notion.

Source code in src/notional/blocks.py
583
584
585
586
class File(Block, type="file"):
    """A file block in Notion."""

    file: FileObject = None

Heading1

Bases: TextBlock

A heading_1 block in Notion.

Source code in src/notional/blocks.py
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
class Heading1(TextBlock, type="heading_1"):
    """A heading_1 block in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        color: FullColor = FullColor.DEFAULT

    heading_1: _NestedData = _NestedData()

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.heading_1 and self.heading_1.rich_text:
            return f"# {markdown(*self.heading_1.rich_text)} #"

        return ""

Markdown property

Return the contents of this block as markdown text.

Heading2

Bases: TextBlock

A heading_2 block in Notion.

Source code in src/notional/blocks.py
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
class Heading2(TextBlock, type="heading_2"):
    """A heading_2 block in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        color: FullColor = FullColor.DEFAULT

    heading_2: _NestedData = _NestedData()

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.heading_2 and self.heading_2.rich_text:
            return f"## {markdown(*self.heading_2.rich_text)} ##"

        return ""

Markdown property

Return the contents of this block as markdown text.

Heading3

Bases: TextBlock

A heading_3 block in Notion.

Source code in src/notional/blocks.py
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
class Heading3(TextBlock, type="heading_3"):
    """A heading_3 block in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        color: FullColor = FullColor.DEFAULT

    heading_3: _NestedData = _NestedData()

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.heading_3 and self.heading_3.rich_text:
            return f"### {markdown(*self.heading_3.rich_text)} ###"

        return ""

Markdown property

Return the contents of this block as markdown text.

Image

Bases: Block

An image block in Notion.

Source code in src/notional/blocks.py
589
590
591
592
class Image(Block, type="image"):
    """An image block in Notion."""

    image: FileObject = None

LinkPreview

Bases: Block

A link_preview block in Notion.

Source code in src/notional/blocks.py
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
class LinkPreview(Block, type="link_preview"):
    """A link_preview block in Notion."""

    class _NestedData(GenericObject):
        url: str = None

    link_preview: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, url):
        """Create a new `LinkPreview` block from the given URL."""
        return LinkPreview(link_preview=LinkPreview._NestedData(url=url))

    @property
    def URL(self):
        """Return the URL contained in this `LinkPreview` block."""
        return self.link_preview.url

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.link_preview and self.link_preview.url:
            return f"<{self.link_preview.url}>"

        return ""

Markdown property

Return the contents of this block as markdown text.

URL property

Return the URL contained in this LinkPreview block.

__compose__(url) classmethod

Create a new LinkPreview block from the given URL.

Source code in src/notional/blocks.py
549
550
551
552
@classmethod
def __compose__(cls, url):
    """Create a new `LinkPreview` block from the given URL."""
    return LinkPreview(link_preview=LinkPreview._NestedData(url=url))

LinkToPage

Bases: Block

A link_to_page block in Notion.

Source code in src/notional/blocks.py
778
779
780
781
class LinkToPage(Block, type="link_to_page"):
    """A link_to_page block in Notion."""

    link_to_page: ParentRef

NumberedListItem

Bases: TextBlock, WithChildrenMixin

A numbered list item in Notion.

Source code in src/notional/blocks.py
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
class NumberedListItem(TextBlock, WithChildrenMixin, type="numbered_list_item"):
    """A numbered list item in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        children: Optional[List[Block]] = None
        color: FullColor = FullColor.DEFAULT

    numbered_list_item: _NestedData = _NestedData()

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.numbered_list_item and self.numbered_list_item.rich_text:
            return f"1. {markdown(*self.numbered_list_item.rich_text)}"

        return ""

Markdown property

Return the contents of this block as markdown text.

PDF

Bases: Block

A pdf block in Notion.

Source code in src/notional/blocks.py
601
602
603
604
class PDF(Block, type="pdf"):
    """A pdf block in Notion."""

    pdf: FileObject = None

Page

Bases: DataRecord

A standard Notion page object.

Source code in src/notional/blocks.py
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
class Page(DataRecord, object="page"):
    """A standard Notion page object."""

    url: str = None
    icon: Optional[Union[FileObject, EmojiObject]] = None
    cover: Optional[FileObject] = None
    properties: Dict[str, PropertyValue] = {}

    def __getitem__(self, name):
        """Indexer for the given property name.

        :param name: the name of the property to get from the internal properties
        """

        prop = self.properties.get(name)

        if prop is None:
            raise AttributeError(f"No such property: {name}")

        return prop

    def __setitem__(self, name, value):
        """Set the object data for the given property.

        If `value` is `None`, the property data will be deleted from the page.  This
        does not affect the schema of the page, only the contents of the property.

        :param name: the name of the property to set in the internal properties
        :param value: the new value for the given property
        """

        if value is None:
            self.properties.pop(name, None)

        elif isinstance(value, PropertyValue):
            self.properties[name] = value

        else:
            raise ValueError(f"Unable to set {name} :: unsupported value type")

    @property
    def Title(self):
        """Return the title of this page as a string.

        The title of a page is stored in its properties.  This method will examine the
        page properties, looking for the appropriate `title` entry and return as a
        string.
        """

        # the 'title' property may (or may not) be indexed by name...  especially in
        # the case of # database pages.  the only reliable way to find the title is by
        # scanning each property.

        for prop in self.properties.values():
            if prop.id == "title":
                return prop.Value

        return None

Title property

Return the title of this page as a string.

The title of a page is stored in its properties. This method will examine the page properties, looking for the appropriate title entry and return as a string.

__getitem__(name)

Indexer for the given property name.

:param name: the name of the property to get from the internal properties

Source code in src/notional/blocks.py
71
72
73
74
75
76
77
78
79
80
81
82
def __getitem__(self, name):
    """Indexer for the given property name.

    :param name: the name of the property to get from the internal properties
    """

    prop = self.properties.get(name)

    if prop is None:
        raise AttributeError(f"No such property: {name}")

    return prop

__setitem__(name, value)

Set the object data for the given property.

If value is None, the property data will be deleted from the page. This does not affect the schema of the page, only the contents of the property.

:param name: the name of the property to set in the internal properties :param value: the new value for the given property

Source code in src/notional/blocks.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
def __setitem__(self, name, value):
    """Set the object data for the given property.

    If `value` is `None`, the property data will be deleted from the page.  This
    does not affect the schema of the page, only the contents of the property.

    :param name: the name of the property to set in the internal properties
    :param value: the new value for the given property
    """

    if value is None:
        self.properties.pop(name, None)

    elif isinstance(value, PropertyValue):
        self.properties[name] = value

    else:
        raise ValueError(f"Unable to set {name} :: unsupported value type")

Paragraph

Bases: TextBlock, WithChildrenMixin

A paragraph block in Notion.

Source code in src/notional/blocks.py
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
class Paragraph(TextBlock, WithChildrenMixin, type="paragraph"):
    """A paragraph block in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        children: Optional[List[Block]] = None
        color: FullColor = FullColor.DEFAULT

    paragraph: _NestedData = _NestedData()

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.paragraph and self.paragraph.rich_text:
            return markdown(*self.paragraph.rich_text)

        return ""

Markdown property

Return the contents of this block as markdown text.

Quote

Bases: TextBlock, WithChildrenMixin

A quote block in Notion.

Source code in src/notional/blocks.py
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
class Quote(TextBlock, WithChildrenMixin, type="quote"):
    """A quote block in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        children: Optional[List[Block]] = None
        color: FullColor = FullColor.DEFAULT

    quote: _NestedData = _NestedData()

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.quote and self.quote.rich_text:
            return "> " + markdown(*self.quote.rich_text)

        return ""

Markdown property

Return the contents of this block as markdown text.

SyncedBlock

Bases: Block, WithChildrenMixin

A synced_block block in Notion - either original or synced.

Source code in src/notional/blocks.py
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
class SyncedBlock(Block, WithChildrenMixin, type="synced_block"):
    """A synced_block block in Notion - either original or synced."""

    class _NestedData(GenericObject):
        synced_from: Optional[BlockRef] = None
        children: Optional[List[Block]] = None

    synced_block: _NestedData = _NestedData()

    @property
    def IsOriginal(self):
        """Determine if this block represents the original content.

        If this method returns `False`, the block represents the sync'ed block.
        """
        return self.synced_block.synced_from is None

IsOriginal property

Determine if this block represents the original content.

If this method returns False, the block represents the sync'ed block.

Table

Bases: Block, WithChildrenMixin

A table block in Notion.

Source code in src/notional/blocks.py
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
class Table(Block, WithChildrenMixin, type="table"):
    """A table block in Notion."""

    class _NestedData(GenericObject):
        table_width: int = 0
        has_column_header: bool = False
        has_row_header: bool = False

        # note that children will not be populated when getting this block
        # https://developers.notion.com/reference/block#table-blocks
        children: Optional[List[TableRow]] = []

    table: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, *rows):
        """Create a new `Table` block with the given rows."""
        table = cls()

        for row in rows:
            table.append(row)

        return table

    def append(self, block: TableRow):
        """Append the given row to this table.

        This method is only applicable when creating a new `Table` block.  In order to
        add rows to an existing `Table`, use the `blocks.children.append()` endpoint.

        When adding a row, this method will rase an exception if the width does not
        match the expected number of cells for existing rows in the block.
        """

        # XXX need to review whether this is applicable during update...  may need
        # to raise an error if the block has already been created on the server

        if not isinstance(block, TableRow):
            raise ValueError("Only TableRow may be appended to Table blocks.")

        if self.Width == 0:
            self.table.table_width = block.Width
        elif self.Width != block.Width:
            raise ValueError("Number of cells in row must match table")

        self.table.children.append(block)

    @property
    def Width(self):
        """Return the current width of this table."""
        return self.table.table_width

Width property

Return the current width of this table.

__compose__(*rows) classmethod

Create a new Table block with the given rows.

Source code in src/notional/blocks.py
739
740
741
742
743
744
745
746
747
@classmethod
def __compose__(cls, *rows):
    """Create a new `Table` block with the given rows."""
    table = cls()

    for row in rows:
        table.append(row)

    return table

append(block)

Append the given row to this table.

This method is only applicable when creating a new Table block. In order to add rows to an existing Table, use the blocks.children.append() endpoint.

When adding a row, this method will rase an exception if the width does not match the expected number of cells for existing rows in the block.

Source code in src/notional/blocks.py
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
def append(self, block: TableRow):
    """Append the given row to this table.

    This method is only applicable when creating a new `Table` block.  In order to
    add rows to an existing `Table`, use the `blocks.children.append()` endpoint.

    When adding a row, this method will rase an exception if the width does not
    match the expected number of cells for existing rows in the block.
    """

    # XXX need to review whether this is applicable during update...  may need
    # to raise an error if the block has already been created on the server

    if not isinstance(block, TableRow):
        raise ValueError("Only TableRow may be appended to Table blocks.")

    if self.Width == 0:
        self.table.table_width = block.Width
    elif self.Width != block.Width:
        raise ValueError("Number of cells in row must match table")

    self.table.children.append(block)

TableOfContents

Bases: Block

A table_of_contents block in Notion.

Source code in src/notional/blocks.py
466
467
468
469
470
471
472
class TableOfContents(Block, type="table_of_contents"):
    """A table_of_contents block in Notion."""

    class _NestedData(GenericObject):
        color: FullColor = FullColor.DEFAULT

    table_of_contents: _NestedData = _NestedData()

TableRow

Bases: Block

A table_row block in Notion.

Source code in src/notional/blocks.py
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
class TableRow(Block, type="table_row"):
    """A table_row block in Notion."""

    class _NestedData(GenericObject):
        cells: List[List[RichTextObject]] = None

        def __getitem__(self, col):
            """Return the cell content for the requested column.

            This will raise an `IndexError` if there are not enough columns.
            """
            if col > len(self.cells):
                raise IndexError()

            return self.cells[col]

    table_row: _NestedData = _NestedData()

    def __getitem__(self, cell_num):
        """Return the cell content for the requested column."""
        return self.table_row[cell_num]

    @classmethod
    def __compose__(cls, *cells):
        """Create a new `TableRow` block with the given cell contents."""
        row = cls()

        for cell in cells:
            row.append(cell)

        return row

    def append(self, text):
        """Append the given text as a new cell in this `TableRow`.

        `text` may be a string, `RichTextObject` or a list of `RichTextObject`'s.

        :param text: the text content to append
        """
        if self.table_row.cells is None:
            self.table_row.cells = []

        if isinstance(text, list):
            self.table_row.cells.append(list)

        elif isinstance(text, RichTextObject):
            self.table_row.cells.append([text])

        else:
            rtf = TextObject[text]
            self.table_row.cells.append([rtf])

    @property
    def Width(self):
        """Return the width (number of cells) in this `TableRow`."""
        return len(self.table_row.cells) if self.table_row.cells else 0

Width property

Return the width (number of cells) in this TableRow.

__compose__(*cells) classmethod

Create a new TableRow block with the given cell contents.

Source code in src/notional/blocks.py
689
690
691
692
693
694
695
696
697
@classmethod
def __compose__(cls, *cells):
    """Create a new `TableRow` block with the given cell contents."""
    row = cls()

    for cell in cells:
        row.append(cell)

    return row

__getitem__(cell_num)

Return the cell content for the requested column.

Source code in src/notional/blocks.py
685
686
687
def __getitem__(self, cell_num):
    """Return the cell content for the requested column."""
    return self.table_row[cell_num]

append(text)

Append the given text as a new cell in this TableRow.

text may be a string, RichTextObject or a list of RichTextObject's.

:param text: the text content to append

Source code in src/notional/blocks.py
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
def append(self, text):
    """Append the given text as a new cell in this `TableRow`.

    `text` may be a string, `RichTextObject` or a list of `RichTextObject`'s.

    :param text: the text content to append
    """
    if self.table_row.cells is None:
        self.table_row.cells = []

    if isinstance(text, list):
        self.table_row.cells.append(list)

    elif isinstance(text, RichTextObject):
        self.table_row.cells.append([text])

    else:
        rtf = TextObject[text]
        self.table_row.cells.append([rtf])

Template

Bases: Block, WithChildrenMixin

A template block in Notion.

Source code in src/notional/blocks.py
802
803
804
805
806
807
808
809
class Template(Block, WithChildrenMixin, type="template"):
    """A template block in Notion."""

    class _NestedData(GenericObject):
        rich_text: Optional[List[RichTextObject]] = None
        children: Optional[List[Block]] = None

    template: _NestedData = _NestedData()

TextBlock

Bases: Block, ABC

A standard text block object in Notion.

Source code in src/notional/blocks.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
class TextBlock(Block, ABC):
    """A standard text block object in Notion."""

    # text blocks have a nested object with 'type' name and a 'rich_text' child

    @property
    def __text__(self):
        """Provide shorthand access to the nested text content in this block."""

        return self("rich_text")

    @classmethod
    def __compose__(cls, *text):
        """Compose a `TextBlock` from the given text items."""

        obj = cls()
        obj.concat(*text)

        return obj

    def concat(self, *text):
        """Concatenate text (either `RichTextObject` or `str` items) to this block."""

        rtf = rich_text(*text)

        # calling the block returns the nested data...  this helps deal with
        # sublcasses of `TextBlock` that each have different "type" attributes
        nested = self()
        nested.rich_text.extend(rtf)

    @property
    def PlainText(self):
        """Return the contents of this Block as plain text."""

        content = self.__text__

        return None if content is None else plain_text(*content)

PlainText property

Return the contents of this Block as plain text.

__text__ property

Provide shorthand access to the nested text content in this block.

__compose__(*text) classmethod

Compose a TextBlock from the given text items.

Source code in src/notional/blocks.py
150
151
152
153
154
155
156
157
@classmethod
def __compose__(cls, *text):
    """Compose a `TextBlock` from the given text items."""

    obj = cls()
    obj.concat(*text)

    return obj

concat(*text)

Concatenate text (either RichTextObject or str items) to this block.

Source code in src/notional/blocks.py
159
160
161
162
163
164
165
166
167
def concat(self, *text):
    """Concatenate text (either `RichTextObject` or `str` items) to this block."""

    rtf = rich_text(*text)

    # calling the block returns the nested data...  this helps deal with
    # sublcasses of `TextBlock` that each have different "type" attributes
    nested = self()
    nested.rich_text.extend(rtf)

ToDo

Bases: TextBlock, WithChildrenMixin

A todo list item in Notion.

Source code in src/notional/blocks.py
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
class ToDo(TextBlock, WithChildrenMixin, type="to_do"):
    """A todo list item in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        checked: bool = False
        children: Optional[List[Block]] = None
        color: FullColor = FullColor.DEFAULT

    to_do: _NestedData = _NestedData()

    @classmethod
    def __compose__(cls, text, checked=False, href=None):
        """Compose a ToDo block from the given text and checked state."""
        return ToDo(
            to_do=ToDo._NestedData(
                rich_text=[TextObject[text, href]],
                checked=checked,
            )
        )

    @property
    def IsChecked(self):
        """Determine if this ToDo is marked as checked or not.

        If the block is empty (e.g. no nested data), this method returns `None`.
        """
        return self.to_do.checked if self.to_do else None

    @property
    def Markdown(self):
        """Return the contents of this block as markdown text."""

        if self.to_do and self.to_do.rich_text:
            if self.to_do.checked:
                return f"- [x] {markdown(*self.to_do.rich_text)}"

            return f"- [ ] {markdown(*self.to_do.rich_text)}"

        return ""

IsChecked property

Determine if this ToDo is marked as checked or not.

If the block is empty (e.g. no nested data), this method returns None.

Markdown property

Return the contents of this block as markdown text.

__compose__(text, checked=False, href=None) classmethod

Compose a ToDo block from the given text and checked state.

Source code in src/notional/blocks.py
413
414
415
416
417
418
419
420
421
@classmethod
def __compose__(cls, text, checked=False, href=None):
    """Compose a ToDo block from the given text and checked state."""
    return ToDo(
        to_do=ToDo._NestedData(
            rich_text=[TextObject[text, href]],
            checked=checked,
        )
    )

Toggle

Bases: TextBlock, WithChildrenMixin

A toggle list item in Notion.

Source code in src/notional/blocks.py
444
445
446
447
448
449
450
451
452
class Toggle(TextBlock, WithChildrenMixin, type="toggle"):
    """A toggle list item in Notion."""

    class _NestedData(GenericObject):
        rich_text: List[RichTextObject] = []
        children: Optional[List[Block]] = None
        color: FullColor = FullColor.DEFAULT

    toggle: _NestedData = _NestedData()

UnsupportedBlock

Bases: Block

A placeholder for unsupported blocks in the API.

Source code in src/notional/blocks.py
130
131
132
133
134
135
136
class UnsupportedBlock(Block, type="unsupported"):
    """A placeholder for unsupported blocks in the API."""

    class _NestedData(GenericObject):
        pass

    unsupported: Optional[_NestedData] = None

Video

Bases: Block

A video block in Notion.

Source code in src/notional/blocks.py
595
596
597
598
class Video(Block, type="video"):
    """A video block in Notion."""

    video: FileObject = None

WithChildrenMixin

Mixin for blocks that support children blocks.

Source code in src/notional/blocks.py
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
class WithChildrenMixin:
    """Mixin for blocks that support children blocks."""

    @property
    def __children__(self):
        """Provide short-hand access to the children in this block."""

        return self("children")

    def __iadd__(self, block):
        """Append the given block to the children of this parent in place."""
        self.append(block)
        return self

    def append(self, block):
        """Append the given block to the children of this parent."""

        if block is None:
            raise ValueError("block cannot be None")

        nested = self()

        if nested.children is None:
            nested.children = []

        nested.children.append(block)

        self.has_children = True

__children__ property

Provide short-hand access to the children in this block.

__iadd__(block)

Append the given block to the children of this parent in place.

Source code in src/notional/blocks.py
187
188
189
190
def __iadd__(self, block):
    """Append the given block to the children of this parent in place."""
    self.append(block)
    return self

append(block)

Append the given block to the children of this parent.

Source code in src/notional/blocks.py
192
193
194
195
196
197
198
199
200
201
202
203
204
205
def append(self, block):
    """Append the given block to the children of this parent."""

    if block is None:
        raise ValueError("block cannot be None")

    nested = self()

    if nested.children is None:
        nested.children = []

    nested.children.append(block)

    self.has_children = True