Issues

Issue #121 new

render correct module prefix when custom types detected

Andrey Petrov
created an issue

I have a custom Enum type that I use which is based on the Integer type: https://gist.github.com/shazow/5478648

When I create a table that uses this type, and use Alembic's autogen to create a migration, it creates a normal Enum type column, rather than Integer that it should.

(This was with Alembic v0.5.0)

Comments (16)

  1. Andrey Petrov reporter

    For the upgrade, it creates something like...

        op.create_table(...
        sa.Column('type', sa.Enum(), nullable=True),
        ...
        )
    

    Whereas it should be sa.Integer().

  2. Mike Bayer repo owner

    why should it be Integer when the type is actually Enum()? your custom type might have behaviors that affect how the Integer is produced. Ultimately it just uses __repr__() so if you want it to come out as Integer, or better yet your Enum() with appropriate arguments, add that to your __repr__().

  3. Mike Bayer repo owner

    Also it shouldn't be doing "sa." there, the "sa." prefix only comes out when it detects that the type's class is actually declared within SQLAlchemy. are you seeing "sa." ?

  4. Andrey Petrov reporter
    1. Are you saying it just derives the type from the classname? So if I called it class Foo, it would think it's type Foo? Either way, this is inconsistent behaviour with SA proper which correctly interprets it as Integer type when doing meta.create_all().

    2. Yes, I'm seeing "sa." on the type (as I copypasta'd the snipped example).

  5. Andrey Petrov reporter

    Ah I did notice that I'm doing super(Enum, self).__init__(), so I can see that it's not just the name that lets it think it might be Enum.

    Basically I want the type to "behave" as an Enum object in Python, but underneath to be an SQL Integer type.

  6. Mike Bayer repo owner

    It will of course emit INTEGER when the create_all() actually emits the SQL. Your Enum() is a TypeDecorator, it only provides Python behavior, which may include how your Integer() type is set up. I have types like "Money", "Percentage", etc. which set up NUMERIC with certain precision/scale so I certainly want to see Money/Percentage types in my migration scripts, I don't see what issue this causes. The alembic create_table() is using Table() internally so I don't see where the opportunity for inconsistency arises here.

    To change how your type comes out in a migration script, you have two options: 1. modify __repr__() or 2. use the render_item argument in your context, see the example at http://alembic.readthedocs.org/en/latest/api.html#alembic.environment.EnvironmentContext.configure .

    as far as the "sa." prefix, I was mistaken on that, we have logic to detect types that are dialect-specific versus in types.py, but currently it doesn't omit "sa." if the type is not part of SQLAlchemy at all. The user-defined type repr() would override this, as well as setting a different sqlalchemy_module_prefix.

  7. Mike Bayer repo owner

    TypeDecorator does use impl to determine the "actual" type, the one that takes place at the SQL/DBAPI level. I'm not sure what the actual problem you're having is.

  8. Andrey Petrov reporter

    Let's call my custom Enum type CustomIntegerEnum.

    When I define a Table with a CustomIntegerEnum column, the following inconsistency happens:

    1. When I use SQLAlchemy meta.create_all(), it creates my column as an Integer type.
    2. If, instead, I use Alembic and autogen a migration, it creates my column as an Enum type.
  9. Mike Bayer repo owner

    I mean that, can be fixed - we detect the types module and all that, it shouldn't be sticking "sa." in there if it knows module is outside of SQLAlchemy.

  10. Andrey Petrov reporter

    Ah, if it was sticking in the correct module prefix, then that would work too.

    I was assuming it had to be an elementary derived type or something.

  11. Log in to comment