Skip to content

Commit

Permalink
improved validation of annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
ljeub-pometry committed Nov 19, 2024
1 parent d1cd67b commit 6a35a71
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 16 deletions.
6 changes: 4 additions & 2 deletions python/python/raphtory/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from typing import *
from raphtory import *
from raphtory.algorithms import *
from raphtory.vectors import *
from raphtory.node_state import *
from raphtory.graphql import *
from raphtory.typing import *
from datetime import datetime
Expand Down Expand Up @@ -2451,7 +2453,7 @@ class MutableNode(Node):
properties (PropInput): A dictionary of properties to be added to the node. Each key is a string representing the property name, and each value is of type Prop representing the property value.
"""

def add_updates(self, t: TimeInput, properties: PropInput = None) -> Result:
def add_updates(self, t: TimeInput, properties: PropInput = None):
"""
Add updates to a node in the graph at a specified time.
This function allows for the addition of property updates to a node within the graph. The updates are time-stamped, meaning they are applied at the specified time.
Expand Down Expand Up @@ -2719,7 +2721,7 @@ class Node(object):
List[int]: A list of unix timestamps of the event history of node.
"""

def history_date_time(self) -> List[Datetime]:
def history_date_time(self):
"""
Returns the history of a node, including node additions and changes made to node.
Expand Down
2 changes: 2 additions & 0 deletions python/python/raphtory/algorithms/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from typing import *
from raphtory import *
from raphtory.algorithms import *
from raphtory.vectors import *
from raphtory.node_state import *
from raphtory.graphql import *
from raphtory.typing import *
from datetime import datetime
Expand Down
2 changes: 2 additions & 0 deletions python/python/raphtory/graph_gen/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from typing import *
from raphtory import *
from raphtory.algorithms import *
from raphtory.vectors import *
from raphtory.node_state import *
from raphtory.graphql import *
from raphtory.typing import *
from datetime import datetime
Expand Down
2 changes: 2 additions & 0 deletions python/python/raphtory/graph_loader/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from typing import *
from raphtory import *
from raphtory.algorithms import *
from raphtory.vectors import *
from raphtory.node_state import *
from raphtory.graphql import *
from raphtory.typing import *
from datetime import datetime
Expand Down
2 changes: 2 additions & 0 deletions python/python/raphtory/graphql/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from typing import *
from raphtory import *
from raphtory.algorithms import *
from raphtory.vectors import *
from raphtory.node_state import *
from raphtory.graphql import *
from raphtory.typing import *
from datetime import datetime
Expand Down
2 changes: 2 additions & 0 deletions python/python/raphtory/node_state/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from typing import *
from raphtory import *
from raphtory.algorithms import *
from raphtory.vectors import *
from raphtory.node_state import *
from raphtory.graphql import *
from raphtory.typing import *
from datetime import datetime
Expand Down
2 changes: 2 additions & 0 deletions python/python/raphtory/vectors/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from typing import *
from raphtory import *
from raphtory.algorithms import *
from raphtory.vectors import *
from raphtory.node_state import *
from raphtory.graphql import *
from raphtory.typing import *
from datetime import datetime
Expand Down
51 changes: 37 additions & 14 deletions python/scripts/gen-stubs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3

import ast
import inspect
import logging
import textwrap
Expand All @@ -14,13 +14,9 @@
MethodDescriptorType,
ModuleType,
)
import builtins
from typing import *
from raphtory import *
from raphtory.graphql import *
from raphtory.typing import *
from docstring_parser import parse, DocstringStyle, DocstringParam, ParseError
from datetime import datetime
from pandas import DataFrame

logger = logging.getLogger(__name__)
fn_logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -48,13 +44,19 @@
imports = """
from typing import *
from raphtory import *
from raphtory.algorithms import *
from raphtory.vectors import *
from raphtory.node_state import *
from raphtory.graphql import *
from raphtory.typing import *
from datetime import datetime
from pandas import DataFrame
"""

# imports for type checking
global_ns = {}
exec(imports, global_ns)


def format_type(obj) -> str:
if isinstance(obj, type):
Expand All @@ -69,6 +71,18 @@ def format_type(obj) -> str:
return repr(obj)


class AnnotationError(Exception):
pass


def validate_annotation(annotation: str):
parsed = ast.parse(f"_: {annotation}")
for node in ast.walk(parsed.body[0].annotation):
if isinstance(node, ast.Name):
if node.id not in global_ns and node.id not in builtins.__dict__:
raise AnnotationError(f"Unknown type {node.id}")


def format_param(param: inspect.Parameter) -> str:
if param.kind == param.VAR_KEYWORD:
name = f"**{param.name}"
Expand Down Expand Up @@ -214,20 +228,24 @@ def extract_param_annotation(param: DocstringParam) -> dict:
else:
type_val = param.type_name
try:
eval(type_val)
validate_annotation(type_val)
if param.is_optional:
type_val = f"Optional[{type_val}]"
res["annotation"] = type_val
except Exception as e:
raise ParseError(f"Invalid type name {type_val}: {e}")
fn_logger.error(
f"Invalid annotation {repr(type_val)} for parameter {param.arg_name}: {e}"
)

if param.is_optional:
type_val = f"Optional[{type_val}]"
res["annotation"] = type_val
if param.default is not None or param.is_optional:
if param.default is not None:
try:
eval(param.default)
validate_annotation(param.default)
res["default"] = param.default
except Exception as e:
raise ParseError(f"Invalid default value {param.default}: {e}")
res["default"] = param.default
fn_logger.error(
f"Invalid default value {repr(param.default)} for parameter {param.arg_name}: {e}"
)
return res


Expand All @@ -247,6 +265,11 @@ def extract_types(
}
if parse_result.returns is not None:
return_type = parse_result.returns.type_name
try:
validate_annotation(return_type)
except Exception as e:
fn_logger.error(f"Invalid return type {repr(return_type)}: {e}")
return_type = None
else:
return_type = None
return type_annotations, return_type
Expand Down

0 comments on commit 6a35a71

Please sign in to comment.