Skip to content

Commit

Permalink
refactor: enhance schema parsing and client methods for Notion integr…
Browse files Browse the repository at this point in the history
…ation

- Improved the `parse_schema` function to support both natural language and structured property definitions.
- Added a `dict` method to the `PropertyOption` class for better data representation.
- Enhanced the `create_entry` method in `NotionClient` to handle both dictionary and `EntryConfig` inputs.
- Introduced a new `get_database` method to retrieve database schema from Notion, improving API interaction capabilities.
  • Loading branch information
atxtechbro committed Dec 22, 2024
1 parent de1f451 commit 37becc4
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 32 deletions.
73 changes: 44 additions & 29 deletions notion_automation/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,42 +117,57 @@ def create_database(schema_path, entries_path=None, page_id=None):
sys.exit(1)

def parse_schema(schema_data):
"""Parses the schema data into properties."""
"""Parse schema data into properties."""
properties = {}

if isinstance(schema_data["properties"], list):
# Check if it's natural language descriptions
if all(isinstance(p, str) for p in schema_data["properties"]):
properties = parse_natural_language_properties(schema_data["properties"])
else:
# List of property dicts
for prop in schema_data["properties"]:
name = prop.get("name")
property_type = prop.get("type")
if not name or not property_type:
raise ValueError(f"Property definition is missing 'name' or 'type': {prop}")
options = prop.get("options", [])
property_options = [
# Natural language or list format
for prop in schema_data["properties"]:
if isinstance(prop, str):
# Natural language format
name, desc = prop.split(":", 1)
name = name.strip()
desc = desc.strip()

if "date" in desc.lower():
prop_type = "date"
elif any(word in desc.lower() for word in ["category", "type", "status"]):
prop_type = "select"
# Extract options from parentheses
import re
options_match = re.search(r'\((.*?)\)', desc)
if options_match:
options = [
PropertyOption(name=opt.strip())
for opt in options_match.group(1).split(",")
]
else:
options = None
else:
prop_type = "rich_text"
options = None

properties[name] = PropertyConfig(
property_type=prop_type,
options=options
)
else:
# List of property objects format
name = prop["name"]
prop_type = prop["type"]
options = [
PropertyOption(name=opt) if isinstance(opt, str) else PropertyOption(**opt)
for opt in options
for opt in prop.get("options", [])
]
properties[name] = PropertyConfig(
property_type=property_type, options=property_options
property_type=prop_type,
options=options
)
elif isinstance(schema_data["properties"], dict):
# Existing logic for dict format
for name, prop in schema_data["properties"].items():
if 'property_type' not in prop:
raise ValueError(f"Property '{name}' is missing 'property_type'")
property_type = prop["property_type"]
options_data = prop.get("options", [])
options = [PropertyOption(**option) for option in options_data]
properties[name] = PropertyConfig(
property_type=property_type, options=options
)
else:
raise ValueError("Invalid schema format for 'properties' field.")

# Dictionary format
for name, config in schema_data["properties"].items():
properties[name] = PropertyConfig(**config)

return properties

def parse_natural_language_properties(property_descriptions):
Expand Down
7 changes: 7 additions & 0 deletions notion_automation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
class PropertyOption:
name: str
color: Optional[str] = None

def dict(self):
"""Convert to dictionary representation."""
return {
"name": self.name,
"color": self.color
}

@dataclass
class PropertyConfig:
Expand Down
34 changes: 31 additions & 3 deletions notion_automation/notion_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,25 @@ def create_database(self, parent_id, schema):
if not response.ok:
logger.error(f"Notion API error: {response.status_code}")
logger.error(f"Response body: {response.text}")
raise Exception(f"Failed to create database: {response.text}")

response.raise_for_status()
return response.json()["id"]

def create_entry(self, database_id, entry):
"""Create a new entry in the database.
Args:
database_id (str): ID of the target database
entry (dict or EntryConfig): Entry data
"""
url = f"{self.base_url}/pages"

# Handle both dict and EntryConfig inputs
properties = entry.properties if hasattr(entry, 'properties') else entry

payload = {
"parent": {"database_id": database_id},
"properties": self._format_entry_properties(entry.properties)
"properties": self._format_entry_properties(properties)
}

response = requests.post(url, headers=self.headers, json=payload)
Expand Down Expand Up @@ -125,4 +134,23 @@ def _format_entry_property(self, prop):
elif prop.type == "date":
return {"date": {"start": prop.value}}
else:
raise ValueError(f"Unsupported property type: {prop.type}")
raise ValueError(f"Unsupported property type: {prop.type}")

def get_database(self, database_id):
"""Retrieve database schema from Notion.
Args:
database_id (str): ID of the database to retrieve
Returns:
dict: Database schema information
"""
url = f"{self.base_url}/databases/{database_id}"
response = requests.get(url, headers=self.headers)

if not response.ok:
logger.error(f"Notion API error: {response.status_code}")
logger.error(f"Response body: {response.text}")
response.raise_for_status()

return response.json()

0 comments on commit 37becc4

Please sign in to comment.