from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

from sqlalchemy import event
from sqlalchemy.schema import FetchedValue
from sqlalchemy.dialects import postgresql as pg

from warehouse import db
from warehouse.databases.mixins import UUIDPrimaryKeyMixin
from warehouse.database.types import CIText


class Project(UUIDPrimaryKeyMixin, db.Model):

    __tablename__ = "projects"

    name = db.Column(CIText, unique=True, nullable=False)
    normalized = db.Column(CIText, unique=True, nullable=False,
                                    server_default=FetchedValue(),
                                    server_onupdate=FetchedValue())

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<Project: {name}>".format(name=self.name)


# Create the Trigger to fill in normalized (TODO: Move this to Alembic?)
event.listen(Project.__table__, "after_create", db.DDL("""
CREATE OR REPLACE FUNCTION normalize_name() RETURNS trigger AS
$body$
BEGIN
    new.normalized = lower(regexp_replace(new.name, '[^A-Za-z0-9.]+', '-'));
    RETURN new;
end;
$body$ LANGUAGE plpgsql;

CREATE TRIGGER %(table)s_normalize_name
BEFORE INSERT OR UPDATE
ON %(table)s
FOR EACH ROW
EXECUTE PROCEDURE normalize_name();
"""))

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

from sqlalchemy.schema import FetchedValue
from sqlalchemy.dialects import postgresql as pg
from sqlalchemy.ext.declarative import declared_attr

from warehouse import db
from warehouse.database.mixins import UUIDPrimaryKeyMixin, TimeStampedMixin
from warehouse.database.schema import TableDDL
from warehouse.database.types import CIText
from warehouse.database.utils import table_args


class Project(UUIDPrimaryKeyMixin, TimeStampedMixin, db.Model):

    __tablename__ = "projects"
    __table_args__ = declared_attr(table_args((
            TableDDL("""
                    CREATE OR REPLACE FUNCTION normalize_name()
                    RETURNS trigger AS $$
                    BEGIN
                        NEW.normalized = lower(regexp_replace(new.name, '[^A-Za-z0-9.]+', '-'));
                        return NEW;
                    END;
                    $$ LANGUAGE plpgsql;

                    CREATE TRIGGER %(table)s_normalize_name
                    BEFORE INSERT OR UPDATE
                    ON %(table)s
                    FOR EACH ROW
                    EXECUTE PROCEDURE normalize_name();
                """),
        )))

    name = db.Column(CIText, unique=True, nullable=False)
    normalized = db.Column(CIText, unique=True, nullable=False,
                                    server_default=FetchedValue(),
                                    server_onupdate=FetchedValue())

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<Project: {name}>".format(name=self.name)

Refactor Project to use new mixins and methods
Refactor Project to use new mixins and methods

  from __future__ import absolute_import
  from __future__ import division
  from __future__ import unicode_literals
  
- from sqlalchemy import event
  from sqlalchemy.schema import FetchedValue
  from sqlalchemy.dialects import postgresql as pg
+ from sqlalchemy.ext.declarative import declared_attr
  
  from warehouse import db
- from warehouse.databases.mixins import UUIDPrimaryKeyMixin
+ from warehouse.database.mixins import UUIDPrimaryKeyMixin, TimeStampedMixin
+ from warehouse.database.schema import TableDDL
  from warehouse.database.types import CIText
+ from warehouse.database.utils import table_args
  
  
- class Project(UUIDPrimaryKeyMixin, db.Model):
+ class Project(UUIDPrimaryKeyMixin, TimeStampedMixin, db.Model):
  
      __tablename__ = "projects"
+     __table_args__ = declared_attr(table_args((
+             TableDDL("""
+                     CREATE OR REPLACE FUNCTION normalize_name()
+                     RETURNS trigger AS $$
+                     BEGIN
+                         NEW.normalized = lower(regexp_replace(new.name, '[^A-Za-z0-9.]+', '-'));
+                         return NEW;
+                     END;
+                     $$ LANGUAGE plpgsql;
+ 
+                     CREATE TRIGGER %(table)s_normalize_name
+                     BEFORE INSERT OR UPDATE
+                     ON %(table)s
+                     FOR EACH ROW
+                     EXECUTE PROCEDURE normalize_name();
+                 """),
+         )))
  
      name = db.Column(CIText, unique=True, nullable=False)
      normalized = db.Column(CIText, unique=True, nullable=False,
                                      server_default=FetchedValue(),
                                      server_onupdate=FetchedValue())
  
      def __init__(self, name):
          self.name = name
  
      def __repr__(self):
          return "<Project: {name}>".format(name=self.name)
  
- 
- # Create the Trigger to fill in normalized (TODO: Move this to Alembic?)
- event.listen(Project.__table__, "after_create", db.DDL("""
- CREATE OR REPLACE FUNCTION normalize_name() RETURNS trigger AS
- $body$
- BEGIN
-     new.normalized = lower(regexp_replace(new.name, '[^A-Za-z0-9.]+', '-'));
-     RETURN new;
- end;
- $body$ LANGUAGE plpgsql;
- 
- CREATE TRIGGER %(table)s_normalize_name
- BEFORE INSERT OR UPDATE
- ON %(table)s
- FOR EACH ROW
- EXECUTE PROCEDURE normalize_name();
- """))
- 
Refactor Project to use new mixins and methods
## Code Before:
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

from sqlalchemy import event
from sqlalchemy.schema import FetchedValue
from sqlalchemy.dialects import postgresql as pg

from warehouse import db
from warehouse.databases.mixins import UUIDPrimaryKeyMixin
from warehouse.database.types import CIText


class Project(UUIDPrimaryKeyMixin, db.Model):

    __tablename__ = "projects"

    name = db.Column(CIText, unique=True, nullable=False)
    normalized = db.Column(CIText, unique=True, nullable=False,
                                    server_default=FetchedValue(),
                                    server_onupdate=FetchedValue())

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<Project: {name}>".format(name=self.name)


# Create the Trigger to fill in normalized (TODO: Move this to Alembic?)
event.listen(Project.__table__, "after_create", db.DDL("""
CREATE OR REPLACE FUNCTION normalize_name() RETURNS trigger AS
$body$
BEGIN
    new.normalized = lower(regexp_replace(new.name, '[^A-Za-z0-9.]+', '-'));
    RETURN new;
end;
$body$ LANGUAGE plpgsql;

CREATE TRIGGER %(table)s_normalize_name
BEFORE INSERT OR UPDATE
ON %(table)s
FOR EACH ROW
EXECUTE PROCEDURE normalize_name();
"""))

## Instruction:
Refactor Project to use new mixins and methods
## Code After:
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

from sqlalchemy.schema import FetchedValue
from sqlalchemy.dialects import postgresql as pg
from sqlalchemy.ext.declarative import declared_attr

from warehouse import db
from warehouse.database.mixins import UUIDPrimaryKeyMixin, TimeStampedMixin
from warehouse.database.schema import TableDDL
from warehouse.database.types import CIText
from warehouse.database.utils import table_args


class Project(UUIDPrimaryKeyMixin, TimeStampedMixin, db.Model):

    __tablename__ = "projects"
    __table_args__ = declared_attr(table_args((
            TableDDL("""
                    CREATE OR REPLACE FUNCTION normalize_name()
                    RETURNS trigger AS $$
                    BEGIN
                        NEW.normalized = lower(regexp_replace(new.name, '[^A-Za-z0-9.]+', '-'));
                        return NEW;
                    END;
                    $$ LANGUAGE plpgsql;

                    CREATE TRIGGER %(table)s_normalize_name
                    BEFORE INSERT OR UPDATE
                    ON %(table)s
                    FOR EACH ROW
                    EXECUTE PROCEDURE normalize_name();
                """),
        )))

    name = db.Column(CIText, unique=True, nullable=False)
    normalized = db.Column(CIText, unique=True, nullable=False,
                                    server_default=FetchedValue(),
                                    server_onupdate=FetchedValue())

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<Project: {name}>".format(name=self.name)
