Coverage for mindsdb / integrations / handlers / eventbrite_handler / eventbrite_tables.py: 0%
241 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
1import pandas as pd
2import collections
3from mindsdb.integrations.libs.api_handler import APITable
4from mindsdb_sql_parser import ast
5from mindsdb.integrations.utilities.sql_utils import extract_comparison_conditions
6from mindsdb.integrations.utilities.handlers.query_utilities import (
7 SELECTQueryParser,
8 SELECTQueryExecutor,
9)
12def flatten(d, parent_key="", sep="_"):
13 items = []
14 for k, v in d.items():
15 new_key = parent_key + sep + k if parent_key else k
16 if isinstance(v, collections.MutableMapping):
17 items.extend(flatten(v, new_key, sep=sep).items())
18 else:
19 items.append((new_key, v))
20 return dict(items)
23class EventbriteUserTable(APITable):
24 def select(self, query: ast.Select) -> pd.DataFrame:
25 self.handler.connect()
27 if query.limit is not None:
28 raise NotImplementedError("Limit is not supported for user info table")
30 user_info = self.handler.api.get_current_user()
32 # Normalize email field
33 if "emails" in user_info and isinstance(user_info["emails"], list):
34 user_info["email"] = (
35 user_info["emails"][0]["email"] if user_info["emails"] else None
36 )
37 user_info["email_verified"] = (
38 user_info["emails"][0]["verified"] if user_info["emails"] else None
39 )
40 user_info["email_primary"] = (
41 user_info["emails"][0]["primary"] if user_info["emails"] else None
42 )
43 del user_info["emails"]
44 else:
45 user_info["email"] = None
46 user_info["email_verified"] = None
47 user_info["email_primary"] = None
49 data = pd.DataFrame([user_info])
51 # Select columns based on query
52 columns = self.get_columns()
53 selected_columns = [
54 target.parts[-1]
55 for target in query.targets
56 if isinstance(target, ast.Identifier)
57 ]
58 if selected_columns:
59 columns = [col for col in columns if col in selected_columns]
60 data = data[columns]
62 return data
64 def get_columns(self):
65 return [
66 "email",
67 "email_verified",
68 "email_primary",
69 "id",
70 "name",
71 "first_name",
72 "last_name",
73 "is_public",
74 "image_id",
75 ]
78class EventbriteOrganizationTable(APITable):
79 def select(self, query: ast.Select) -> pd.DataFrame:
80 self.handler.connect()
82 organization_info = self.handler.api.get_user_organizations()
84 # Normalize organization data
85 organizations = organization_info.get("organizations", [])
86 result = pd.DataFrame(organizations)
88 # filter targets
89 columns = []
90 for target in query.targets:
91 if isinstance(target, ast.Star):
92 columns = []
93 break
94 elif isinstance(target, ast.Identifier):
95 columns.append(target.parts[-1])
96 else:
97 raise NotImplementedError
99 if len(columns) == 0:
100 columns = self.get_columns()
102 # columns to lower case
103 columns = [name.lower() for name in columns]
105 if len(result) == 0:
106 result = pd.DataFrame([], columns=columns)
107 else:
108 # add absent columns
109 for col in set(columns) & set(result.columns) ^ set(columns):
110 result[col] = None
112 # filter by columns
113 result = result[columns]
115 return result
117 def get_columns(self):
118 return [
119 "_type",
120 "name",
121 "vertical",
122 "parent_id",
123 "locale",
124 "created",
125 "image_id",
126 "id",
127 ]
130class EventbriteCategoryTable(APITable):
131 def select(self, query: ast.Select) -> pd.DataFrame:
132 self.handler.connect()
134 category_info = self.handler.api.list_categories()
135 categories = category_info.get("categories", [])
136 result = pd.DataFrame(categories)
138 select_statement_parser = SELECTQueryParser(
139 query, "categoryInfoTable", self.get_columns()
140 )
142 (
143 selected_columns,
144 where_conditions,
145 order_by_conditions,
146 result_limit,
147 ) = select_statement_parser.parse_query()
149 total_results = result_limit if result_limit else 100
151 # filter targets
152 columns = []
153 for target in query.targets:
154 if isinstance(target, ast.Star):
155 columns = []
156 break
157 elif isinstance(target, ast.Identifier):
158 columns.append(target.parts[-1])
159 else:
160 raise NotImplementedError
162 if len(columns) == 0:
163 columns = self.get_columns()
165 # columns to lower case
166 columns = [name.lower() for name in columns]
168 if len(result) == 0:
169 result = pd.DataFrame([], columns=columns)
170 else:
171 # add absent columns
172 for col in set(columns) & set(result.columns) ^ set(columns):
173 result[col] = None
175 # filter by columns
176 result = result[columns]
178 select_statement_executor = SELECTQueryExecutor(
179 result, selected_columns, where_conditions, order_by_conditions
180 )
182 result = select_statement_executor.execute_query()
184 return result.head(total_results)
186 def get_columns(self):
187 return [
188 "resource_uri",
189 "id",
190 "name",
191 "name_localized",
192 "short_name",
193 "short_name_localized",
194 ]
197class EventbriteSubcategoryTable(APITable):
198 def select(self, query: ast.Select) -> pd.DataFrame:
199 self.handler.connect()
201 # Dummy function to simulate API call and response
202 category_info = self.handler.api.list_subcategories()
204 # Normalizing the category data
205 categories = category_info.get("subcategories", [])
206 result = pd.DataFrame(categories)
208 select_statement_parser = SELECTQueryParser(
209 query, "subcategoryInfoTable", self.get_columns()
210 )
212 (
213 selected_columns,
214 where_conditions,
215 order_by_conditions,
216 result_limit,
217 ) = select_statement_parser.parse_query()
219 total_results = result_limit if result_limit else 100
221 # Normalize nested fields
222 parent_category = result["parent_category"].apply(pd.Series)
223 parent_category.columns = [f"parent_{col}" for col in parent_category.columns]
224 result = pd.concat([result, parent_category], axis=1).drop(
225 "parent_category", axis=1
226 )
228 # filter targets
229 columns = []
230 for target in query.targets:
231 if isinstance(target, ast.Star):
232 columns = []
233 break
234 elif isinstance(target, ast.Identifier):
235 columns.append(target.parts[-1])
236 else:
237 raise NotImplementedError
239 if len(columns) == 0:
240 columns = self.get_columns()
242 # columns to lower case
243 columns = [name.lower() for name in columns]
245 if len(result) == 0:
246 result = pd.DataFrame([], columns=columns)
247 else:
248 # add absent columns
249 for col in set(columns) & set(result.columns) ^ set(columns):
250 result[col] = None
252 # filter by columns
253 result = result[columns]
255 select_statement_executor = SELECTQueryExecutor(
256 result, selected_columns, where_conditions, order_by_conditions
257 )
259 result = select_statement_executor.execute_query()
261 return result.head(total_results)
263 def get_columns(self):
264 return [
265 "resource_uri",
266 "id",
267 "name",
268 "name_localized",
269 "parent_category",
270 "parent_resource_uri",
271 "parent_id",
272 "parent_name",
273 "parent_name_localized",
274 "parent_short_name",
275 "parent_short_name_localized",
276 ]
279class EventbriteFormatTable(APITable):
280 def select(self, query: ast.Select) -> pd.DataFrame:
281 self.handler.connect()
283 # Simulate API call and get the response
284 format_info = self.handler.api.list_formats()
286 # Normalize format data
287 formats = format_info.get("formats", [])
288 result = pd.DataFrame(formats)
290 select_statement_parser = SELECTQueryParser(
291 query, "formatInfoTable", self.get_columns()
292 )
294 (
295 selected_columns,
296 where_conditions,
297 order_by_conditions,
298 result_limit,
299 ) = select_statement_parser.parse_query()
301 total_results = result_limit if result_limit else 100
303 # filter targets
304 columns = []
305 for target in query.targets:
306 if isinstance(target, ast.Star):
307 columns = []
308 break
309 elif isinstance(target, ast.Identifier):
310 columns.append(target.parts[-1])
311 else:
312 raise NotImplementedError
314 if len(columns) == 0:
315 columns = self.get_columns()
317 # columns to lower case
318 columns = [name.lower() for name in columns]
320 if len(result) == 0:
321 result = pd.DataFrame([], columns=columns)
322 else:
323 # add absent columns
324 for col in set(columns) & set(result.columns) ^ set(columns):
325 result[col] = None
327 # filter by columns
328 result = result[columns]
330 select_statement_executor = SELECTQueryExecutor(
331 result, selected_columns, where_conditions, order_by_conditions
332 )
334 result = select_statement_executor.execute_query()
336 return result.head(total_results)
338 def get_columns(self):
339 return [
340 "resource_uri",
341 "id",
342 "name",
343 "name_localized",
344 "short_name",
345 "short_name_localized",
346 ]
349class EventbriteEventDetailsTable(APITable):
350 def select(self, query: ast.Select) -> pd.DataFrame:
351 self.handler.connect()
353 conditions = extract_comparison_conditions(query.where)
354 allowed_keys = set(["event_id"])
356 params = {}
357 filters = []
358 for op, arg1, arg2 in conditions:
359 if op == "or":
360 raise NotImplementedError("OR is not supported")
361 elif op == "=" and arg1 in allowed_keys:
362 params[arg1] = arg2
363 elif op != "=":
364 raise NotImplementedError(f"Unknown op: {op}")
365 else:
366 filters.append([op, arg1, arg2])
368 if query.limit is not None:
369 params["max_results"] = query.limit.value
371 if "event_id" not in params:
372 # search not works without searchQuery, use 'London'
373 params["event_id"] = "717926867587"
375 event_details = self.handler.api.get_event(params["event_id"])
377 # Normalize event data
378 flat_event_details = flatten(event_details)
379 result = pd.DataFrame([flat_event_details])
381 for col in ["name", "description", "start", "end", "logo"]:
382 if col in result.columns:
383 result = pd.concat(
384 [result, result[col].apply(pd.Series).add_prefix(f"{col}_")],
385 axis=1,
386 )
387 result = result.drop([col], axis=1)
389 # filter targets
390 columns = []
391 for target in query.targets:
392 if isinstance(target, ast.Star):
393 columns = []
394 break
395 elif isinstance(target, ast.Identifier):
396 columns.append(target.parts[-1])
397 else:
398 raise NotImplementedError
400 if len(columns) == 0:
401 columns = self.get_columns()
403 # columns to lower case
404 columns = [name.lower() for name in columns]
406 if len(result) == 0:
407 result = pd.DataFrame([], columns=columns)
408 else:
409 # add absent columns
410 for col in set(columns) & set(result.columns) ^ set(columns):
411 result[col] = None
413 # filter by columns
414 result = result[columns]
415 return result
417 def get_columns(self):
418 return [
419 "name_text",
420 "name_html",
421 "description_text",
422 "description_html",
423 "url",
424 "start_timezone",
425 "start_local",
426 "start_utc",
427 "end_timezone",
428 "end_local",
429 "end_utc",
430 "organization_id",
431 "created",
432 "changed",
433 "published",
434 "capacity",
435 "capacity_is_custom",
436 "status",
437 "currency",
438 "listed",
439 "shareable",
440 "online_event",
441 "tx_time_limit",
442 "hide_start_date",
443 "hide_end_date",
444 "locale",
445 "is_locked",
446 "privacy_setting",
447 "is_series",
448 "is_series_parent",
449 "inventory_type",
450 "is_reserved_seating",
451 "show_pick_a_seat",
452 "show_seatmap_thumbnail",
453 "show_colors_in_seatmap_thumbnail",
454 "source",
455 "is_free",
456 "version",
457 "summary",
458 "facebook_event_id",
459 "logo_id",
460 "organizer_id",
461 "venue_id",
462 "category_id",
463 "subcategory_id",
464 "format_id",
465 "id",
466 "resource_uri",
467 "is_externally_ticketed",
468 "logo_crop_mask",
469 "logo_original",
470 "logo_id",
471 "logo_url",
472 "logo_aspect_ratio",
473 "logo_edge_color",
474 "logo_edge_color_set",
475 ]
478class EventbriteEventsTable(APITable):
479 def __init__(self, handler):
480 self.handler = handler
482 def select(self, query: ast.Select) -> pd.DataFrame:
483 self.handler.connect()
485 conditions = extract_comparison_conditions(query.where)
486 allowed_keys = set(["organization_id"])
488 params = {}
489 for op, arg1, arg2 in conditions:
490 if op == "=" and arg1 in allowed_keys:
491 params[arg1] = arg2
492 else:
493 raise NotImplementedError(
494 f"Unsupported operation or field: {op} {arg1}"
495 )
497 if "organization_id" not in params:
498 raise ValueError("Organization ID must be provided")
500 event_list = self.handler.api.list_events(params["organization_id"])
501 result = pd.DataFrame(event_list["events"])
503 # Normalize event data and split nested dictionaries into separate columns
504 result = pd.concat(
505 [
506 result.drop(["name", "description", "start", "end", "logo"], axis=1),
507 result["name"].apply(pd.Series).add_prefix("name_"),
508 result["description"].apply(pd.Series).add_prefix("description_"),
509 result["start"].apply(pd.Series).add_prefix("start_"),
510 result["end"].apply(pd.Series).add_prefix("end_"),
511 result["logo"].apply(pd.Series).add_prefix("logo_"),
512 ],
513 axis=1,
514 )
516 select_statement_parser = SELECTQueryParser(
517 query, "subcategoryInfoTable", self.get_columns()
518 )
520 (
521 selected_columns,
522 where_conditions,
523 order_by_conditions,
524 result_limit,
525 ) = select_statement_parser.parse_query()
527 total_results = result_limit if result_limit else 100
529 # filter targets
530 columns = []
531 for target in query.targets:
532 if isinstance(target, ast.Star):
533 columns = []
534 break
535 elif isinstance(target, ast.Identifier):
536 columns.append(target.parts[-1])
537 else:
538 raise NotImplementedError
540 if len(columns) == 0:
541 columns = self.get_columns()
543 # columns to lower case
544 columns = [name.lower() for name in columns]
546 if len(result) == 0:
547 result = pd.DataFrame([], columns=columns)
548 else:
549 # add absent columns
550 for col in set(columns) & set(result.columns) ^ set(columns):
551 result[col] = None
553 # filter by columns
554 result = result[columns]
556 select_statement_executor = SELECTQueryExecutor(
557 result, selected_columns, where_conditions, order_by_conditions
558 )
560 result = select_statement_executor.execute_query()
562 return result.head(total_results)
564 def get_columns(self):
565 return [
566 "name_text",
567 "name_html",
568 "description_text",
569 "description_html",
570 "url",
571 "start_timezone",
572 "start_local",
573 "start_utc",
574 "end_timezone",
575 "end_local",
576 "end_utc",
577 "organization_id",
578 "created",
579 "changed",
580 "published",
581 "capacity",
582 "capacity_is_custom",
583 "status",
584 "currency",
585 "listed",
586 "shareable",
587 "online_event",
588 "tx_time_limit",
589 "hide_start_date",
590 "hide_end_date",
591 "locale",
592 "is_locked",
593 "privacy_setting",
594 "is_series",
595 "is_series_parent",
596 "inventory_type",
597 "is_reserved_seating",
598 "show_pick_a_seat",
599 "show_seatmap_thumbnail",
600 "show_colors_in_seatmap_thumbnail",
601 "source",
602 "is_free",
603 "summary",
604 "organizer_id",
605 "venue_id",
606 "category_id",
607 "subcategory_id",
608 "format_id",
609 "id",
610 "resource_uri",
611 "is_externally_ticketed",
612 ]