Skip to main content
Glama

Penpot MCP Server

by montevive
lint.py9.26 kB
#!/usr/bin/env python3 """Script to run linters with auto-fix capabilities. Run with: python lint.py [--autofix] """ import argparse import importlib.util import subprocess import sys from pathlib import Path def is_venv(): """Check if running in a virtual environment.""" return (hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)) def check_dependencies(): """Check if all required dependencies are installed.""" missing_deps = [] # Check for required modules required_modules = ["flake8", "isort", "autopep8", "pyflakes"] # In Python 3.12+, also check for pycodestyle as a fallback if sys.version_info >= (3, 12): required_modules.append("pycodestyle") for module in required_modules: if importlib.util.find_spec(module) is None: missing_deps.append(module) # Special check for autopep8 compatibility with Python 3.12+ if sys.version_info >= (3, 12) and importlib.util.find_spec("autopep8") is not None: try: import autopep8 # Try to access a function that would use lib2to3 # Will throw an error if lib2to3 is missing and not handled properly autopep8_version = autopep8.__version__ print(f"Using autopep8 version: {autopep8_version}") except ImportError as e: if "lib2to3" in str(e): print("WARNING: You're using Python 3.12+ where lib2to3 is no longer included.") print("Your installed version of autopep8 may not work correctly.") print("Consider using a version of autopep8 compatible with Python 3.12+") print("or run this script with Python 3.11 or earlier.") if missing_deps: print("ERROR: Missing required dependencies:") for dep in missing_deps: print(f" - {dep}") if not is_venv(): print("\nYou are using the system Python environment.") print("It's recommended to use a virtual environment:") print("\n1. Create a virtual environment:") print(" python3 -m venv .venv") print("\n2. Activate the virtual environment:") print(" source .venv/bin/activate # On Linux/macOS") print(" .venv\\Scripts\\activate # On Windows") print("\n3. Install dependencies:") print(" pip install -r requirements-dev.txt") else: print("\nPlease install these dependencies with:") print(" pip install -r requirements-dev.txt") return False return True def run_command(cmd, cwd=None): """Run a shell command and return the exit code.""" try: process = subprocess.run(cmd, shell=True, cwd=cwd) return process.returncode except Exception as e: print(f"Error executing command '{cmd}': {e}") return 1 def fix_unused_imports(root_dir): """Fix unused imports using pyflakes and autoflake.""" try: if importlib.util.find_spec("autoflake") is not None: print("Running autoflake to remove unused imports...") cmd = "autoflake --remove-all-unused-imports --recursive --in-place penpot_mcp/ tests/" return run_command(cmd, cwd=root_dir) else: print("autoflake not found. To automatically remove unused imports, install:") print(" pip install autoflake") return 0 except Exception as e: print(f"Error with autoflake: {e}") return 0 def fix_whitespace_and_docstring_issues(root_dir): """Attempt to fix whitespace and simple docstring issues.""" # Find Python files that need fixing try: filelist_cmd = "find penpot_mcp tests setup.py -name '*.py' -type f" process = subprocess.run( filelist_cmd, shell=True, cwd=root_dir, capture_output=True, text=True ) if process.returncode != 0: print("Error finding Python files") return 1 files = process.stdout.strip().split('\n') fixed_count = 0 for file_path in files: if not file_path: continue full_path = Path(root_dir) / file_path try: with open(full_path, 'r', encoding='utf-8') as f: content = f.read() # Fix trailing whitespace fixed_content = '\n'.join(line.rstrip() for line in content.split('\n')) # Ensure final newline if not fixed_content.endswith('\n'): fixed_content += '\n' # Add basic docstrings to empty modules, classes, functions if '__init__.py' in file_path and '"""' not in fixed_content: package_name = file_path.split('/')[-2] fixed_content = f'"""Package {package_name}."""\n' + fixed_content # Write back if changes were made if fixed_content != content: with open(full_path, 'w', encoding='utf-8') as f: f.write(fixed_content) fixed_count += 1 except Exception as e: print(f"Error processing {file_path}: {e}") if fixed_count > 0: print(f"Fixed whitespace and newlines in {fixed_count} files") return 0 except Exception as e: print(f"Error in whitespace fixing: {e}") return 0 def main(): """Main entry point for the linter script.""" parser = argparse.ArgumentParser(description="Run linters with optional auto-fix") parser.add_argument( "--autofix", "-a", action="store_true", help="Automatically fix linting issues" ) args = parser.parse_args() # Verify dependencies before proceeding if not check_dependencies(): return 1 root_dir = Path(__file__).parent.absolute() print("Running linters...") # Run isort isort_cmd = "isort --profile black ." if args.autofix: print("Running isort with auto-fix...") exit_code = run_command(isort_cmd, cwd=root_dir) else: print("Checking imports with isort...") exit_code = run_command(f"{isort_cmd} --check", cwd=root_dir) if exit_code != 0 and not args.autofix: print("isort found issues. Run with --autofix to fix automatically.") # Run additional fixers when in autofix mode if args.autofix: # Fix unused imports fix_unused_imports(root_dir) # Fix whitespace and newline issues fix_whitespace_and_docstring_issues(root_dir) # Run autopep8 print("Running autopep8 with auto-fix...") if sys.version_info >= (3, 12): print("Detected Python 3.12+. Using compatible code formatting approach...") # Use a more compatible approach for Python 3.12+ # First try autopep8 (newer versions may have fixed lib2to3 dependency) autopep8_cmd = "autopep8 --recursive --aggressive --aggressive --in-place --select E,W penpot_mcp/ tests/ setup.py" try: exit_code = run_command(autopep8_cmd, cwd=root_dir) if exit_code != 0: print("Warning: autopep8 encountered issues. Some files may not have been fixed.") except Exception as e: if "lib2to3" in str(e): print("Error with autopep8 due to missing lib2to3 module in Python 3.12+") print("Using pycodestyle for checking only (no auto-fix is possible)") exit_code = run_command("pycodestyle penpot_mcp/ tests/", cwd=root_dir) else: raise else: # Normal execution for Python < 3.12 autopep8_cmd = "autopep8 --recursive --aggressive --aggressive --in-place --select E,W penpot_mcp/ tests/ setup.py" exit_code = run_command(autopep8_cmd, cwd=root_dir) if exit_code != 0: print("Warning: autopep8 encountered issues. Some files may not have been fixed.") # Run flake8 (check only, no auto-fix) print("Running flake8...") flake8_cmd = "flake8 --exclude=.venv,venv,__pycache__,.git,build,dist,*.egg-info,node_modules" flake8_result = run_command(flake8_cmd, cwd=root_dir) if flake8_result != 0: print("flake8 found issues that need to be fixed manually.") print("Common issues and how to fix them:") print("- F401 (unused import): Remove the import or use it") print("- D1XX (missing docstring): Add a docstring to the module/class/function") print("- E501 (line too long): Break the line or use line continuation") print("- F841 (unused variable): Remove or use the variable") if args.autofix: print("Auto-fix completed! Run flake8 again to see if there are any remaining issues.") elif exit_code != 0 or flake8_result != 0: print("Linting issues found. Run with --autofix to fix automatically where possible.") return 1 else: print("All linting checks passed!") return 0 if __name__ == "__main__": sys.exit(main())

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/montevive/penpot-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server