Package: records-mover
Records mover is a command-line tool and Python library you can
use to move relational data from one place to another.Relational data here means anything roughly "rectangular" - with
columns and rows.  For example, it supports reading and writing from:Databases, including using native high-speed methods of
import/export of bulk data.  Redshift, Vertica and PostgreSQL are
well-supported, with some support for BigQuery and MySQL.CSV filesParquet files (initial support)Google SheetsPandas DataFramesRecords directories - a structured directory of CSV/Parquet/etc
files containing some JSON metadata about their format and origins.
Records directories are especially helpful for the ever-ambiguous
CSV format, where they solve the problem of 'hey, this may be a
CSV - but what's the schema?  What's the format of the CSV itself?
How is it escaped?'Records mover can be exended expand to handle additional databases
and data file types.  Databases are supported by building on top of
theirSQLAlchemydrivers.  Records
mover is able to auto-negotiate the most efficient way of moving data
from one to the other.CLI use exampleInstalling:pip3install'records_mover[cli,postgres-binary,redshift-binary]'Loading a CSV into a database:mvrecfile2tablefoo.csvredshiftdb1myschema1mytable1Copying a table from a PostgreSQL to a Redshift database:mvrec--help
mvrectable2tablepostgresdb1myschema1mytable1redshiftdb2myschema2mytable2Note records mover will automatically build an appropriateCREATE TABLEstatement on the target end if the table doesn't already exist.Note that the connection details for the database names here must be
configured usingdb-facts.For more installation notes, seeINSTALL.md.  To
understand the security model here, seeSECURITY.md.CLI use demo (table creation and loading)Python library use exampleFirst, install records_mover.  We'll also use Pandas, so we'll install
that, too, as well as a driver for Postgres.pip3installrecords_mover[pandas,postgres-source]Now we can run this code:#!/usr/bin/env python3# Pull in the records-mover library - be sure to run the pip install above first!fromrecords_moverimportsources,targets,movefrompandasimportDataFrameimportsqlalchemyimportossqlalchemy_url=f"postgresql+psycopg2://username:{os.environ['DB_PASSWORD']}@hostname/database_name"db_engine=sqlalchemy.create_engine(sqlalchemy_url)df=DataFrame.from_dict([{'a':1}])# or make your own!source=sources.dataframe(df=df)target=targets.table(schema_name='myschema',table_name='mytable',db_engine=db_engine)results=move(source,target)When moving data, the sources supported can be foundhere,
and the targets supported can be foundhere.Advanced Python library use exampleHere's another example, using some additional features:Loading from an existing dataframe.Secrets management usingdb-facts, which is a way
to configure credentials in YAML files or even fetch them
dynamically from your secrets store.Logging configuration to show the internal processing steps (helpful
in optimizing performance or debugging issues)you can use this:#!/usr/bin/env python3# Pull in the records-mover library - be sure to run the pip install above first!fromrecords_moverimportSessionfrompandasimportDataFramesession=Session()session.set_stream_logging()records=session.recordsdb_engine=session.get_default_db_engine()df=DataFrame.from_dict([{'a':1}])# or make your own!source=records.sources.dataframe(df=df)target=records.targets.table(schema_name='myschema',table_name='mytable',db_engine=db_engine)results=records.move(source,target)Python library API documentationYou can can find more API documentationhere.
In particular, note:Session() constructorsources factory methodstargets factory methodsmove() methodBaseRecordsFormatLocal DevelopmentThe included Dockerfile can be used to build a docker image that is
suitable for local development.dockerbuildDockerfile.dev-trecords-mover:latest.Or, using docker compose,dockercomposebuildThe following commands assume the records-mover container has been
namedrecords-mover.Mount the directory containing your local copy of the repository to
have it override what's in the container.dockerrun-it--mountsrc="$(pwd)/records_mover",target=/records-mover/records_mover,type=bindrecords-moverThis will mount your local src overtop of the same directory in the
container. Mount any additional directories you are working on with
additional --mount entriesAlternatively, you can launch the container using docker-compose.
This will start the container with pre-defined mounts.docker-compose up -dThis will build the container image as necessary, launch it, and
mount the most relevant volumes for local dev.
The container is hosting a bash shell and will run until you
manually shut it down.Note, if you have to add a dependency to requirements.txt and want
to test it locally, add the lineCOPY requirements.txt .afterRUN git clone ...in the Dockerfile and rebuild the container.Working within the containerThe container presumes you're still working with python
virtual environments when working with it. This could possibly
be considered a "hat on a hat" situation.
The practical consequence of this is that if you do open a shell
in the container, ensure you activate thevenvvirtual
environment. Otherwise, you will not have all the dependencies
you'll need.After you've started a shell with thedocker run...command above,
you can activate the virtual environment with:source venv/bin/activateRunning unit and type testsUnit and type tests can be run within the container by running:make citest
make cicoverage
make typecheck
make citypecoverageThe tests can be run from outside the container using docker-compose.dockercomposeruntestIt's theoretically possible to build sufficient additional
containers to support running integration tests locally but
that has not been planned yet.