check-duplicate-variables 1.0.4
A tool to detect duplicate variable names within the same scope in Python files
Requires Python: >=3.7
Keywords: python, ast, duplicate, variables, code-quality, testing, static-analysis, linting

# check-duplicate-variables

A Python tool that detects duplicate variable names within the same scope (module or class) in Python files. This tool is designed to help identify potential copy-paste errors, refactoring issues, and maintain code quality in automated testing frameworks, particularly page object models.

## Features

- **AST-based Analysis**: Uses Python's Abstract Syntax Tree (AST) for accurate parsing
- **Scope-aware Detection**: Identifies duplicates within module-level and class-level scopes separately
- **Value Comparison**: Reports whether duplicate assignments have the same or different values
- **Multiple Assignment Types**: Handles standard assignments, type-annotated assignments, tuple unpacking, and attribute assignments
- **Recursive Directory Scanning**: Automatically scans all Python files in a directory tree
- **CI/CD Friendly**: Provides exit codes and formatted output suitable for continuous integration pipelines
- **Error Handling**: Gracefully handles file I/O errors, encoding issues, and syntax errors

## Installation

### Install from PyPI

```bash
pip install check-duplicate-variables
```

### Install from Source

```bash
git clone https://github.com/pandiyarajk/check-duplicate-python-variables.git
cd check-duplicate-python-variables
pip install .
```

### Requirements

- Python 3.7 or higher
- No additional packages required (uses only standard library: `ast`, `os`, `sys`, `collections`, `typing`)

## Usage

### Basic Usage

After installation, use the `check-duplicate-variables` command:

```bash
check-duplicate-variables
```

This will look for a `pageobjects` directory in the current working directory.

### Custom Directory

Specify a custom directory to scan:

```bash
check-duplicate-variables /path/to/your/python/files
```

### As a Python Module

You can also run it as a Python module:

```bash
python -m check-duplicate-variables [directory]

or

python -m check-duplicate-variables [filepath]
```

### Standalone Script

If you have the standalone script, you can run it directly:

```bash
python check_duplicate_variables.py [directory]
```

### Exit Codes

- `0`: No duplicates found and no errors encountered
- `1`: Duplicates found or I/O/parse errors occurred

## Output Format

The tool outputs one line per duplicate variable found:

```
file_path: variable_name (same values) - line1, line2, line3
file_path: variable_name (different values) - line1, line2
```

### Example Output

```
pageobjects/login_page.py: username (same values) - 15, 23, 45
pageobjects/login_page.py: password (different values) - 18, 32
pageobjects/dashboard.py: button_text (same values) - 10, 25
```

- `(same values)`: All assignments have identical values (potential copy-paste error)
- `(different values)`: Assignments have different values (intentional reassignment or bug)

## How It Works

1. **File Scanning**: Recursively walks the specified directory and finds all `.py` files
2. **AST Parsing**: Each file is parsed using Python's `ast` module
3. **Variable Tracking**: The `VariableAnalyzer` visitor class traverses the AST and tracks all variable assignments per scope
4. **Duplicate Detection**: Identifies variables assigned more than once in the same scope
5. **Value Comparison**: Extracts and normalizes the source code of assigned values to compare them
6. **Reporting**: Outputs results in a CI-friendly format with line numbers and value comparison status

## Supported Assignment Types

The tool detects duplicates in the following assignment patterns:

- **Simple assignments**: `x = 1`
- **Type-annotated assignments**: `x: int = 1`
- **Multiple assignments**: `x = y = 1`
- **Tuple unpacking**: `a, b = 1, 2`
- **Attribute assignments**: `self.attr = value`
- **Subscript assignments**: `x[i] = value`

## Use Cases

- **Page Object Models**: Detect duplicate locators or element definitions in Selenium/Playwright page objects
- **Code Quality**: Identify copy-paste errors and refactoring opportunities
- **Pre-commit Hooks**: Integrate into Git pre-commit hooks to catch issues before commit
- **CI/CD Pipelines**: Add to GitHub Actions, GitLab CI, or other CI/CD workflows
- **Code Reviews**: Automated detection of duplicate variable definitions

## Integration Examples

### GitHub Actions

```yaml
name: Check Duplicate Variables

on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Install check-duplicate-variables
        run: pip install check-duplicate-variables
      - name: Check for duplicate variables
        run: check-duplicate-variables ./src
```

### Pre-commit Hook

Create `.git/hooks/pre-commit`:

```bash
#!/bin/bash
check-duplicate-variables ./pageobjects
if [ $? -ne 0 ]; then
    echo "Duplicate variables detected. Please fix before committing."
    exit 1
fi
```

## Limitations

- Only detects duplicates within the same scope (module or class)
- Does not detect duplicates across different scopes (e.g., module variable vs. class variable with same name)
- Value comparison is based on source code normalization, not runtime evaluation
- Does not handle dynamically generated variable names

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Author

**Pandiyaraj Karuppasamy**

- Email: pandiyarajk@live.com
- GitHub: [@pandiyarajk](https://github.com/pandiyarajk)

## Repository

https://github.com/pandiyarajk/check-duplicate-python-variables.git

## Changelog

See [CHANGE_LOG.md](CHANGE_LOG.md) for version history and changes.