Skip to content

Generated migrations are not Python-compliant when names contain hyphens or other invalid identifier characters #167

@Waszker

Description

@Waszker

Description

When generating migrations that include PGGrantTableOp, the code currently derives Python variable names directly from PostgreSQL role names.

Relevant code:

def to_variable_name(self) -> str:
"""A deterministic variable name based on PGFunction's contents"""
schema_name = self.schema.lower()
table_name = self.table.lower()
role_name = self.role.lower()
return f"{schema_name}_{table_name}_{role_name}_{str(self.grant)}".lower()

If a role name contains characters that are invalid in Python identifiers (e.g. hyphens -, spaces, leading digits), the generated migration file becomes invalid Python and raises a syntax error on import.

Example PostgreSQL role:

CREATE ROLE reporting-readonly;

Example generated migration snippet (simplified):

reporting-readonly_grant = alembic_utils.pg_grant_table.PGGrantTableOp(
    role="reporting-readonly",
    ...
)

This results in:

public_table_name_reporting-readonly_... = ...  # invalid Python identifier

Expected behavior

Generated Alembic migration files should always be valid Python, regardless of PostgreSQL role naming conventions.

Actual behavior

Role names are interpolated into Python variable names without sanitization, causing invalid syntax for valid PostgreSQL identifiers.

Suggested approaches

Some possible improvements (happy to submit a PR if direction is agreed):

  1. Sanitize variable names

    • Replace invalid characters with underscores
    • Ensure the identifier does not start with a digit
    • Optionally append a short hash to avoid collisions
  2. Avoid role-derived variable names entirely

    • Use a deterministic but generic naming scheme:

      grant_op_1 = PGGrantTableOp(...)
    • Or generate names based on a hash of the parameters

Environment

  • alembic_utils: current main / commit ccf9be7
  • PostgreSQL: roles with hyphens in name
  • Alembic migrations autogenerated via alembic_utils

Let me know if you’d like me to propose a concrete implementation or tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions