Skip to content

Commit

Permalink
#27 relation type Property
Browse files Browse the repository at this point in the history
  • Loading branch information
lastorel committed Jul 28, 2022
1 parent 88a50ca commit 7133f27
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 11 deletions.
14 changes: 9 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

## v1.3.0

- \#27: Switched from `2022-02-22` to `2022-06-28` version of Notion API
- [#27](https://github.com/lastorel/pytion/issues/27): Switched from `2022-02-22` to `2022-06-28` version of Notion API
- `Request()` (internal) method argument added
- \#27: Fix of parent object hierarchy
- \#27: `models.Block` now has non-empty `parent` attr
- [#27](https://github.com/lastorel/pytion/issues/27): Fix of parent object hierarchy
- [#27](https://github.com/lastorel/pytion/issues/27): `models.Block` now has non-empty `parent` attr
- `models.Database`: `is_inline` attr added
- `Notion()`: new optional arg `version` added to customize API interaction
- \#27: You must retrieve Page properties manually. `.get_page_properties` method added
- [#27](https://github.com/lastorel/pytion/issues/27): You must retrieve Page properties manually. `.get_page_properties` method added
- [#27](https://github.com/lastorel/pytion/issues/27): add support of `relation` type `Property`
- [#27](https://github.com/lastorel/pytion/issues/27): updates for `relation` type `PropertyValue`
- [#16](https://github.com/lastorel/pytion/issues/17): tests of Property model

### Breaking changes

- `Request()` method now looks for positional argument `api` for getting version (internal method)
- Page has title=`unknown` until you retrieve its properties
- Page has title=`unknown` until you retrieve its properties
- `PropertyValue` with `relation` type now represents by list of `LinkTo` object instead of list of IDs
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Current Notion API version = **"2022-06-28"**

_*does not use notion-sdk-py client_

See [Change Log](./CHANGELOG.md)

# Contents

1. [Quick Start](#quick-start)
Expand Down Expand Up @@ -209,10 +211,10 @@ There are classes **based on API** structures:
- You can retrieve more data about a User by his ID using `.get()`
- `Property` based on [Property object](https://developers.notion.com/reference/property-object)
- You can create object `Property.create(...)` while creating or editing database: `.db_create()` or `.db_update()`
- `formula`, `relation`, `rollup` type properties configuration is not supported
- `formula`, `rollup` type properties configuration is not supported
- `PropertyValue` based on [Property values](https://developers.notion.com/reference/property-value-object)
- You can create object `PropertyValue.create(...)` to set or edit page properties by `.page_create()` or `.page_update()`
- `files`, `relation`, `formula`, `rollup` type properties are not editable
- `files`, `formula`, `rollup` type properties are not editable

There are also useful **internal** classes:

Expand Down Expand Up @@ -286,6 +288,13 @@ Extension attributes are listed below in support matrix:

> API converts **toggle heading** Block to simple heading Block.
### Supported Property types

| Property type | Property type | Property Schema | Property Values | Property Item | Config attrs |
| --- | --- | --- | --- | --- | --- |
| `title` | rw | rw | rw | + | |
| in_progress... | rw | rw | rw | + | |

### Block creating examples

Create `paragraph` block object and add it to Notion:
Expand Down
38 changes: 34 additions & 4 deletions pytion/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,23 @@ def format_iso_time(cls, time: str) -> Optional[datetime]:


class Property(object):
def __init__(self, data: Dict[str, str]):
def __init__(self, data: Dict[str, Any]):
self.to_delete = True if data.get("type", False) is None else False
self.id: str = data.get("id")
self.type: str = data.get("type", "")
self.name: str = data.get("name")
self.raw = data
self.subtype = None

if self.type == "relation":
if isinstance(data[self.type], dict):
self.subtype = data[self.type].get("type")
self.relation = LinkTo.create(database_id=data[self.type].get("database_id"))
if self.subtype == "single_property":
pass
elif self.subtype == "dual_property":
self.relation_property_id = data[self.type][self.subtype].get("synced_property_id")
self.relation_property_name = data[self.type][self.subtype].get("synced_property_name")

def __str__(self):
return self.name if self.name else self.type
Expand All @@ -237,7 +248,11 @@ def get(self) -> Optional[Dict[str, Dict]]:
data["name"] = self.name
# property retyping while patch
if self.type:
data[self.type] = {}
# create relation type property with configuration
if self.type == "relation":
data[self.type] = {self.subtype: {}, "database_id": self.relation.id}
else:
data[self.type] = {}
return data

@classmethod
Expand All @@ -248,7 +263,15 @@ def create(cls, type_: Optional[str] = "", **kwargs):
+ addons:
set type_ = `None` to delete this Property
set param `name` to rename this Property
+ relation type:
set param `single_property` with `database_id` value OR
set param `dual_property` with `database_id` value
Property.create(type_="relation", dual_property="v111c132c12c1242341c41c")
"""
if type_ == "relation":
subtype = next(kwarg for kwarg in kwargs if kwarg in ("single_property", "dual_property"))
kwargs["relation"] = {"type": subtype, subtype: {}, "database_id": kwargs[subtype]}
return cls({"type": type_, **kwargs})


Expand Down Expand Up @@ -331,7 +354,10 @@ def __init__(self, data: Dict, name: str, **kwargs):
self.value = [user if isinstance(user, User) else User(**user) for user in data[self.type]]

if self.type == "relation":
self.value: List[str] = [item.get("id") for item in data["relation"]]
self.value: List[LinkTo] = [
LinkTo.create(page_id=item.get("id")) if not isinstance(item, LinkTo) else item
for item in data[self.type]
]

if self.type == "rollup":
rollup_type = data["rollup"]["type"]
Expand Down Expand Up @@ -420,8 +446,12 @@ def get(self):
if self.type == "people":
return {self.type: [user.get() for user in self.value]}

# relation type
if self.type == "relation":
return {self.type: [{"id": lt.id} for lt in self.value]}

# unsupported types:
if self.type in ["files", "relation"]:
if self.type in ["files"]:
return {self.type: []}
if self.type in ["created_time", "last_edited_by", "last_edited_time", "created_by"]:
return None
Expand Down
45 changes: 45 additions & 0 deletions tests/test_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from pytion.models import *


class TestProperty:
def test_create(self):
p = Property.create(type_="multi_select", name="multiselected")
p.get()
assert p.id is None
assert p.type == "multi_select"
assert p.to_delete is False

def test_create__to_rename(self):
p = Property.create(name="renamed")
p.get()
assert p.id is None
assert p.type == ""
assert p.name == "renamed"
assert p.to_delete is False

def test_create__to_delete(self):
p = Property.create(type_=None)
p.get()
assert p.id is None
assert p.type is None
assert p.to_delete is True

def test_create__relation_single(self):
p = Property.create("relation", single_property="878d628488d94894ab14f9b872cd6870")
p.get()
assert p.id is None
assert p.type == "relation"
assert p.to_delete is False
assert isinstance(p.relation, LinkTo)
assert p.relation.uri == "databases"
assert p.subtype == "single_property"

def test_create__relation_dual(self):
p = Property.create("relation", dual_property="878d628488d94894ab14f9b872cd6870")
p.get()
assert p.id is None
assert p.type == "relation"
assert p.to_delete is False
assert isinstance(p.relation, LinkTo)
assert p.relation.uri == "databases"
assert p.subtype == "dual_property"

0 comments on commit 7133f27

Please sign in to comment.