Spaces:
Paused
Paused
| """ | |
| Code quality tools and configuration for the application. | |
| """ | |
| import streamlit as st | |
| import subprocess | |
| import os | |
| from pathlib import Path | |
| import tempfile | |
| import json | |
| def render_code_quality_tools(): | |
| """ | |
| Render the code quality tools interface. | |
| """ | |
| st.markdown("<h2>Code Quality Tools</h2>", unsafe_allow_html=True) | |
| # Tabs for different tools | |
| tab1, tab2, tab3, tab4 = st.tabs(["Linting", "Formatting", "Type Checking", "Testing"]) | |
| with tab1: | |
| render_linting_tools() | |
| with tab2: | |
| render_formatting_tools() | |
| with tab3: | |
| render_type_checking_tools() | |
| with tab4: | |
| render_testing_tools() | |
| def render_linting_tools(): | |
| """ | |
| Render linting tools interface. | |
| """ | |
| st.markdown("### Linting with Pylint/Flake8") | |
| st.markdown(""" | |
| Linting tools help identify potential errors, enforce coding standards, and encourage best practices. | |
| **Available Tools:** | |
| - **Pylint**: Comprehensive linter that checks for errors and enforces a coding standard | |
| - **Flake8**: Wrapper around PyFlakes, pycodestyle, and McCabe complexity checker | |
| """) | |
| # File upload for linting | |
| uploaded_file = st.file_uploader("Upload Python file for linting", type=["py"]) | |
| linter = st.radio("Select linter", ["Pylint", "Flake8"]) | |
| if uploaded_file and st.button("Run Linter"): | |
| with st.spinner(f"Running {linter}..."): | |
| # Save uploaded file to a temporary file | |
| with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as tmp_file: | |
| tmp_file.write(uploaded_file.getvalue()) | |
| tmp_path = tmp_file.name | |
| try: | |
| if linter == "Pylint": | |
| # Run pylint | |
| result = subprocess.run( | |
| ["pylint", tmp_path], | |
| capture_output=True, | |
| text=True | |
| ) | |
| else: | |
| # Run flake8 | |
| result = subprocess.run( | |
| ["flake8", tmp_path], | |
| capture_output=True, | |
| text=True | |
| ) | |
| # Display results | |
| st.subheader("Linting Results") | |
| if result.returncode == 0: | |
| st.success("No issues found!") | |
| else: | |
| st.error("Issues found:") | |
| st.code(result.stdout or result.stderr, language="text") | |
| except Exception as e: | |
| st.error(f"Error running {linter}: {str(e)}") | |
| finally: | |
| # Clean up temporary file | |
| os.unlink(tmp_path) | |
| def render_formatting_tools(): | |
| """ | |
| Render code formatting tools interface. | |
| """ | |
| st.markdown("### Code Formatting with Black & isort") | |
| st.markdown(""" | |
| Code formatters automatically reformat your code to follow a consistent style. | |
| **Available Tools:** | |
| - **Black**: The uncompromising Python code formatter | |
| - **isort**: A utility to sort imports alphabetically and automatically separate them into sections | |
| """) | |
| # File upload for formatting | |
| uploaded_file = st.file_uploader("Upload Python file for formatting", type=["py"]) | |
| formatter = st.radio("Select formatter", ["Black", "isort", "Both"]) | |
| if uploaded_file and st.button("Format Code"): | |
| with st.spinner(f"Running {formatter}..."): | |
| # Get original code | |
| original_code = uploaded_file.getvalue().decode("utf-8") | |
| # Save uploaded file to a temporary file | |
| with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as tmp_file: | |
| tmp_file.write(uploaded_file.getvalue()) | |
| tmp_path = tmp_file.name | |
| try: | |
| formatted_code = "" | |
| if formatter in ["Black", "Both"]: | |
| # Run black | |
| result = subprocess.run( | |
| ["black", tmp_path], | |
| capture_output=True, | |
| text=True | |
| ) | |
| with open(tmp_path, "r") as f: | |
| formatted_code = f.read() | |
| if formatter in ["isort", "Both"]: | |
| # If both, use the code formatted by black | |
| if formatter == "Both": | |
| with open(tmp_path, "w") as f: | |
| f.write(formatted_code) | |
| # Run isort | |
| result = subprocess.run( | |
| ["isort", tmp_path], | |
| capture_output=True, | |
| text=True | |
| ) | |
| with open(tmp_path, "r") as f: | |
| formatted_code = f.read() | |
| # Display results side by side | |
| st.subheader("Formatting Results") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown("#### Original Code") | |
| st.code(original_code, language="python") | |
| with col2: | |
| st.markdown("#### Formatted Code") | |
| st.code(formatted_code, language="python") | |
| except Exception as e: | |
| st.error(f"Error running {formatter}: {str(e)}") | |
| finally: | |
| # Clean up temporary file | |
| os.unlink(tmp_path) | |
| def render_type_checking_tools(): | |
| """ | |
| Render type checking tools interface. | |
| """ | |
| st.markdown("### Type Checking with mypy") | |
| st.markdown(""" | |
| Static type checking helps catch type errors before runtime. | |
| **Available Tool:** | |
| - **mypy**: Optional static typing for Python | |
| """) | |
| # File upload for type checking | |
| uploaded_file = st.file_uploader("Upload Python file for type checking", type=["py"]) | |
| if uploaded_file and st.button("Check Types"): | |
| with st.spinner("Running mypy..."): | |
| # Save uploaded file to a temporary file | |
| with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as tmp_file: | |
| tmp_file.write(uploaded_file.getvalue()) | |
| tmp_path = tmp_file.name | |
| try: | |
| # Run mypy | |
| result = subprocess.run( | |
| ["mypy", tmp_path], | |
| capture_output=True, | |
| text=True | |
| ) | |
| # Display results | |
| st.subheader("Type Checking Results") | |
| if result.returncode == 0: | |
| st.success("No type issues found!") | |
| else: | |
| st.error("Type issues found:") | |
| st.code(result.stdout or result.stderr, language="text") | |
| except Exception as e: | |
| st.error(f"Error running mypy: {str(e)}") | |
| finally: | |
| # Clean up temporary file | |
| os.unlink(tmp_path) | |
| def render_testing_tools(): | |
| """ | |
| Render testing tools interface. | |
| """ | |
| st.markdown("### Testing with pytest") | |
| st.markdown(""" | |
| Testing frameworks help ensure your code works as expected. | |
| **Available Tool:** | |
| - **pytest**: Simple and powerful testing framework | |
| """) | |
| # Test file upload | |
| test_file = st.file_uploader("Upload test file", type=["py"]) | |
| # Code file upload (optional) | |
| code_file = st.file_uploader("Upload code file to test (optional)", type=["py"]) | |
| if test_file and st.button("Run Tests"): | |
| with st.spinner("Running tests..."): | |
| # Create temporary directory for test files | |
| with tempfile.TemporaryDirectory() as tmp_dir: | |
| # Save test file | |
| test_path = os.path.join(tmp_dir, "test_" + test_file.name) | |
| with open(test_path, "wb") as f: | |
| f.write(test_file.getvalue()) | |
| # Save code file if provided | |
| if code_file: | |
| code_path = os.path.join(tmp_dir, code_file.name) | |
| with open(code_path, "wb") as f: | |
| f.write(code_file.getvalue()) | |
| try: | |
| # Run pytest | |
| result = subprocess.run( | |
| ["pytest", "-v", test_path], | |
| capture_output=True, | |
| text=True | |
| ) | |
| # Display results | |
| st.subheader("Test Results") | |
| st.code(result.stdout, language="text") | |
| if result.returncode == 0: | |
| st.success("All tests passed!") | |
| else: | |
| st.error("Some tests failed.") | |
| except Exception as e: | |
| st.error(f"Error running tests: {str(e)}") | |
| def create_pylintrc(): | |
| """ | |
| Create a sample pylintrc configuration file. | |
| """ | |
| pylintrc = """[MASTER] | |
| # Python version | |
| py-version = 3.8 | |
| # Parallel processing | |
| jobs = 1 | |
| [MESSAGES CONTROL] | |
| # Disable specific messages | |
| disable= | |
| C0111, # missing-docstring | |
| C0103, # invalid-name | |
| R0903, # too-few-public-methods | |
| R0913, # too-many-arguments | |
| W0511, # fixme | |
| [FORMAT] | |
| # Maximum line length | |
| max-line-length = 100 | |
| # Expected indentation | |
| indent-string = ' ' | |
| [DESIGN] | |
| # Maximum number of locals for function / method body | |
| max-locals = 15 | |
| # Maximum number of arguments for function / method | |
| max-args = 5 | |
| # Maximum number of attributes for a class | |
| max-attributes = 7 | |
| """ | |
| return pylintrc | |
| def create_flake8_config(): | |
| """ | |
| Create a sample flake8 configuration file. | |
| """ | |
| flake8_config = """[flake8] | |
| max-line-length = 100 | |
| exclude = .git,__pycache__,build,dist | |
| ignore = | |
| E203, # whitespace before ':' | |
| E501, # line too long | |
| W503 # line break before binary operator | |
| """ | |
| return flake8_config | |
| def create_mypy_config(): | |
| """ | |
| Create a sample mypy configuration file. | |
| """ | |
| mypy_config = """[mypy] | |
| python_version = 3.8 | |
| warn_return_any = True | |
| warn_unused_configs = True | |
| disallow_untyped_defs = False | |
| disallow_incomplete_defs = False | |
| [mypy.plugins.numpy.*] | |
| follow_imports = skip | |
| [mypy.plugins.pandas.*] | |
| follow_imports = skip | |
| """ | |
| return mypy_config | |
| def create_pytest_config(): | |
| """ | |
| Create a sample pytest configuration file. | |
| """ | |
| pytest_config = """[pytest] | |
| testpaths = tests | |
| python_files = test_*.py | |
| python_functions = test_* | |
| markers = | |
| slow: marks tests as slow (deselect with '-m "not slow"') | |
| integration: marks tests as integration tests | |
| """ | |
| return pytest_config |