Table of Contents¶
yalchemy¶
yalchemy is a tool for converting YAML (or Python dictionaries) to SQLAlchemy objects.
Quick Start¶
yalchemy provides the following intermediate yalchemy objects:
Table
- For converting SQLAlchemy Tables.Index
- For converting SQLAlchemy Indexes.ForeignKey
- For converting SQLAlchemy ForeignKeys.UniqueConstraint
- For converting SQLAlchemy UniqueConstraints.CheckConstraint
- For converting SQLAlchemy CheckConstraints.Column
- For converting SQLAlchemy ColumnsTableSet
- A utility for representing a list of SQLAlchemy Tables.
Each of these objects implement the following yalchemy object interface:
-
class
yalchemy.table_structures.
Yalchemy
[source]¶ The base yalchemy object that defines the interface for serialization
-
classmethod
from_sqla
(sqla_obj)[source]¶ Constructs a yalchemy object from a sqlalchemy object
Parameters: sqla_obj – The sqlalchemy object
-
classmethod
from_yaml
(yaml_str, loader_factory=None)[source]¶ Loads a yalchemy object from a yaml string
Parameters: - yaml (str) – The yaml string
- loader_factory (function(stream)) – (optional) constructs a custom PyYaml loader. If not provided and libyaml is installed, it will default to CSafeLoader. If not provided and libyaml is not installed, it will default to SafeLoader.
-
to_dict
()[source]¶ Converts a yalchemy object to a dictionary.
Note
Wrapper around _to_dict that will order the _to_dict returned dict by the __slots__ order in an OrderedDict. Please remember to override
_to_dict
and notto_dict
when subclassing yalchemy.
-
classmethod
With this interface, it’s possible to do the following types of conversions:
import yalchemy
# Create a SQLAlchemy table from a dictionary
table = yalchemy.Table.from_dict({
'name': 'my_table',
'schema': 'schema',
'columns': [
{'name': 'col1', 'datatype': 'varchar', 'format': [123], 'null': '^@'},
{'name': 'col2', 'datatype': 'integer', 'required': True},
{'name': 'col3', 'datatype': 'timestamptz', 'required': True,
'default': {'type': 'function', 'value': 'NOW()'}}
],
'foreign_keys': [
{'column': 'col2', 'remote_table': 'other_table', 'remote_column': 'other_col'}
],
'indexes': [{'columns': ['col1', 'col2']}],
'unique_constraints': [{'columns': ['col3']}],
'primary_keys': ['col2']
}).to_sqla(...)
# Columns, foreign keys, and indexes can also be created / converted in the same way
column = yalchemy.Column.from_dict({
'name': 'col2',
'datatype': 'integer',
'required': True
}).to_sqla(...)
fkey = yalchemy.ForeignKey.from_dict({
'column': 'col2',
'remote_table': 'other_table',
'remote_column': 'other_col'
}).to_sqla(...)
index = yalchemy.Index.from_dict({'columns': ['col1', 'col2']}).to_sqla(...)
In yalchemy, the keys used in the dictionaries in the from_dict
constructors are similar to
the constructor arguments. For example,
# Create a yalchemy column object directly
column = yalchemy.Column(name='col2', remote_table='other_table', remote_column='other_col')
# Create the yalchemy object from a dictionary
column = yalchemy.Column.from_dict({'name': 'col2', 'remote_table': 'other_table', 'remote_column': 'other_col'})
# Convert it to sqlalchemy
column.to_sqla()
When instantiating more complex objects like a Table
, the keys used in the dictionaries are also similar
to the constructor arguments, however, the values are sometimes other yalchemy objects. It is recommended to use
from_dict
constructor when instantiating a yalchemy object whenever possible.
Keep in mind that to_sqla
methods sometimes require additional arguments for conversion. Please consult the
Interface section for details on all of the to_sqla
methods.
Installation¶
yalchemy can be installed with:
pip3 install yalchemy
To improve performance, it is recommended to install LibYAML to leverage the native C implementation of the PyYaml parser.
Interface¶
-
class
yalchemy.
Column
(name, datatype, format_=None, required=False, default=None, doc=None)[source]¶ A yalchemy Column that can be converted to a sqlalchemy Column
-
classmethod
from_dict
(dict_obj)[source]¶ Creates a yalchemy Column from a dictionary.
The dictionary has the following specification:
{ # The name of the column 'name': str(required), # The datatype. Can be any of the postgres datatypes listed # at https://www.postgresql.org/docs/current/static/datatype.html#DATATYPE-TABLE 'datatype': str(required), # The format of the datatype. This is an array of arguments that is passed # into the datatype. For example, a format of [255] for a varchar type would # create a varchar(255) column datatype 'format': list(default=[]), # If the datatype is required. If False, it will be null 'required': bool(default=False), # The database server-side default for the column. Column defaults follow the # specification provided in the `ColumnDefault.from_dict` documentation 'default': dict(optional) }
-
classmethod
-
class
yalchemy.
Index
(columns, name=None)[source]¶ A yalchemy Index that can be converted to a sqlalchemy Index
-
from_dict
(dict_obj)¶ Creates a yalchemy column collection from a dictionary.
The dictionary has the following specification:
{ # The list of column names. If multiple are # provided, a multidimensional index will be created 'columns': list[str](required), # A fixed name for this object # (if not specified, will automatically generate a hashed name) 'name': str(optional) }
-
-
class
yalchemy.
ForeignKey
(column, remote_table, remote_column)[source]¶ A yalchemy ForeignKey that can be converted to a sqlalchemy ForeignKeyIndex
-
classmethod
from_dict
(dict_obj)[source]¶ Creates a yalchemy ForeignKey from a dictionary.
The dictionary has the following specification:
{ # The name of the column 'column': str(required), # The name of the remote table 'remote_table': str(required), # The name of the remote column 'remote_column': str(required), }
Note
The
column
andremote_column
arguments can be list of strings in the case of creating foreign keys on combinations of columns.
-
classmethod
-
class
yalchemy.
UniqueConstraint
(columns, name=None)[source]¶ A yalchemy UniqueConstraint that can be converted to a sqlalchemy UniqueConstraint
-
from_dict
(dict_obj)¶ Creates a yalchemy column collection from a dictionary.
The dictionary has the following specification:
{ # The list of column names. If multiple are # provided, a multidimensional index will be created 'columns': list[str](required), # A fixed name for this object # (if not specified, will automatically generate a hashed name) 'name': str(optional) }
-
-
class
yalchemy.
CheckConstraint
(name, check)[source]¶ A yalchemy CheckConstraint that can be converted to a sqlalchemy CheckConstraint
Note
While other yalchemy objects perform equality comparisons on all attributes of their classes, CheckConstraint does not do comparison on the ‘check’ attribute. This is because Postgres may format the check value when storing it.
-
classmethod
from_dict
(dict_obj)[source]¶ Creates a yalchemy CheckConstraint from a dictionary.
The dictionary has the following specification:
{ # The check is the string of the check we want to # have on the constraint. It should be verbatium # what the check would be in SQL 'name': str(required), 'check': str(required), }
-
classmethod
-
class
yalchemy.
Table
(name, schema, columns=None, foreign_keys=None, primary_keys=None, indexes=None, check_constraints=None, unique_constraints=None, doc=None)[source]¶ A yalchemy Table that can be converted to a sqlalchemy Table
-
classmethod
from_dict
(dict_obj)[source]¶ Creates a yalchemy Table from a dictionary.
The dictionary has the following specification:
{ # The table name 'name': str(required), # The schema 'schema': str(required), # The list of table column dictioniaries. Column dictionaries # follow the specification provided in the `Column.from_dict` documentation 'columns': list[dict](optional), # The list of column foreign key dictionaries. Foreign keys follow the # specification provided in the `ForeignKey.from_dict` documentation 'foreign_keys': list[dict](optional), # The list of index dictionaries. Indexes follow the # specification provided in the `Index.from_dict` documentation 'indexes': list[dict](optional), # The list of column names (as strings) that are primary keys. The unique # constraint is made with the columns in the given order. 'primary_keys': list[str](optional), # The list of unique constraints. Unique constraints follow the # specification provided in the `UniqueConstraint.from_dict` documentation # The list of check constraints. Check constraints follow the # specification provided in the `CheckConstraint.from_dict` documentation 'check_constraints': list[dict](optional) # Documentation for the table. Not read from sqlalchemy objs # or written to them until SA version 1.2 'doc': str(optional) }
A full example of a table looks like this:
{ 'name': 'my_table', 'schema': 'schema', 'doc': 'Some document string' 'columns': [ {'name': 'col1', 'datatype': 'varchar', 'format': [123], 'required': False}, {'name': 'col2', 'datatype': 'integer', 'required': True, 'doc': 'col2 is a good column'}, ], 'foreign_keys': [ {'column': 'col2', 'remote_table': 'other_table', 'remote_column': 'other_col'} ], 'indexes': [{'columns': ['col1', 'col2']}], 'unique_constraints': [{'name': 'my_unique_constraint', 'columns': ['col2']}], 'check_constraints': [{'name': 'my_check', 'check': 'char_length(col1) = col2'}] 'primary_keys': ['col2'] }
-
classmethod
from_sqla
(sqla_obj)[source]¶ Create a yalchemy Table from a sqlalchemy Table.
Parameters: sqla_obj – The sqlalchemy Table object
-
to_sqla
(metadata=None, include_indexes=True)[source]¶ Converts the yalchemy Table to a sqlalchemy Table.
Parameters: - metadata (MetaData) – The sqlalchemy metdata object. If
None
, creates a new sqlalchemy MetaData instance. - include_indexes (bool, default=True) – Include indexes when creating the sqlalchemy Table object
- metadata (MetaData) – The sqlalchemy metdata object. If
-
classmethod
-
class
yalchemy.
TableSet
(tables=None)[source]¶ A yalchemy TableSet that can be converted to a list of sqlalchemy Tables
-
classmethod
from_dict
(dict_obj)[source]¶ Creates a yalchemy TableSet from a dictionary.
The dictionary has the following specification:
{ # The list of table dictionaries. The specification for a table # dictionary can be found in the `Table.from_dict` documentation. 'tables': list[dict](optional) }
-
classmethod
from_sqla
(sqla_objs)[source]¶ Create a yalchemy TableSet from a list of sqlalchemy Tables.
Parameters: sqla_objs (list[Table]) – A list of sqlalchemy tables
-
classmethod
Release Notes¶
0.2.15
------
* SRE-544 Unpin the minor version
0.2.14
------
* [SRE-544] Upgrade the dependency (#17)
0.2.13
------
* update deploy key
0.2.12
------
* respect column ordering in yalchemy indexes and primary keys (#15)
0.2.11
------
* primary keys should be ordered (#13)
0.2.10
------
0.2.9
-----
* [DI-8] Temple update 2018-07-27 (#11)
* [DI-8] Temple update 2018-07-26 (#10)
0.2.8
-----
* Improve yaml loader for Yalchemy.from\_yaml() (#7)
0.2.7
-----
* Fix AUTHORS auto-update by pbr (#5)
0.2.6
-----
* Relax core dependencies and fix AUTHORS (#3)
0.2.5
-----
* Remove temporary README.md which is taking precedence over README.rst (#2)
0.2.4
-----
* Initial open source release of yalchemy (#1)
* first commit
Contributing Guide¶
This project was created using temple. For more information about temple, go to the Temple docs.
Setup¶
Set up your development environment with:
git clone git@github.com:CloverHealth/yalchemy.git
cd yalchemy
make setup
make setup
will setup a virtual environment managed by pyenv and install dependencies.
Note that if you’d like to use something else to manage dependencies other than pyenv, call make dependencies
instead of
make setup
.
Documentation¶
Sphinx documentation can be built with:
make docs
The static HTML files are stored in the docs/_build/html
directory. A shortcut for opening them is:
make open_docs
Releases and Versioning¶
Anything that is merged into the master branch will be automatically deployed to PyPI. Documentation will be published to ReadTheDocs.
The following files will be generated and should not be edited by a user:
ChangeLog
- Contains the commit messages of the releases. Please have readable commit messages in the master branch and squash and merge commits when necessary.AUTHORS
- Contains the contributing authors.version.py
- Automatically updated to include the version string.
This project uses Semantic Versioning through PBR. This means when you make a commit, you can add a message like:
sem-ver: feature, Added this functionality that does blah.
Depending on the sem-ver tag, the version will be bumped in the right way when releasing the package. For more information, about PBR, go the the PBR docs.