Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GoEx] Added additional support for GoEx DBs and APIs. #698

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ dist
.editorconfig
.DS_Store
**/*.pyc
goex/goex-env/
goex/exec_engine/checkpoints/
goex/exec_engine/credentials/*
!goex/exec_engine/credentials/credentials_utils.py
!goex/exec_engine/credentials/supported.txt
goex/docker/*/requirements.txt
goex/docker/misc/images.json
goex-env/*

################## Berkley Function Call Leaderboard ##########################

Expand All @@ -28,6 +30,6 @@ berkeley-function-call-leaderboard/score/
# Ignore environment variables
berkeley-function-call-leaderboard/.env
!berkeley-function-call-leaderboard/.env.example

goex/goex-env/*
.direnv/
.venv
Empty file added database_dump.sql
Empty file.
2 changes: 1 addition & 1 deletion goex/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# mysql
# mysql and postgresql
DATABASE_USER=root
DATABASE_PASSWORD=abcdefg
DATABASE_HOST=localhost
Expand Down
42 changes: 41 additions & 1 deletion goex/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ To test out database interactions locally, each database server requires its own

Press `Ctrl-D` to exit out and now your `.db` file will be created!

- Run `demo/env_setup.py` to get your environment variables set up
- Run `demo/envsetup.py_` to get your environment variables set up
Use default values if you are running just the demo.

```
Expand Down Expand Up @@ -185,6 +185,46 @@ goex execute -prompt "In the users table, add 500 to everyone's current balance"
goex -set_config dbtype mysql
```

#### PostgreSQL

- Install PostgreSQL
- For non-Mac, [install postgresql here](https://www.postgresql.org/download/)
- Mac:

```
brew install postgresql
```

- Put the user, password, host, and database name info into `.env` by running this script

```
python3 demo/env_setup.py
```

- If you don't have your own server, import the example database using `demo/postgresql_setup.py` by running:

```sh
python3 demo/postgreSQL_setup.py mydb
```

- If password authentication is required, update the authentication method in `/etc/postgresql/<version>/main/pg_hba.conf` to the following:

```
local all postgres md5
```

Then create a pgpass file to keep track of the authentication required for database operations `~/.pgpass`, with the following content, and with octal permissions 0600.
```
hostname:port:database:username:password
```

- Set GoEx to use PostgreSQL for DB operations
```
goex -set_config dbtype postgreSQL
```
#### MongoDB
- **MongoDB currently does not support a general method of executing queries. More work may need be done to support different combinations of queries for mongoDB databases**

### Filesystem

The goex command will be executed at the path pointed to by `fs_path` in `user_config.json`. If `fs_path` is not specified or is equal to `""`, execution will occur in the user's current working directory. Below is an example of how to set this up.
Expand Down
5 changes: 3 additions & 2 deletions goex/authorizations/scripts/spotify_authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import wsgiref.simple_server
import wsgiref.util
from urllib.parse import quote, urlparse, parse_qs
from .consts import AUTH_URL, CERT_FILE_PATH, KEY_FILE_PATH

from consts import AUTH_URL, CERT_FILE_PATH, KEY_FILE_PATH
print(CERT_FILE_PATH)
SPOTIFY_FOLDER_PATH = os.path.join(os.path.dirname(Path(os.path.realpath(__file__)).parent.parent), 'exec_engine/credentials/spotify')
TOKEN_FILE = os.path.join(SPOTIFY_FOLDER_PATH, 'token.pickle')

Expand All @@ -23,6 +23,7 @@ def main():
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in
creds = run_spotify_flow()
print(creds)
# Save the credentials for the next run
if not os.path.isdir(SPOTIFY_FOLDER_PATH):
os.mkdir(SPOTIFY_FOLDER_PATH)
Expand Down
4 changes: 3 additions & 1 deletion goex/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from main import ExecutionEngine, PythonAPIExecutor

from exec_engine.utils import SQL_Type, Filesystem_Type
from exec_engine.db_manager import MySQLManager, SQLiteManager
from exec_engine.db_manager import MySQLManager, SQLiteManager, PostgreSQLManager
from dotenv import load_dotenv
import questionary

Expand Down Expand Up @@ -213,6 +213,8 @@ def db_callback(prompt, generate_mode):
db_manager = MySQLManager(config, docker_sandbox=engine.docker_sandbox)
elif db_type == 'sqlite':
db_manager = SQLiteManager(config, docker_sandbox=engine.docker_sandbox)
elif db_type == 'postgresql':
db_manager = PostgreSQLManager(config, docker_sandbox=engine.docker_sandbox)
except Exception as e:
print(f"Error during {db_type} Manager Init: {e}")
return
Expand Down
45 changes: 45 additions & 0 deletions goex/demo/postgresql_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""
Setup script for postgresql
"""

import subprocess
import os
import sys
from pathlib import Path
from dotenv import load_dotenv

load_dotenv()

if __name__ == "__main__":
# Check if the database name was provided as a command-line argument
if len(sys.argv) < 2:
print("Usage: python3 postgresql_setup.py database_name")
sys.exit(1)

ROOT_FOLDER_PATH = os.path.dirname(Path(os.path.realpath(__file__)).parent)

postgresql_username = os.environ.get('DATABASE_USER')
postgresql_password = os.environ.get('DATABASE_PASSWORD')
database_name = sys.argv[1]
dump_file_path = os.path.join(ROOT_FOLDER_PATH, "docker/postgresql_docker/checkpoints/database_dump.sql")

# Command to create the database if it doesn't exist
create_db_command = f'echo "SELECT \'CREATE DATABASE {database_name}\' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = \'{database_name}\')\gexec" | psql'

# Command to import the .sql file into the postgresql database
import_command = f'psql --username={postgresql_username} {database_name} < {dump_file_path}'

# Execute the create database command
try:
subprocess.run(create_db_command, shell=True, check=True)
print(f"Database '{database_name}' created (if it didn't already exist).")
except subprocess.CalledProcessError as e:
print(f"Error creating database: {e}")
sys.exit(1)

# Execute the import command
try:
subprocess.run(import_command, shell=True, check=True)
print("Import successful")
except subprocess.CalledProcessError as e:
print(f"Error during import: {e}")
96 changes: 96 additions & 0 deletions goex/docker/postgresql_docker/checkpoints/database_dump.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
--
-- PostgreSQL database dump
--

-- Dumped from database version 14.13 (Ubuntu 14.13-0ubuntu0.22.04.1)
-- Dumped by pg_dump version 14.13 (Ubuntu 14.13-0ubuntu0.22.04.1)

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;

SET default_tablespace = '';

SET default_table_access_method = heap;

--
-- Name: employees; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.employees (
id integer NOT NULL,
name character varying(50),
department character varying(50),
salary numeric(10,2),
hire_date date
);


ALTER TABLE public.employees OWNER TO postgres;

--
-- Name: employees_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
--

CREATE SEQUENCE public.employees_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;


ALTER TABLE public.employees_id_seq OWNER TO postgres;

--
-- Name: employees_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
--

ALTER SEQUENCE public.employees_id_seq OWNED BY public.employees.id;


--
-- Name: employees id; Type: DEFAULT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.employees ALTER COLUMN id SET DEFAULT nextval('public.employees_id_seq'::regclass);


--
-- Data for Name: employees; Type: TABLE DATA; Schema: public; Owner: postgres
--

COPY public.employees (id, name, department, salary, hire_date) FROM stdin;
1 Alice Engineering 75000.00 2020-05-10
2 Bob Sales 50000.00 2019-08-15
3 Charlie Marketing 60000.00 2021-01-20
\.


--
-- Name: employees_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
--

SELECT pg_catalog.setval('public.employees_id_seq', 3, true);


--
-- Name: employees employees_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.employees
ADD CONSTRAINT employees_pkey PRIMARY KEY (id);


--
-- PostgreSQL database dump complete
--

15 changes: 15 additions & 0 deletions goex/exec_engine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,18 @@ If the user has the dry run testing option on (option 2), then before the API ca
- the setup required for each DB will be performed in a shell script located in `docker/docker/container_setup`

Afterwards, a Python script will run with the API call wrapped around a reversion tester to see if the state before running the API call and after the API call + its negation are the same. This gets captured and sent back as the dry run result. From their, the CLI or GUI can prompt the user to confirm or cancel the operation if it is deemed to be irreversible by the generated negation API.

### API

With the spotify API specifically, the functions can be tests by calling them and then running the file.
However when testing, the credentials must be editted first.

Steps to test:
1. Go to the specific spotify function that is needed to be tested
2. Change the credentials, like the client ID, client Secret, and the redirect URI
3. Run the spotify_api_details function and sign in to a spotify account
4. Call the fucntion in the file, for example to test spotify_play_song
Call by writing
>>> spotify_play_song('song_name')
^ type in any song that you want to be played!
All inputs to the functions are strings, but they can vary from album names, song names, to playlist names and song names.
Loading