Skip to content

Commit ec6ee77

Browse files
Add tree API
1 parent 9f9bd61 commit ec6ee77

File tree

5 files changed

+121
-3
lines changed

5 files changed

+121
-3
lines changed

mindsdb_sdk/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
from mindsdb_sdk.connect import connect
2+
from mindsdb_sdk.tree import TreeNode

mindsdb_sdk/connectors/rest_api.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,15 @@ def model_predict(self, project, model, data, params=None, version=None):
128128
return pd.DataFrame(r.json())
129129

130130
@_try_relogin
131-
def objects_tree(self, item=''):
132-
r = self.session.get(self.url + f'/api/tree/{item}')
131+
def objects_tree(self, item='', with_schemas=False):
132+
params = {}
133+
if with_schemas:
134+
params['all_schemas'] = 'true'
135+
136+
r = self.session.get(self.url + f'/api/tree/{item}', params=params)
133137
_raise_for_status(r)
134138

135-
return pd.DataFrame(r.json())
139+
return r.json() # Return raw JSON instead of DataFrame for more flexible processing
136140

137141
@staticmethod
138142
def read_file_as_bytes(file_path: str):

mindsdb_sdk/databases.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from mindsdb_sql.parser.ast import DropDatabase, Identifier
55

66
from mindsdb_sdk.utils.objects_collection import CollectionBase
7+
from .tree import TreeNode
78

89
from .query import Query
910
from .tables import Tables
@@ -52,6 +53,35 @@ def query(self, sql: str) -> Query:
5253
:return: Query object
5354
"""
5455
return Query(self.api, sql, database=self.name)
56+
57+
def tree(self, with_schemas: bool = False) -> List[TreeNode]:
58+
"""
59+
Get the tree structure of tables and schemas within this database.
60+
61+
This returns a list of table/schema nodes with their metadata including:
62+
- name: table/schema name
63+
- class: node type ('table', 'schema', 'job')
64+
- type: table type ('table', 'view', 'job', 'system view')
65+
- engine: table engine (if applicable)
66+
- deletable: whether the item can be deleted
67+
- schema: schema name (for tables)
68+
- children: nested tables (for schemas)
69+
70+
:param with_schemas: Whether to include schema information for data databases
71+
:return: List of TreeNode objects representing tables/schemas
72+
73+
Example:
74+
75+
>>> db = server.databases.get('my_postgres')
76+
>>> tree = db.tree(with_schemas=True)
77+
>>> for item in tree:
78+
... if item.class_ == 'schema':
79+
... print(f"Schema: {item.name} with {len(item.children)} tables")
80+
... else:
81+
... print(f"Table: {item.name}, Type: {item.type}")
82+
"""
83+
tree_data = self.api.objects_tree(self.name, with_schemas=with_schemas)
84+
return [TreeNode.from_dict(item) for item in tree_data]
5585

5686

5787
class Databases(CollectionBase):

mindsdb_sdk/server.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
from typing import List
2+
13
from .agents import Agents
24
from .databases import Databases
35
from .projects import Project, Projects
46
from .ml_engines import MLEngines
57
from .handlers import Handlers
68
from .skills import Skills
9+
from .tree import TreeNode
710

811

912
class Server(Project):
@@ -58,6 +61,29 @@ def status(self) -> dict:
5861
:return: server status info
5962
"""
6063
return self.api.status()
64+
65+
def tree(self) -> List[TreeNode]:
66+
"""
67+
Get the tree structure of databases on the server.
68+
69+
This returns a list of database nodes with their metadata including:
70+
- name: database name
71+
- class: node type ('db')
72+
- type: database type ('data', 'project', 'system')
73+
- engine: database engine
74+
- deletable: whether the database can be deleted
75+
- visible: whether the database is visible
76+
77+
:return: List of TreeNode objects representing databases
78+
79+
Example:
80+
81+
>>> tree = server.tree()
82+
>>> for db in tree:
83+
... print(f"Database: {db.name}, Type: {db.type}, Engine: {db.engine}")
84+
"""
85+
tree_data = self.api.objects_tree('')
86+
return [TreeNode.from_dict(item) for item in tree_data]
6187

6288
def __repr__(self):
6389
return f'{self.__class__.__name__}({self.api.url})'

mindsdb_sdk/tree.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from typing import List, Optional, Dict, Any
2+
from dataclasses import dataclass
3+
4+
5+
@dataclass
6+
class TreeNode:
7+
"""Represents any node in the MindsDB tree structure."""
8+
name: str
9+
class_: str # 'class' is a reserved keyword, so using 'class_'
10+
type: Optional[str] = None
11+
engine: Optional[str] = None
12+
deletable: bool = False
13+
visible: bool = True
14+
schema: Optional[str] = None # For table nodes that have schema information
15+
children: Optional[List['TreeNode']] = None
16+
17+
def __post_init__(self):
18+
if self.children is None:
19+
self.children = []
20+
21+
@classmethod
22+
def from_dict(cls, data: Dict[str, Any]) -> 'TreeNode':
23+
"""Create TreeNode from dictionary data."""
24+
children = []
25+
if 'children' in data and data['children']:
26+
children = [cls.from_dict(child) for child in data['children']]
27+
28+
return cls(
29+
name=data['name'],
30+
class_=data.get('class', ''),
31+
type=data.get('type'),
32+
engine=data.get('engine'),
33+
deletable=data.get('deletable', False),
34+
visible=data.get('visible', True),
35+
schema=data.get('schema'), # Include schema if present
36+
children=children
37+
)
38+
39+
def to_dict(self) -> Dict[str, Any]:
40+
"""Convert TreeNode to dictionary."""
41+
result = {
42+
'name': self.name,
43+
'class': self.class_,
44+
'deletable': self.deletable,
45+
'visible': self.visible
46+
}
47+
48+
if self.type is not None:
49+
result['type'] = self.type
50+
if self.engine is not None:
51+
result['engine'] = self.engine
52+
if self.schema is not None:
53+
result['schema'] = self.schema
54+
if self.children:
55+
result['children'] = [child.to_dict() for child in self.children]
56+
57+
return result

0 commit comments

Comments
 (0)