diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..75d215c --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,33 @@ +{ + "name": "Python 3", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye", + "customizations": { + "codespaces": { + "openFiles": [ + "README.md", + "streamlit.py" + ] + }, + "vscode": { + "settings": {}, + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance" + ] + } + }, + "updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y None: - from .gemini_config import AnalyzerConfigs, ResponseData #prevent circular import - - self.language: str[Optional] = "python" - self.style_guide: str[Optional] = "google official" - self.gemini_model = genai.GenerativeModel( - AnalyzerConfigs.gemini_models[1], - generation_config={ - "response_mime_type": "application/json", - "response_schema": list[ResponseData] - } - ) - self._gen_ai_config = genai.configure(api_key=AnalyzerConfigs.genai_api_key) - self._input_code: str = None - self._prompt: str = None - self._response: Union[list, None] = None - self._logger = structlog.get_logger("CodeAnalyzer") - - def analyze_code(self) -> Union[list, None]: - ''' - This method analyzes the input code and generates a style guide using the Gemini model. - ''' - try: - prompt = f"""Analyze the following {self.language} code according to {self.style_guide} style guidelines: + def __init__(self) -> None: + from .gemini_config import ( + AnalyzerConfigs, + ResponseData, + ) # prevent circular import + + self.language: str[Optional] = "python" + self.style_guide: str[Optional] = "google official" + self.gemini_model = genai.GenerativeModel( + AnalyzerConfigs.gemini_models[1], + generation_config={ + "response_mime_type": "application/json", + "response_schema": list[ResponseData], + }, + ) + self._gen_ai_config = genai.configure(api_key=AnalyzerConfigs.genai_api_key) + self._input_code: str = None + self._prompt: str = None + self._response: Union[list, None] = None + self._logger = structlog.get_logger("CodeAnalyzer") + + def analyze_code(self) -> Union[list, None]: + """ + This method analyzes the input code and generates a style guide using the Gemini model. + """ + try: + prompt = f"""Analyze the following {self.language} code according to {self.style_guide} style guidelines: ```{self.language} + {self._input_code} ``` @@ -42,19 +47,21 @@ def analyze_code(self) -> Union[list, None]: 1. Specific violations message with line numbers. 2. Suggestions for how to fix each violation, ideally with code examples. 3. Prioritize Only the most critical issues for readability and maintainability. - """ - - model = self.gemini_model - response = model.generate_content(prompt) - - # Extract and format the style guide from the response - # You will need to implement parsing logic here based on Gemini's response format - - style_guide = response.text # Adjust this based on the actual response structure - self._logger.info("Style guide generated successfully.") - #self._logger.info(style_guide) - return style_guide - - except Exception as e: - self._logger.error(f"Error generating style guide: {e}") - return None \ No newline at end of file + """ + + model = self.gemini_model + response = model.generate_content(prompt) + + # Extract and format the style guide from the response + # You will need to implement parsing logic here based on Gemini's response format + + style_guide = ( + response.text + ) # Adjust this based on the actual response structure + self._logger.info("Style guide generated successfully.") + # self._logger.info(style_guide) + return style_guide + + except Exception as e: + self._logger.error(f"Error generating style guide: {e}") + return None diff --git a/app/gemini_config.py b/app/gemini_config.py index 574c9d2..2220fc0 100644 --- a/app/gemini_config.py +++ b/app/gemini_config.py @@ -1,25 +1,38 @@ -import os import streamlit as st -from typing import TypedDict +from typing_extensions import TypedDict + + class AnalyzerConfigs: - ''' + """ This class contains configuration settings for the CodeAnalyzer class. - ''' + """ + gemini_models: list = [ - "gemini-1.5-flash", - "gemini-1.5-pro", #INFO : https://ai.google.dev/gemini-api/docs/json-mode?lang=python + "gemini-1.5-flash", + "gemini-1.5-pro", # INFO : https://ai.google.dev/gemini-api/docs/json-mode?lang=python + ] + famous_languages: list = [ + "Python", + "Java", + "JavaScript", + "C++", + "C#", + "Ruby", + "Go", + "Swift", + "Rust", ] - famous_languages: list = ["Python", "Java", "JavaScript", "C++", "C#", "Ruby", "Go", "Swift", "Rust"] genai_api_key: str = st.secrets["GENAI_API_KEY"] style_guides: dict = { - 'google style': 'https://google.github.io/styleguide/pyguide.html', - 'pep8': 'https://pep8.org/' + "google style": "https://google.github.io/styleguide/pyguide.html", + "pep8": "https://pep8.org/", } - + + class ResponseData(TypedDict): - ''' + """ For schema based responses like `JSON` - ''' + """ + line: int message: str - \ No newline at end of file diff --git a/app/gemini_wrapper.py b/app/gemini_wrapper.py index 5fccca3..dd1ddfb 100644 --- a/app/gemini_wrapper.py +++ b/app/gemini_wrapper.py @@ -2,15 +2,17 @@ import json from gemini_analyzer import CodeAnalyzer + def main(): code = sys.argv[1] analyzer = CodeAnalyzer() analyzer.setCode(code) style_guide = analyzer.analyze_code() if style_guide: - print(json.dumps({'style_guide': style_guide})) + print(json.dumps({"style_guide": style_guide})) else: - print(json.dumps({'error': 'Analysis failed'})) + print(json.dumps({"error": "Analysis failed"})) + -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/examples/class.py b/examples/class.py index 5da1e3c..48129e7 100644 --- a/examples/class.py +++ b/examples/class.py @@ -3,9 +3,10 @@ class Dog: def __init__(self, name, breed): self.name = name self.breed = breed - + def bark(self): print("Woof!") + my_dog = Dog("Buddy", "Golden Retriever") my_dog.bark() diff --git a/examples/greet.py b/examples/greet.py index e39ef0c..220570b 100644 --- a/examples/greet.py +++ b/examples/greet.py @@ -1,6 +1,7 @@ def greet(name): - """Greets the person with the given name.""" + """Greets the person with the given name.""" + + print("Hello,", name) - print("Hello,", name) greet("Alice") diff --git a/examples/sum.py b/examples/sum.py index 3ec1a3c..d4a77e2 100644 --- a/examples/sum.py +++ b/examples/sum.py @@ -1,6 +1,8 @@ -def calculate_sum( a , b): # Intentional spacing issues +def calculate_sum(a, b): # Intentional spacing issues """This function calculates the sum of two numbers.""" - result=a+b -return result # Incorrect indentation + result = a + b + + +return result # Incorrect indentation print(calculate_sum(10, 5)) diff --git a/requirements.txt b/requirements.txt index 22934d2..2ed26a8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,6 @@ python-dotenv==1.0.1 structlog==24.2.0 rich==13.7.1 watchdog==4.0.1 -flask==3.0.3 \ No newline at end of file +flask==3.0.3 +flake8==7.1.0 +black==24.4.2 \ No newline at end of file diff --git a/server.py b/server.py index 441e215..fbf4ac4 100644 --- a/server.py +++ b/server.py @@ -4,21 +4,22 @@ app = Flask(__name__) -@app.route('/analyze', methods=['POST']) + +@app.route("/analyze", methods=["POST"]) def analyze(): data = request.get_json() - code = data['code'] + code = data["code"] analyzer = CodeAnalyzer() analyzer._input_code = code style_guide = analyzer.analyze_code() processed_stule_guide = json.loads(style_guide) - issues = {'issues':processed_stule_guide} + issues = {"issues": processed_stule_guide} if style_guide: - #data = json.loads(style_guide) # Convert string to dictionary - return jsonify({'style_guide' : issues}), 200 + return jsonify({"style_guide": issues}), 200 else: - return jsonify({'error': 'Analysis failed'}), 500 + return jsonify({"error": "Analysis failed"}), 500 + -if __name__ == '__main__': +if __name__ == "__main__": app.run(port=5000) diff --git a/streamlit.py b/streamlit.py index e423bc7..8dfaf2d 100644 --- a/streamlit.py +++ b/streamlit.py @@ -5,31 +5,24 @@ code_handler = CodeAnalyzer() - st.title("AI-Powered Code Style Guide with Gemini") code_input = st.text_area("Paste your code here:", height=250) if st.button("Analyze"): if code_input: - with st.spinner('Analyzing...'): + with st.spinner("Analyzing..."): code_handler._input_code = code_input response = code_handler.analyze_code() data = json.loads(response) st.subheader("Style Guide and Suggestions:") # Expanders - try: - for items in data["issues"]: - with st.expander(f"Line `{items['line']}`"): - st.write(items['message']) - except: - pass - + for items in data["issues"]: + with st.expander(f"Line `{items['line']}`"): + st.write(items["message"]) # JSON output st.subheader("Raw API response : ") - with st.expander(f"Expand"): + with st.expander("Expand"): st.json(response) # Display the Gemini-generated style guide - time.sleep(5) - else: - st.warning("Please paste your code to analyze.") \ No newline at end of file + st.warning("Please paste your code to analyze.")