MindsDB 25.3.4.0__py3-none-any.whl → 25.3.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of MindsDB might be problematic. Click here for more details.

mindsdb/__about__.py CHANGED
@@ -1,10 +1,10 @@
1
1
  __title__ = 'MindsDB'
2
2
  __package_name__ = 'mindsdb'
3
- __version__ = '25.3.4.0'
3
+ __version__ = '25.3.4.1'
4
4
  __description__ = "MindsDB's AI SQL Server enables developers to build AI tools that need access to real-time data to perform their tasks"
5
5
  __email__ = "jorge@mindsdb.com"
6
6
  __author__ = 'MindsDB Inc'
7
7
  __github__ = 'https://github.com/mindsdb/mindsdb'
8
8
  __pypi__ = 'https://pypi.org/project/mindsdb/'
9
- __license__ = 'SSPL v1'
9
+ __license__ = 'Elastic License 2.0'
10
10
  __copyright__ = 'Copyright(c) 2018 MindsDB, Inc'
@@ -0,0 +1,164 @@
1
+ from typing import List
2
+
3
+ import requests
4
+
5
+
6
+ class ConfluenceAPIClient:
7
+ def __init__(self, url: str, username: str, password: str):
8
+ self.url = url
9
+ self.username = username
10
+ self.password = password
11
+ self.session = requests.Session()
12
+ self.session.auth = (self.username, self.password)
13
+ self.session.headers.update({"Accept": "application/json"})
14
+
15
+ def get_spaces(
16
+ self,
17
+ ids: List[int] = None,
18
+ keys: List[str] = None,
19
+ space_type: str = None,
20
+ status: str = None,
21
+ sort_condition: str = None,
22
+ limit: int = None,
23
+ ):
24
+ url = f"{self.url}/wiki/api/v2/spaces"
25
+ params = {
26
+ "description-format": "view",
27
+ }
28
+ if ids:
29
+ params["ids"] = ids
30
+ if keys:
31
+ params["keys"] = keys
32
+ if space_type:
33
+ params["type"] = space_type
34
+ if status:
35
+ params["status"] = status
36
+ if sort_condition:
37
+ params["sort"] = sort_condition
38
+ if limit:
39
+ params["limit"] = limit
40
+
41
+ return self._paginate(url, params)
42
+
43
+ def get_pages(
44
+ self,
45
+ page_ids: List[int] = None,
46
+ space_ids: List[int] = None,
47
+ statuses: List[str] = None,
48
+ title: str = None,
49
+ sort_condition: str = None,
50
+ limit: int = None,
51
+ ) -> List[dict]:
52
+ url = f"{self.url}/wiki/api/v2/pages"
53
+ params = {
54
+ "body-format": "storage",
55
+ }
56
+ if page_ids:
57
+ params["id"] = page_ids
58
+ if space_ids:
59
+ params["space-id"] = space_ids
60
+ if statuses:
61
+ params["status"] = statuses
62
+ if title:
63
+ params["title"] = title
64
+ if sort_condition:
65
+ params["sort"] = sort_condition
66
+ if limit:
67
+ params["limit"] = limit
68
+
69
+ return self._paginate(url, params)
70
+
71
+ def get_blogposts(
72
+ self,
73
+ post_ids: List[int] = None,
74
+ space_ids: List[str] = None,
75
+ statuses: List[str] = None,
76
+ title: str = None,
77
+ sort_condition: str = None,
78
+ limit: int = None,
79
+ ) -> List[dict]:
80
+ url = f"{self.url}/wiki/api/v2/blogposts"
81
+ params = {
82
+ "body-format": "storage",
83
+ }
84
+ if post_ids:
85
+ params["id"] = post_ids
86
+ if space_ids:
87
+ params["space-id"] = space_ids
88
+ if statuses:
89
+ params["status"] = statuses
90
+ if title:
91
+ params["title"] = title
92
+ if sort_condition:
93
+ params["sort"] = sort_condition
94
+ if limit:
95
+ params["limit"] = limit
96
+
97
+ return self._paginate(url, params)
98
+
99
+ def get_whiteboard_by_id(self, whiteboard_id: int) -> dict:
100
+ url = f"{self.url}/wiki/api/v2/whiteboards/{whiteboard_id}"
101
+
102
+ return self._make_request("GET", url)
103
+
104
+ def get_database_by_id(self, database_id: int) -> dict:
105
+ url = f"{self.url}/wiki/api/v2/databases/{database_id}"
106
+
107
+ return self._make_request("GET", url)
108
+
109
+ def get_tasks(
110
+ self,
111
+ task_ids: List[int] = None,
112
+ space_ids: List[str] = None,
113
+ page_ids: List[str] = None,
114
+ blogpost_ids: List[str] = None,
115
+ created_by_ids: List[str] = None,
116
+ assigned_to_ids: List[str] = None,
117
+ completed_by_ids: List[str] = None,
118
+ status: str = None,
119
+ limit: int = None,
120
+ ) -> List[dict]:
121
+ url = f"{self.url}/wiki/api/v2/tasks"
122
+ params = {
123
+ "body-format": "storage",
124
+ }
125
+ if task_ids:
126
+ params["id"] = task_ids
127
+ if space_ids:
128
+ params["space-id"] = space_ids
129
+ if page_ids:
130
+ params["page-id"] = page_ids
131
+ if blogpost_ids:
132
+ params["blogpost-id"] = blogpost_ids
133
+ if created_by_ids:
134
+ params["created-by"] = created_by_ids
135
+ if assigned_to_ids:
136
+ params["assigned-to"] = assigned_to_ids
137
+ if completed_by_ids:
138
+ params["completed-by"] = completed_by_ids
139
+ if status:
140
+ params["status"] = status
141
+ if limit:
142
+ params["limit"] = limit
143
+
144
+ return self._paginate(url, params)
145
+
146
+ def _paginate(self, url: str, params: dict = None) -> List[dict]:
147
+ results = []
148
+ response = self._make_request("GET", url, params)
149
+ results.extend(response["results"])
150
+
151
+ while response["_links"].get("next"):
152
+ params["cursor"] = response["_links"].get("next")
153
+ response = self._make_request("GET", url, params)
154
+ results.extend(response["results"])
155
+
156
+ return results
157
+
158
+ def _make_request(self, method: str, url: str, params: dict = None, data: dict = None) -> dict:
159
+ response = self.session.request(method, url, params=params, json=data)
160
+
161
+ if response.status_code != 200:
162
+ raise Exception(f"Request failed with status code {response.status_code}: {response.text}")
163
+
164
+ return response.json()
@@ -1,83 +1,92 @@
1
- from typing import Optional, Union
1
+ from typing import Any, Dict
2
2
 
3
- import requests
4
- from atlassian import Confluence
5
- from mindsdb_sql_parser import parse_sql
6
-
7
- from mindsdb.integrations.handlers.confluence_handler.confluence_table import (
3
+ from mindsdb.integrations.handlers.confluence_handler.confluence_api_client import ConfluenceAPIClient
4
+ from mindsdb.integrations.handlers.confluence_handler.confluence_tables import (
5
+ ConfluenceBlogPostsTable,
6
+ ConfluenceDatabasesTable,
8
7
  ConfluencePagesTable,
8
+ ConfluenceSpacesTable,
9
+ ConfluenceTasksTable,
10
+ ConfluenceWhiteboardsTable,
9
11
  )
10
12
  from mindsdb.integrations.libs.api_handler import APIHandler
11
13
  from mindsdb.integrations.libs.response import (
12
14
  HandlerStatusResponse as StatusResponse,
13
15
  )
14
- from mindsdb_sql_parser import parse_sql
15
16
  from mindsdb.utilities import log
16
17
 
17
- from atlassian import Confluence
18
- from typing import Optional
19
- import requests
20
18
 
21
19
  logger = log.getLogger(__name__)
22
20
 
21
+
23
22
  class ConfluenceHandler(APIHandler):
24
- """Confluence handler implementation"""
25
-
26
- def __init__(self, name=None, **kwargs):
27
- """Initialize the Confluence handler.
28
- Parameters
29
- ----------
30
- name : str
31
- name of a handler instance
32
- """
33
- super().__init__(name)
23
+ """
24
+ This handler handles the connection and execution of SQL statements on Confluence.
25
+ """
26
+
27
+ name = "confluence"
34
28
 
35
- connection_data = kwargs.get("connection_data", {})
29
+ def __init__(self, name: str, connection_data: Dict, **kwargs: Any) -> None:
30
+ """
31
+ Initializes the handler.
36
32
 
37
- self.parser = parse_sql
38
- self.dialect = 'confluence'
33
+ Args:
34
+ name (str): The name of the handler instance.
35
+ connection_data (Dict): The connection data required to connect to the Confluence API.
36
+ kwargs: Arbitrary keyword arguments.
37
+ """
38
+ super().__init__(name)
39
39
  self.connection_data = connection_data
40
40
  self.kwargs = kwargs
41
+
41
42
  self.connection = None
42
43
  self.is_connected = False
44
+ self.thread_safe = True
43
45
 
44
- confluence_pages_data = ConfluencePagesTable(self)
45
- self._register_table("pages", confluence_pages_data)
46
+ self._register_table("spaces", ConfluenceSpacesTable(self))
47
+ self._register_table("pages", ConfluencePagesTable(self))
48
+ self._register_table("blogposts", ConfluenceBlogPostsTable(self))
49
+ self._register_table("whiteboards", ConfluenceWhiteboardsTable(self))
50
+ self._register_table("databases", ConfluenceDatabasesTable(self))
51
+ self._register_table("tasks", ConfluenceTasksTable(self))
46
52
 
47
- def connect(self):
48
- """Set up the connection required by the handler.
49
- Returns
50
- -------
51
- StatusResponse
52
- connection object
53
+ def connect(self) -> ConfluenceAPIClient:
54
+ """
55
+ Establishes a connection to the Confluence API.
56
+
57
+ Raises:
58
+ ValueError: If the required connection parameters are not provided.
59
+
60
+ Returns:
61
+ atlassian.confluence.Confluence: A connection object to the Confluence API.
53
62
  """
54
63
  if self.is_connected is True:
55
64
  return self.connection
56
-
57
- if not all(key in self.connection_data and self.connection_data.get(key) for key in ['url', 'username', 'password']):
58
- raise ValueError('Required parameters (url, username, password) must be provided and should not be empty.')
59
-
60
- conf = Confluence(
61
- url=self.connection_data.get('url'),
65
+
66
+ if not all(key in self.connection_data and self.connection_data.get(key) for key in ['api_base', 'username', 'password']):
67
+ raise ValueError('Required parameters (api_base, username, password) must be provided and should not be empty.')
68
+
69
+ self.connection = ConfluenceAPIClient(
70
+ url=self.connection_data.get('api_base'),
62
71
  username=self.connection_data.get('username'),
63
72
  password=self.connection_data.get('password'),
64
73
  )
65
- self.connection = conf
74
+
66
75
  self.is_connected = True
67
76
  return self.connection
68
77
 
69
78
  def check_connection(self) -> StatusResponse:
70
- """Check connection to the handler.
71
- Returns
72
- -------
73
- StatusResponse
74
- Status confirmation
79
+ """
80
+ Checks the status of the connection to the Confluence API.
81
+
82
+ Returns:
83
+ StatusResponse: An object containing the success status and an error message if an error occurs.
75
84
  """
76
85
  response = StatusResponse(False)
77
- need_to_close = self.is_connected is False
78
86
 
79
87
  try:
80
- self.connect()
88
+ connection = self.connect()
89
+ connection.get_spaces(limit=1)
81
90
  response.success = True
82
91
  except Exception as e:
83
92
  logger.error(f"Error connecting to Confluence API: {e}!")
@@ -86,17 +95,3 @@ class ConfluenceHandler(APIHandler):
86
95
  self.is_connected = response.success
87
96
 
88
97
  return response
89
-
90
- def native_query(self, query: str) -> StatusResponse:
91
- """Receive and process a raw query.
92
- Parameters
93
- ----------
94
- query : str
95
- query in a native format
96
- Returns
97
- -------
98
- StatusResponse
99
- Request status
100
- """
101
- ast = parse_sql(query)
102
- return self.query(ast)