Skip to content

Schema

pelican.schema.helpers.TableBuilder

TableBuilder(table_name, metadata, primary_key=True, table=None)
Source code in pelican/schema/helpers.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def __init__(
    self,
    table_name: str,
    metadata: MetaData,
    primary_key: bool = True,
    table: Table | None = None,
) -> None:
    self.table_name = table_name
    self.metadata = metadata
    self.table = table if table is not None else Table(self.table_name, metadata)

    self._is_existing_table = table is not None
    self.operations: list[Operation] = []

    if primary_key and not self._is_existing_table:
        self.integer("id", primary_key=True, autoincrement=True)

table_name instance-attribute

table_name = table_name

metadata instance-attribute

metadata = metadata

table instance-attribute

table = table if table is not None else Table(table_name, metadata)

operations instance-attribute

operations = []

column

column(name, type_, *args, **kwargs)
Source code in pelican/schema/helpers.py
53
54
55
56
57
58
59
def column(self, name: str, type_: _T, *args: Any, **kwargs: Any) -> None:
    column_ = Column(name, type_, *args, **kwargs)
    # TODO: Add Column class for the builder which would then be used to build the SA Column in the compiler
    self.table.append_column(column_, replace_existing=True)

    if self._is_existing_table:
        self.operations.append(AddColumn(self.table_name, column_))

alter

alter(name, **kwargs)
Source code in pelican/schema/helpers.py
61
62
63
64
def alter(self, name: str, **kwargs: Any) -> None:
    if not self._is_existing_table:
        raise ValueError("alter can only be used on existing table")
    self.operations.append(AlterColumn(self.table_name, name, **kwargs))

rename

rename(old_name, new_name)
Source code in pelican/schema/helpers.py
66
67
68
69
def rename(self, old_name: str, new_name: str) -> None:
    if not self._is_existing_table:
        raise ValueError("rename can only be used on existing table")
    self.operations.append(RenameColumn(self.table_name, old_name, new_name))

drop

drop(name)
Source code in pelican/schema/helpers.py
71
72
73
74
def drop(self, name: str) -> None:
    if not self._is_existing_table:
        raise ValueError("drop can only be used on existing table")
    self.operations.append(DropColumn(self.table_name, name))

integer

integer(name, *args, **kwargs)
Source code in pelican/schema/helpers.py
76
77
def integer(self, name: str, *args: Any, **kwargs: Any) -> None:
    self.column(name, Integer, *args, **kwargs)

float

float(name, *args, **kwargs)
Source code in pelican/schema/helpers.py
79
80
def float(self, name: str, *args: Any, **kwargs: Any) -> None:
    self.column(name, Float, *args, **kwargs)

double

double(name, *args, **kwargs)
Source code in pelican/schema/helpers.py
82
83
def double(self, name: str, *args: Any, **kwargs: Any) -> None:
    self.column(name, Double, *args, **kwargs)

boolean

boolean(name, *args, **kwargs)
Source code in pelican/schema/helpers.py
85
86
def boolean(self, name: str, *args: Any, **kwargs: Any) -> None:
    self.column(name, Boolean, *args, **kwargs)

string

string(name, length=255, *args, **kwargs)
Source code in pelican/schema/helpers.py
88
89
def string(self, name: str, length: int = 255, *args: Any, **kwargs: Any) -> None:
    self.column(name, String(length), *args, **kwargs)

text

text(name, *args, **kwargs)
Source code in pelican/schema/helpers.py
91
92
def text(self, name: str, *args: Any, **kwargs: Any) -> None:
    self.column(name, Text, *args, **kwargs)

datetime

datetime(name, *args, **kwargs)
Source code in pelican/schema/helpers.py
94
95
96
def datetime(self, name: str, *args: Any, **kwargs: Any) -> None:
    default = kwargs.pop("default", func.now())
    self.column(name, DateTime, default=default, *args, **kwargs)

timestamps

timestamps()
Source code in pelican/schema/helpers.py
 98
 99
100
def timestamps(self) -> None:
    self.datetime("created_at", nullable=False)
    self.datetime("updated_at", onupdate=func.now(), nullable=False)

references

references(model_name, on_delete='CASCADE', **kwargs)
Source code in pelican/schema/helpers.py
102
103
104
105
106
107
108
109
110
111
112
113
114
def references(
    self, model_name: str, on_delete: str = "CASCADE", **kwargs: Any
) -> None:
    self.table.append_column(
        Column(
            f"{model_name}_id",
            Integer,
            ForeignKey(
                f"{inflection.pluralize(model_name)}.id", ondelete=on_delete
            ),
            **kwargs,
        )
    )

index

index(column_names, *, name=None, unique=False)
Source code in pelican/schema/helpers.py
116
117
118
119
120
121
122
123
124
125
126
127
def index(
    self, column_names: list[str], *, name: str | None = None, unique: bool = False
) -> None:
    if not column_names:
        raise ValueError("At least one column name is required for an index")

    if name is None:
        name = f"{self.table_name}_{'_'.join(column_names)}_idx"

    self.operations.append(
        CreateIndex(self.table_name, name, column_names, unique=unique)
    )

add_foreign_key

add_foreign_key(columns, ref_table, ref_columns, *, name=None, on_delete=None)
Source code in pelican/schema/helpers.py
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
def add_foreign_key(
    self,
    columns: list[str],
    ref_table: str,
    ref_columns: list[str],
    *,
    name: str | None = None,
    on_delete: str | None = None,
) -> None:
    self.operations.append(
        AddForeignKeyConstraint(
            self.table_name,
            columns=columns,
            ref_table=ref_table,
            ref_columns=ref_columns,
            constraint_name=name,
            on_delete=on_delete,
        )
    )

remove_foreign_key

remove_foreign_key(*, name)
Source code in pelican/schema/helpers.py
149
150
def remove_foreign_key(self, *, name: str) -> None:
    self.operations.append(DropForeignKeyConstraint(self.table_name, name))

remove_index

remove_index(column_names=None, *, name=None)
Source code in pelican/schema/helpers.py
152
153
154
155
156
157
158
159
160
161
162
163
def remove_index(
    self, column_names: list[str] | None = None, *, name: str | None = None
) -> None:
    if not self._is_existing_table:
        raise ValueError("remove_index can only be used on existing table")

    if not name:
        if not column_names:
            raise ValueError("At least one column name is required for an index")
        name = f"{self.table_name}_{'_'.join(column_names)}_idx"

    self.operations.append(RemoveIndex(self.table_name, name))

pelican.schema.helpers.create_table

create_table(table_name, primary_key=True)

Create a new table

Example

from pelican import create_table


@migration.up()
def upgrade():
    with create_table('spaceships') as t:
        t.string('name', nullable=False)
        t.string('designation', nullable=False)
        t.integer('crew_capacity', default=1)
        t.timestamps()
Source code in pelican/schema/helpers.py
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
@contextmanager
def create_table(table_name: str, primary_key: bool = True) -> Iterator[TableBuilder]:
    """Create a new table

    ## Example

    ```python
    from pelican import create_table


    @migration.up()
    def upgrade():
        with create_table('spaceships') as t:
            t.string('name', nullable=False)
            t.string('designation', nullable=False)
            t.integer('crew_capacity', default=1)
            t.timestamps()
    ```
    """
    runner = get_runner()
    builder = TableBuilder(table_name, runner.metadata, primary_key=primary_key)
    yield builder

    with runner.engine.connect() as conn:
        with conn.begin():
            builder.table.create(conn, checkfirst=True)

    runner.execute_operations(builder.operations)

pelican.schema.helpers.change_table

change_table(table_name)

Modify an existing table

Example

from pelican import change_table


@migration.up()
def upgrade():
    with change_table('spaceships') as t:
        t.string('name', nullable=False) # add column
        t.alter('name', nullable=True) # alter column
        t.rename('name', 'new_name') # rename column
        t.drop('new_name') # drop column
Source code in pelican/schema/helpers.py
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
@contextmanager
def change_table(table_name: str) -> Iterator[TableBuilder]:
    """Modify an existing table

    ## Example

    ```python
    from pelican import change_table


    @migration.up()
    def upgrade():
        with change_table('spaceships') as t:
            t.string('name', nullable=False) # add column
            t.alter('name', nullable=True) # alter column
            t.rename('name', 'new_name') # rename column
            t.drop('new_name') # drop column
    ```
    """
    runner = get_runner()
    table = Table(
        table_name, runner.metadata, autoload_with=runner.engine, extend_existing=True
    )

    builder = TableBuilder(table_name, runner.metadata, table=table)
    yield builder

    runner.execute_operations(builder.operations)

pelican.schema.helpers.drop_table

drop_table(table_name)

Drop an existing table

Example

from pelican import drop_table


@migration.down()
def downgrade():
    drop_table('spaceships')
Source code in pelican/schema/helpers.py
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
def drop_table(table_name: str) -> None:
    """Drop an existing table

    ## Example

    ```python
    from pelican import drop_table


    @migration.down()
    def downgrade():
        drop_table('spaceships')
    ```
    """
    runner = get_runner()

    with runner.engine.connect() as conn:
        with conn.begin():
            table = Table(table_name, runner.metadata, autoload_with=runner.engine)
            table.drop(conn)