upgrade-python-3

Upgrade your Python codebase from version 3.x -> 3.11

Example

constants:
  # Python upgrade prompts
  python_upgrade_prompts:
    - Replace deprecated syntax (e.g., `async` and `await` outside of functions).
    - Utilize fine-grained error locations in tracebacks for better error debugging.
    - Implement exception groups using the `except*` syntax to handle multiple exceptions.
      Ensure `except` and `except*` are not used for the same named exception in the same `try` block.
    - Enrich exceptions with context using the `.add_note()` method.
    - Apply variadic generics using `*Ts` where appropriate in functions and classes.
    - Mark all `TypedDict` fields as `Required[]` or `NotRequired[]`.
    - Use the `Self` type for class methods returning an instance of the class.
    - Use the `LiteralString` type for parameters constrained to string literals.
    - Adopt `dataclass` transforms using decorators to auto-generate methods.
    - Update `raise Exception ... from e` to the modern `raise Exception(...)` format.
    - If the file is `__init__.py` and empty, leave it unchanged.

  context_depth: 3

  #placeholder
  ignore_file_paths:
    - 'gulpfile.js'
    - 'LICENSE'
    - '**/test/**'
    - 'test/**'
    - 'package.json'
    - '.gitignore'
    - 'tsconfig.json'
    - 'README.md'
    - '**/{{ react_directory }}'
    - '**/{{ react_directory }}/**'
    - '**/Scripts/**'
    - '**/Content/**'
    - '**/Config/**'
    - '*.cs'
    - '*.xml'
    - '*.csproj'
    - '*.asax'
    - '*.config'

steps:
  # Update each requirements file
  - name: Update each requirements file
    tools:
      - name: find_files_by_name_with_regex
        arguments:
          find_file_name_pattern: 'requirements*.txt|(^|/)(Pipfile)$|(^|/)(setup.py)$'
        returns: requirements_files
      - name: async_each
        items: '{{ requirements_files }}'
        each_item:
          item_name: requirements_file
          tools:
            - name: edit_file
              arguments:
                path_to_file: '{{ requirements_file }}'
                edit_prompt: |
                  Upgrade all libraries and dependencies for Python 3.11 compatibility.

                  # Instructions:
                  - **Python Version:** Ensure `python_version` is set to `=3.11` in Pipfile and setup.py. For requirements.txt, omit versioning.
                  - Ensure valid TOML formatting for Pipfile.
                  - Loosen pinned versions (`==`) to `>=` where newer versions are compatible with Python 3.11.
                  - Ensure the final file is free of hidden control/escape characters to ensure cross-platform usability (especially macOS).

  # Build context graph
  - name: Build a context graph of the codebase
    tools:
      - name: find_files_by_name_with_regex
        arguments:
          find_file_name_pattern: '^(?!.*(__init__)).*\.py$'
        returns: files

      - name: build_dependency_graph_with_ai
        arguments:
          files_to_index: '{{ files }}'
          exclude_path_patterns: '{{ ignore_file_paths }}'

  # Update files in order
  - name: Upgrade each .py file in order
    tools:
      - name: find_files_by_name_with_regex
        arguments:
          find_file_name_pattern: '^(?!.*(__init__)).*\.py$'
        returns: files

      - name: async_each
        items: '{{ files }}'
        each_item:
          item_name: file
          tools:
            - name: make_variable
              arguments:
                value: |
                  Rewrite this Python code for compatibility with Python 3.11. 
                  No new tests or code should be written, only refactor for 3.11 compliance.
                  DO NOT modify comments.
              returns: refactor_prompt

            - name: get_file_context
              arguments:
                path_to_file: '{{ file }}'
                depth: '{{ context_depth }}'
                graph_type: 'embedding'
              returns: file_context

            - name: for_each
              items: '{{ python_upgrade_prompts }}'
              each_item:
                item_name: upgrade_prompt
                tools:
                  - name: edit_file
                    arguments:
                      path_to_file: '{{ file }}'
                      edit_prompt: |
                        '{{ file_context }}'
                        '{{ refactor_prompt }}'
                        '{{ upgrade_prompt }}'

            - name: mark_files_converted_in_context
              arguments:
                old_file_path: '{{ file }}'
                new_file_paths:
                  - '{{ file }}'

  # Run sanity checks
  - name: Verify Migrated Files
    tools:
      - name: find_files_by_name_with_regex
        arguments:
          find_file_name_pattern: '^(?!.*(__init__)).*\.py$'
        returns: files
      - name: for_each
        items: '{{ files }}'
        each_item:
          item_name: file
          tools:
            - name: make_variable
              arguments:
                value: |
                  Ensure this file is valid Python 3.11. Fix only typing or indentation issues if needed.
                  No other changes should be made.
              returns: refactor_prompt

            - name: get_file_context
              arguments:
                path_to_file: '{{ file }}'
                depth: '{{ context_depth }}'
                graph_type: 'embedding'
              returns: file_context

            - name: edit_file
              arguments:
                path_to_file: '{{ file }}'
                edit_prompt: |
                  {{ file_context }}
                  {{ refactor_prompt }}

  # Deal with tools files
  - name: Create or Update .tool-versions file
    tools:
      - name: find_files_by_name_with_regex
        arguments:
          find_file_name_pattern: '\.tool-versions$'
        returns: tools_version_files
      - name: if_else
        condition: '{{ tools_version_files }}'
        if:
          tools:
            - name: edit_file
              arguments:
                path_to_file: '.tool-versions'
                edit_prompt: |
                  Update Python version to 3.11. If needed, use patch version 3.11.8.
        else:
          tools:
            - name: create_file
              arguments:
                path_to_file: '.tool-versions'
                file_contents: 'python 3.11.8'

  # Step 3: Update README.md
  - name: Update README.md
    tools:
      - name: edit_file
        arguments:
          path_to_file: 'README.md'
          modify_with_diff: true
          edit_prompt: |
            Update the README.md file to reflect that the project now requires Python 3.11.

            - **Mention Python 3.11:** Clearly state that Python 3.11 or later is required.
            - **Installation Instructions:** Update installation steps to ensure they specify installing Python 3.11.
            - **Anything else:** Update any other relevant sections of the README.md file to reflect the changes in Python 3.11.

            IMPORTANT: Do not delete anything unrelated to the changes required for Python 3.11!

Last updated