Skip to content

Commit

Permalink
Merge pull request #54 from nalbion/feature/get_email-from-gitconfig
Browse files Browse the repository at this point in the history
get email from ~/.gitconfig
  • Loading branch information
LeonOstrez authored Sep 9, 2023
2 parents c724429 + b780a9f commit bcfefd0
Show file tree
Hide file tree
Showing 22 changed files with 113 additions and 48 deletions.
13 changes: 7 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8, 3.9, 3.10, 3.11]
python-version: ['3.8', '3.9', '3.10', '3.11']

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
Expand All @@ -30,14 +30,15 @@ jobs:
- name: Lint
run: |
pip install flake8
pip install flake8 ruff
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# stop the build if there are Python syntax errors or undefined names
#ruff --format=github --select=E9,F63,F7,F82 --target-version=py37 .
ruff --format=github --select=E9,F63,F7,F82 --target-version=py37 .
# default set of ruff rules with GitHub Annotations
#ruff --format=github --target-version=py37 .
#ruff --format=github --target-version=py37 --ignore=F401,E501 .
- name: Run tests
run: |
pip install pytest
pytest
cd pilot
PYTHONPATH=. pytest
2 changes: 1 addition & 1 deletion pilot/const/llm.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
MAX_GPT_MODEL_TOKENS = int(os.getenv('MAX_TOKENS'))
MAX_GPT_MODEL_TOKENS = int(os.getenv('MAX_TOKENS', 8192))
MIN_TOKENS_FOR_GPT_RESPONSE = 600
MAX_QUESTIONS = 5
END_RESPONSE = "EVERYTHING_CLEAR"
4 changes: 2 additions & 2 deletions pilot/database/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from functools import reduce
import operator
import psycopg2
from const.common import PROMPT_DATA_TO_IGNORE
from logger.logger import logger
from psycopg2.extensions import quote_ident

from const.common import PROMPT_DATA_TO_IGNORE
from logger.logger import logger
from utils.utils import hash_data
from database.config import DB_NAME, DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DATABASE_TYPE
from database.models.components.base_models import database
Expand Down
2 changes: 1 addition & 1 deletion pilot/database/models/architecture.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ class Architecture(ProgressStep):
architecture = JSONField() # Custom JSON field for SQLite

class Meta:
db_table = 'architecture'
table_name = 'architecture'
2 changes: 1 addition & 1 deletion pilot/database/models/command_runs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class CommandRuns(BaseModel):
previous_step = ForeignKeyField('self', null=True, column_name='previous_step')

class Meta:
db_table = 'command_runs'
table_name = 'command_runs'
indexes = (
(('app', 'hash_id'), True),
)
2 changes: 1 addition & 1 deletion pilot/database/models/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@

class Development(ProgressStep):
class Meta:
db_table = 'development'
table_name = 'development'
2 changes: 1 addition & 1 deletion pilot/database/models/development_planning.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ class DevelopmentPlanning(ProgressStep):
development_plan = JSONField() # Custom JSON field for SQLite

class Meta:
db_table = 'development_planning'
table_name = 'development_planning'
2 changes: 1 addition & 1 deletion pilot/database/models/development_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class DevelopmentSteps(BaseModel):
previous_step = ForeignKeyField('self', null=True, column_name='previous_step')

class Meta:
db_table = 'development_steps'
table_name = 'development_steps'
indexes = (
(('app', 'hash_id'), True),
)
2 changes: 1 addition & 1 deletion pilot/database/models/environment_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

class EnvironmentSetup(ProgressStep):
class Meta:
db_table = 'environment_setup'
table_name = 'environment_setup'
2 changes: 1 addition & 1 deletion pilot/database/models/file_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class FileSnapshot(BaseModel):
content = TextField()

class Meta:
db_table = 'file_snapshot'
table_name = 'file_snapshot'
indexes = (
(('development_step', 'file'), True),
)
2 changes: 1 addition & 1 deletion pilot/database/models/project_description.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ class ProjectDescription(ProgressStep):
summary = TextField()

class Meta:
db_table = 'project_description'
table_name = 'project_description'
2 changes: 1 addition & 1 deletion pilot/database/models/user_apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class UserApps(BaseModel):
workspace = CharField(null=True)

class Meta:
db_table = 'user_apps'
table_name = 'user_apps'
indexes = (
(('app', 'user'), True),
)
2 changes: 1 addition & 1 deletion pilot/database/models/user_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class UserInputs(BaseModel):
previous_step = ForeignKeyField('self', null=True, column_name='previous_step')

class Meta:
db_table = 'user_inputs'
table_name = 'user_inputs'
indexes = (
(('app', 'hash_id'), True),
)
2 changes: 1 addition & 1 deletion pilot/database/models/user_stories.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ class UserStories(ProgressStep):
else:
user_stories = JSONField() # Custom JSON field for SQLite
class Meta:
db_table = 'user_stories'
table_name = 'user_stories'
2 changes: 1 addition & 1 deletion pilot/database/models/user_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ class UserTasks(ProgressStep):
user_tasks = JSONField() # Custom JSON field for SQLite

class Meta:
db_table = 'user_tasks'
table_name = 'user_tasks'
4 changes: 2 additions & 2 deletions pilot/helpers/agents/Developer.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def implement_step(self, convo, step_index, type, description):
if type == 'COMMAND':
for cmd in step_details:
run_command_until_success(cmd['command'], cmd['timeout'], convo)
elif type == 'CODE_CHANGE':
code_changes_details = get_step_code_changes()
# elif type == 'CODE_CHANGE':
# code_changes_details = get_step_code_changes()
# TODO: give to code monkey for implementation
pass
Empty file added pilot/logger/__init__.py
Empty file.
5 changes: 1 addition & 4 deletions pilot/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@
from __future__ import print_function, unicode_literals

import sys

from dotenv import load_dotenv
from termcolor import colored
load_dotenv()

from termcolor import colored
from helpers.Project import Project

from utils.arguments import get_arguments
from utils.exit import exit_gpt_pilot
from logger.logger import logger
Expand Down
2 changes: 1 addition & 1 deletion pilot/prompts/dev_ops/debug.prompt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ You wanted me to check this - `{{ issue_description }}` but there was a problem{

`run_command` function will run a command on the machine and will return the CLI output to you so you can see what to do next.

`implement_code_changes` function will change the code where you just need to thoroughly describe what needs to be implmemented, I will implement the requested changes and let you know.
`implement_code_changes` function will change the code where you just need to thoroughly describe what needs to be implemented, I will implement the requested changes and let you know.

Return a list of steps that are needed to debug this issue. By the time we execute the last step, the issue should be fixed completely. Also, make sure that at least the last step has `check_if_fixed` set to TRUE.

Expand Down
40 changes: 26 additions & 14 deletions pilot/utils/arguments.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import getpass
import hashlib
import os
import re
import sys
import uuid

from getpass import getuser
from termcolor import colored

from database.database import get_app, get_app_by_user_workspace


Expand All @@ -25,7 +25,7 @@ def get_arguments():
arguments[arg] = True

if 'user_id' not in arguments:
arguments['user_id'] = username_to_uuid(getpass.getuser())
arguments['user_id'] = username_to_uuid(getuser())

app = None
if 'workspace' in arguments:
Expand All @@ -40,7 +40,6 @@ def get_arguments():
if app is None:
app = get_app(arguments['app_id'])

# arguments['user_id'] = str(app.user.id)
arguments['app_type'] = app.app_type
arguments['name'] = app.name
# Add any other fields from the App model you wish to include
Expand All @@ -54,19 +53,12 @@ def get_arguments():
else:
arguments['app_id'] = str(uuid.uuid4())
print(colored('\n------------------ STARTING NEW PROJECT ----------------------', 'green', attrs=['bold']))
print(f"If you wish to continue with this project in future run:")
print("If you wish to continue with this project in future run:")
print(colored(f'python {sys.argv[0]} app_id={arguments["app_id"]}', 'green', attrs=['bold']))
print(colored('--------------------------------------------------------------\n', 'green', attrs=['bold']))



if 'user_id' not in arguments:
arguments['user_id'] = username_to_uuid(getpass.getuser())

if 'email' not in arguments:
# todo change email so its not uuid4 but make sure to fix storing of development steps where
# 1 user can have multiple apps. In that case each app should have its own development steps
arguments['email'] = str(uuid.uuid4())
arguments['email'] = get_email()

if 'password' not in arguments:
arguments['password'] = 'password'
Expand All @@ -77,6 +69,26 @@ def get_arguments():
return arguments


def get_email():
# Attempt to get email from .gitconfig
gitconfig_path = os.path.expanduser('~/.gitconfig')

if os.path.exists(gitconfig_path):
with open(gitconfig_path, 'r') as file:
content = file.read()

# Use regex to search for email address
email_match = re.search(r'email\s*=\s*([\w\.-]+@[\w\.-]+)', content)

if email_match:
return email_match.group(1)

# If not found, return a UUID
# todo change email so its not uuid4 but make sure to fix storing of development steps where
# 1 user can have multiple apps. In that case each app should have its own development steps
return str(uuid.uuid4())


# TODO can we make BaseModel.id a CharField with default=uuid4?
def username_to_uuid(username):
sha1 = hashlib.sha1(username.encode()).hexdigest()
Expand Down
27 changes: 21 additions & 6 deletions pilot/utils/llm_connection.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import re
import requests
import os
import sys
import time
import json
import tiktoken
import questionary
Expand Down Expand Up @@ -116,7 +118,7 @@ def create_gpt_chat_completion(messages: List[dict], req_type, min_tokens=MIN_TO

# Check if the error message is related to token limit
if "context_length_exceeded" in error_message.lower():
raise Exception(f'Too many tokens in the request. Please try to continue the project with some previous development step.')
raise Exception('Too many tokens in the request. Please try to continue the project with some previous development step.')
else:
print('The request to OpenAI API failed. Here is the error message:')
print(e)
Expand Down Expand Up @@ -147,8 +149,15 @@ def wrapper(*args, **kwargs):
# If the specific error "context_length_exceeded" is present, simply return without retry
if "context_length_exceeded" in err_str:
raise Exception("context_length_exceeded")

print(colored(f'There was a problem with request to openai API:', 'red'))
if "rate_limit_exceeded" in err_str:
# Extracting the duration from the error string
match = re.search(r"Please try again in (\d+)ms.", err_str)
if match:
wait_duration = int(match.group(1)) / 1000
time.sleep(wait_duration)
continue

print(colored('There was a problem with request to openai API:', 'red'))
print(err_str)

user_message = questionary.text(
Expand Down Expand Up @@ -187,10 +196,16 @@ def return_result(result_data, lines_printed):
if endpoint == 'AZURE':
# If yes, get the AZURE_ENDPOINT from .ENV file
endpoint_url = os.getenv('AZURE_ENDPOINT') + '/openai/deployments/' + model + '/chat/completions?api-version=2023-05-15'
headers = {'Content-Type': 'application/json', 'api-key': os.getenv('AZURE_API_KEY')}
headers = {
'Content-Type': 'application/json',
'api-key': os.getenv('AZURE_API_KEY')
}
else:
# If not, send the request to the OpenAI endpoint
headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + os.getenv("OPENAI_API_KEY")}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + os.getenv("OPENAI_API_KEY")
}
endpoint_url = 'https://api.openai.com/v1/chat/completions'

response = requests.post(
Expand Down Expand Up @@ -230,7 +245,7 @@ def return_result(result_data, lines_printed):

if json_line['choices'][0]['finish_reason'] == 'function_call':
function_calls['arguments'] = load_data_to_json(function_calls['arguments'])
return return_result({'function_calls': function_calls}, lines_printed);
return return_result({'function_calls': function_calls}, lines_printed)

json_line = json_line['choices'][0]['delta']

Expand Down
40 changes: 40 additions & 0 deletions pilot/utils/test_arguments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import pytest
from unittest.mock import patch, mock_open
import uuid
from .arguments import get_email, username_to_uuid


def test_email_found_in_gitconfig():
mock_file_content = """
[user]
name = test_user
email = [email protected]
"""
with patch('os.path.exists', return_value=True):
with patch('builtins.open', mock_open(read_data=mock_file_content)):
assert get_email() == "[email protected]"


def test_email_not_found_in_gitconfig():
mock_file_content = """
[user]
name = test_user
"""
mock_uuid = "12345678-1234-5678-1234-567812345678"

with patch('os.path.exists', return_value=True):
with patch('builtins.open', mock_open(read_data=mock_file_content)):
with patch.object(uuid, "uuid4", return_value=mock_uuid):
assert get_email() == mock_uuid


def test_gitconfig_not_present():
mock_uuid = "12345678-1234-5678-1234-567812345678"

with patch('os.path.exists', return_value=False):
with patch.object(uuid, "uuid4", return_value=mock_uuid):
assert get_email() == mock_uuid


def test_username_to_uuid():
assert username_to_uuid("test_user") == "31676025-316f-b555-e0bf-a12f0bcfd0ea"

0 comments on commit bcfefd0

Please sign in to comment.