Skip to main content

A tool for concatenating files in topological order

Project description

topcat

topological concatenation of files

Description

topcat is a simple tool to concatenate files in a topological order. It is useful when you have a set of files that depend on each other and you want to concatenate them in the right order.

For my use case this is SQL files.

I like to treat my SQL files as a set of functions and views that depend on each other. I like to keep them in separate files and concatenate them in the right order to create a single file that I can run in my database.

Installation

pip:

pip install topcat

poetry:

poetry add topcat

Usage

The quick version

topcat -i /path/to/input -o /path/to/output.sql

Where /path/to/input is the directory containing the files to concatenate and /path/to/output.sql will be where the concatenated file will be written.

The long version

USAGE:
    topcat [FLAGS] [OPTIONS] --output <FILE>

FLAGS:
        --dry        Only print the output, do not write to file.
    -h, --help       Prints help information
    -V, --version    Prints version information
    -v, --verbose    Print debug information

OPTIONS:
        --comment-str <comment-str>
            The string used to denote a comment. eg '--' [default: --]

        --ensure-each-file-ends-with <ensure-each-file-ends-with-str>
            Add this string to the end of files if it does not exist. eg ';' [default: ;]

    -x, --exclude <PATTERN>...                                           Exclude files matching given glob pattern
        --file-separator-str <file-separator-str>
            Add this between each concatenated file in the output. eg '---' [default:
            ------------------------------------------------------------------------------------------------------------------------]
    -n, --include <PATTERN>...                                           Only include files matching glob pattern
    -i, --input_dir <DIR>...
            Path to directory containing files to be concatenated

    -o, --output <FILE>                                                  Path to generate combined output file

Some quirks here:

  • -i is the input directory. You can have multiple input directories. This is useful if you have a set of files in different directories that depend on each other.
  • -o is the output file. This is where the concatenated file will be written.
  • -x and -n are used to exclude and include files respectively. These are glob patterns. For example -x **/tests/* will exclude all files in any tests directory. -n **/functions/* will only include files in the functions directory. You can use these together to include and exclude files as you need. You can use these multiple times.
  • --comment-str is the string used to denote a comment. This is used to find the name, requires, dropped_by and exists comments in the files. The default is --. In SQL this is -- but in other languages it might be // or #.
  • --ensure-each-file-ends-with is the string to add to the end of each file if it doesn't exist. This is useful for SQL files where you might want to ensure each file ends with a ;. The default is ;.
  • --file-separator-str is the string to add between each concatenated file in the output. The default is a long line of dashes. This is just visually useful to see where one file ends and the next begins.
  • --dry will only print the output, it will not write to the output file.
  • -v will print debug information and a .dot format of the dependency graph.

What a file needs to include to be concatenated

name

The only requirement for a file to be included in the concatenation is that it needs to have a name comment at the top of the file.

This can be anything you want, but it needs to be unique. This is used to define a node in the dependency graph.

For example:

-- name: my_schema

requires

If a file requires another file to be concatenated before it, you can add a requires comment to the file. An alias for requires is dropped_by. I use dropped_by in SQL files for clarity to show that the DDL in the file gets dropped so I don't need to use CREATE OR REPLACE FUNCTION or the like.

For example:

-- name: my_schema.b
-- dropped_by: my_schema
-- requires: my_schema.a

exists

exists is for soft dependencies. For example in plpgsql functions, the body isn't parsed until the function is called. So any dependent objects you can't use requires for, you can use exists to ensure the file is included in the concatenated file but order of creation doesn't matter.

For example:

-- name: my_schema.b
-- dropped_by: my_schema
-- requires: my_schema.a
-- exists: my_schema.c

Example

Lets say you have a directory with the following files:


sql
├── my_other_schema
│ ├── functions
│ │ ├── a.sql
│ │ ├── b.sql
│ │ └── c.sql
│ └── schema.sql
└── my_schema
├── functions
│ └── a.sql
└── schema.sql

And the content of the files is:

sql/my_schema/schema.sql:

-- name: my_schema

DROP SCHEMA IF EXISTS my_schema CASCADE;
CREATE SCHEMA IF NOT EXISTS my_schema;

sql/my_schema/functions/a.sql:

-- name: my_schema.a
-- dropped_by: my_schema

CREATE FUNCTION my_schema.a() RETURNS INT AS
$$
SELECT 1;
$$ LANGUAGE SQL IMMUTABLE
                PARALLEL SAFE;

sql/my_schema/functions/b.sql:

-- name: my_schema.b
-- dropped_by: my_schema
-- requires: my_schema.a

CREATE FUNCTION my_schema.b() RETURNS INT AS
$$
SELECT my_schema.a() + 1
$$ LANGUAGE SQL;

sql/my_schema/functions/c.sql:

-- name: my_schema.c
-- dropped_by: my_schema
-- requires: my_schema.b

CREATE FUNCTION my_schema.c() RETURNS INT AS
$$
SELECT my_schema.b() + 1
$$ LANGUAGE SQL IMMUTABLE
                PARALLEL SAFE;

sql/my_other_schema/schema.sql:

-- name: my_other_schema

DROP SCHEMA IF EXISTS my_schema CASCADE;
CREATE SCHEMA IF NOT EXISTS my_schema;

sql/my_other_schema/functions/a.sql:

-- name: my_other_schema.a
-- dropped_by: my_other_schema
-- requires: my_schema.b

CREATE FUNCTION my_other_schema.a() RETURNS INT AS
$$
SELECT my_schema.b() + 1
$$ LANGUAGE SQL IMMUTABLE
                PARALLEL SAFE;

So the dependency graph looks like:

Now you can run topcat to concatenate the files in the right order:

topcat -i tests/input/sql -o tests/output/sql/output.sql

The content of output.sql will be:

-- This file was generated by topcat. To regenerate run:
--
-- topcat -i tests/input/sql -o tests/output/sql/output.sql -v

------------------------------------------------------------------------------------------------------------------------
-- tests/input/sql/my_other_schema/schema.sql
-- name: my_schema

DROP SCHEMA IF EXISTS my_schema CASCADE;
CREATE SCHEMA IF NOT EXISTS my_schema;

------------------------------------------------------------------------------------------------------------------------
-- tests/input/sql/my_other_schema/functions/a.sql
-- name: my_schema.a
-- dropped_by: my_schema

CREATE FUNCTION my_schema.a() RETURNS INT AS
$$
SELECT 1;
$$ LANGUAGE SQL;

------------------------------------------------------------------------------------------------------------------------
-- tests/input/sql/my_other_schema/functions/b.sql
-- name: my_schema.b
-- dropped_by: my_schema
-- requires: my_schema.a

CREATE FUNCTION my_schema.b() RETURNS INT AS
$$
SELECT my_schema.a() + 1
$$ LANGUAGE SQL;

------------------------------------------------------------------------------------------------------------------------
-- tests/input/sql/my_schema/schema.sql
-- name: my_other_schema

DROP SCHEMA IF EXISTS my_other_schema CASCADE;
CREATE SCHEMA IF NOT EXISTS my_other_schema;

------------------------------------------------------------------------------------------------------------------------
-- tests/input/sql/my_schema/functions/a.sql
-- name: my_other_schema.a
-- dropped_by: my_other_schema
-- requires: my_schema.b

CREATE FUNCTION my_other_schema.a() RETURNS INT AS
$$
SELECT my_schema.b() + 1
$$ LANGUAGE SQL IMMUTABLE
                PARALLEL SAFE;

------------------------------------------------------------------------------------------------------------------------
-- tests/input/sql/my_other_schema/functions/c.sql
-- name: my_schema.c
-- dropped_by: my_schema
-- requires: my_schema.b
-- requires: my_other_schema.a

CREATE FUNCTION my_schema.c() RETURNS INT AS
$$
SELECT my_schema.b() + my_other_schema.a() + 1
$$ LANGUAGE SQL;

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

topcat-0.1.2.tar.gz (115.2 kB view details)

Uploaded Source

Built Distributions

topcat-0.1.2-py3-none-win_arm64.whl (402.3 kB view details)

Uploaded Python 3 Windows ARM64

topcat-0.1.2-py3-none-win_amd64.whl (425.7 kB view details)

Uploaded Python 3 Windows x86-64

topcat-0.1.2-py3-none-win32.whl (411.5 kB view details)

Uploaded Python 3 Windows x86

topcat-0.1.2-py3-none-musllinux_1_2_x86_64.whl (564.1 kB view details)

Uploaded Python 3 musllinux: musl 1.2+ x86-64

topcat-0.1.2-py3-none-musllinux_1_2_i686.whl (570.3 kB view details)

Uploaded Python 3 musllinux: musl 1.2+ i686

topcat-0.1.2-py3-none-musllinux_1_2_armv7l.whl (501.4 kB view details)

Uploaded Python 3 musllinux: musl 1.2+ ARMv7l

topcat-0.1.2-py3-none-musllinux_1_2_aarch64.whl (517.4 kB view details)

Uploaded Python 3 musllinux: musl 1.2+ ARM64

topcat-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (517.1 kB view details)

Uploaded Python 3 manylinux: glibc 2.17+ x86-64

topcat-0.1.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (604.2 kB view details)

Uploaded Python 3 manylinux: glibc 2.17+ s390x

topcat-0.1.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (653.7 kB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ppc64le

topcat-0.1.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl (673.4 kB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ppc64

topcat-0.1.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (562.9 kB view details)

Uploaded Python 3 manylinux: glibc 2.17+ i686

topcat-0.1.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (479.5 kB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARMv7l

topcat-0.1.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (483.2 kB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARM64

topcat-0.1.2-py3-none-macosx_10_12_x86_64.whl (502.4 kB view details)

Uploaded Python 3 macOS 10.12+ x86-64

topcat-0.1.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (980.3 kB view details)

Uploaded Python 3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64

File details

Details for the file topcat-0.1.2.tar.gz.

File metadata

  • Download URL: topcat-0.1.2.tar.gz
  • Upload date:
  • Size: 115.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for topcat-0.1.2.tar.gz
Algorithm Hash digest
SHA256 812aab5e2465b079f1eda38695149fc6207b804dad140243cd5bd73cca71a8e7
MD5 16d2ccec5a163aeed911a0ef34d88078
BLAKE2b-256 e1a926990ea2f3042d2e4efa21f146ffc21aeaebbe67ffd8d0f8abb3dd4ef8c4

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-win_arm64.whl.

File metadata

  • Download URL: topcat-0.1.2-py3-none-win_arm64.whl
  • Upload date:
  • Size: 402.3 kB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for topcat-0.1.2-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 e886d83d934ea99037b4535f28ebd48c135ed74e33592a0bca573b63847d51a2
MD5 aefc0a503fb2d465cfab34a68e185e54
BLAKE2b-256 70b807c571d2a44744c4b2abc64c2a21da541f48f75e8004dcd05be94f67ea5b

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-win_amd64.whl.

File metadata

  • Download URL: topcat-0.1.2-py3-none-win_amd64.whl
  • Upload date:
  • Size: 425.7 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for topcat-0.1.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 3e74ed01794edebf7db50873ab4dd0505a4bb7e39ad4afc1482c4115008f4a48
MD5 7f836932671e9fc3664aabdab534ce8d
BLAKE2b-256 98c1563a99311487c2c0d1574d42369b2d5b955bc73f6cac0f2db53e08bf6515

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-win32.whl.

File metadata

  • Download URL: topcat-0.1.2-py3-none-win32.whl
  • Upload date:
  • Size: 411.5 kB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for topcat-0.1.2-py3-none-win32.whl
Algorithm Hash digest
SHA256 3149b6e7182cf7176b446b576cd8e1b866fa1020c4d94a94972b5e982c4b9b08
MD5 833a362d4372dc1a6e0ad3f623fb254b
BLAKE2b-256 80ab4d492c829072849f240517f44fdb1c3e921c6bffb3259c0ea94ae3722c89

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 ce5ca0ba63520dfe366bafc41eff71c093820def82428b074fb1d72a6dcd8ca3
MD5 491d551d80f630e38eca74354ed203d4
BLAKE2b-256 4c7535e6dc868b61b6ce2e66fbb42d811ef34af99f6e301e88eb255bc483a8d2

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 d01d05c847a97643610bad3e6bfa4fa62c97f13585c27b79d8384060e433c119
MD5 41b623e8a1ba0b52ff6f3dc78408cbed
BLAKE2b-256 1ad36c536d5d63c8d53dc00d04af8c3bcc11badf7f9417dfd2193f63d8ad6b7b

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 887eb4086fda17d7d14cbb0659223ecdd3bd235119cd19cf8d9c440500554ac4
MD5 5db7d056479889bce90fe2715bf90ee8
BLAKE2b-256 8d0d9f6549190c627e99e9117d87475fd195a1125246f3f680a7b0abd7d6eb1b

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 17976f07e6a3586c8f2749e9b27ebbc0bce9d7e1e335948443ac1046f92e8292
MD5 d495140e5de9db37b05efc40b1963956
BLAKE2b-256 5d1fda7057059a6c6a79776f56eb0d57bac66216356d0c19cb47b04ba939603f

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f34e61a13576eef37b32981fa64ee5d3a666988e7e939ee4c12a0e295c6cb9bc
MD5 e58ecc83885982ea796e6ebca9fe3531
BLAKE2b-256 a072c70e25af6aea8fb77133ba240e341b6f7c57aa82e7263d0090dea2f675a6

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 eab20d2eed818968a3711e5dd9bca47369b349c46889e3dee82ea233dcd5c7c0
MD5 69d3c6c82b5a4009b9cc1d5827559515
BLAKE2b-256 eb3560ce0a09d3e0b045e9c40c62c2e53f347eff0fa5d915a5038a2fe13ce236

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 ff4f3b0fd77c953f601fe2d4e01f2f8c113bdc6275695c48f2bdcb309491171e
MD5 8763cf5b06e94e1bdbfb8850fa49ffcd
BLAKE2b-256 577eee89e565fd77c0d487e7ced07e40838af0cd61e634d96f462c61c6f9d900

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
Algorithm Hash digest
SHA256 c9da09281175b486888d60c58296745181bf0abd020230a7fc9d98ae436a254d
MD5 f07a621e63ca8a0e27751af1484de28e
BLAKE2b-256 8192bdfc99dba2dfbbc00c05270c2f45986b5e4504ca7b8b8bf24bfa5b0ca071

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 f8563a6e1b01cac8f9667af850caf7b79d2ef91ed3d2a4d5d00c9161ff695276
MD5 1e5e738e940ca675e8bc381010a6546b
BLAKE2b-256 6e66755c551a3cd3ea300f3bff4f674e67e1ca698f20423e637f43c2b5321bf9

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 e0098db0f63ed7d1eba3765580d463509ba9cd47967a16dc9cb88b517f6ddbe4
MD5 8cef727468308d25bfe145a3e09fdaaf
BLAKE2b-256 38fb5a495f3df4d7861cceae56d7708affcb64bff23fbb2e765df99ae2763fd2

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 fb99e1f7ef0c08e9246a48beab0fb4c0f64913aaa2b9fcb7149bf14072cb11f9
MD5 d0126f31f633b3c8f3117cc195d566c4
BLAKE2b-256 7130f4522f829d3487f1f030c04a34b8150caaa28d1add8b067f8c37b04cf9f1

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 2d0dd9e52defb5d90d4a666fa07934b1ac6052e568acd7ecba6ec35e70adff7a
MD5 2ee819d989f4d97edd0d1e97b1442a44
BLAKE2b-256 18bd9b32d5b712281061bdef40c181e536aa0b7f3a9834c29f91ebbe36873208

See more details on using hashes here.

File details

Details for the file topcat-0.1.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for topcat-0.1.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 c477956bba53242add7958ff3be20ff56631ad72c2218789a5cc9d1493c57dca
MD5 7142678ce9a20609e116a0901e896393
BLAKE2b-256 a0693c70f1e21971619a4f17f28446ee4afa8eac7cc1daf9bcaaa2b8b87bb8c4

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page