# Buggy code
def parse_args(args):
    p = DBTArgumentParser(
        prog="dbt",
        description="""
        An ELT tool for managing your SQL transformations and data models.
        For more documentation on these commands, visit: docs.getdbt.com
        """,
        epilog="""
        Specify one of these sub-commands and you can find more help from
        there.
        """,
    )

    p.add_argument(
        "--version",
        action="dbtversion",
        help="""
        Show version information
        """,
    )

    p.add_argument(
        "-r",
        "--record-timing-info",
        default=None,
        type=str,
        help="""
        When this option is passed, dbt will output low-level timing stats to
        the specified file. Example: `--record-timing-info output.profile`
        """,
    )

    p.add_argument(
        "-d",
        "--debug",
        action="store_true",
        help="""
        Display debug logging during dbt execution. Useful for debugging and
        making bug reports.
        """,
    )

    p.add_argument(
        "--no-write-json",
        action="store_false",
        dest="write_json",
        help="""
        If set, skip writing the manifest and run_results.json files to disk
        """,
    )

    p.add_argument(
        "-S",
        "--strict",
        action="store_true",
        help="""
        Run schema validations at runtime. This will surface bugs in dbt, but
        may incur a performance penalty.
        """,
    )

    p.add_argument(
        "--warn-error",
        action="store_true",
        help="""
        If dbt would normally warn, instead raise an exception. Examples
        include --models that selects nothing, deprecations, configurations
        with no associated models, invalid test configurations, and missing
        sources/refs in tests.
        """,
    )

    p.add_argument(
        "--partial-parse",
        action="store_true",
        help="""
        Allow for partial parsing by looking for and writing to a pickle file
        in the target directory.

        WARNING: This can result in unexpected behavior if you use env_var()!
        """,
    )

    # if set, run dbt in single-threaded mode: thread count is ignored, and
    # calls go through `map` instead of the thread pool. This is useful for
    # getting performance information about aspects of dbt that normally run in
    # a thread, as the profiler ignores child threads. Users should really
    # never use this.
    p.add_argument(
        "--single-threaded",
        action="store_true",
        help=argparse.SUPPRESS,
    )

    # if set, extract all models and blocks with the jinja block extractor, and
    # verify that we don't fail anywhere the actual jinja parser passes. The
    # reverse (passing files that ends up failing jinja) is fine.
    p.add_argument("--test-new-parser", action="store_true", help=argparse.SUPPRESS)

    subs = p.add_subparsers(title="Available sub-commands")

    base_subparser = _build_base_subparser()

    # make the subcommands that have their own subcommands
    docs_sub = _build_docs_subparser(subs, base_subparser)
    docs_subs = docs_sub.add_subparsers(title="Available sub-commands")
    source_sub = _build_source_subparser(subs, base_subparser)
    source_subs = source_sub.add_subparsers(title="Available sub-commands")

    _build_init_subparser(subs, base_subparser)
    _build_clean_subparser(subs, base_subparser)
    _build_debug_subparser(subs, base_subparser)
    _build_deps_subparser(subs, base_subparser)
    _build_list_subparser(subs, base_subparser)

    snapshot_sub = _build_snapshot_subparser(subs, base_subparser)
    rpc_sub = _build_rpc_subparser(subs, base_subparser)
    run_sub = _build_run_subparser(subs, base_subparser)
    compile_sub = _build_compile_subparser(subs, base_subparser)
    generate_sub = _build_docs_generate_subparser(docs_subs, base_subparser)
    test_sub = _build_test_subparser(subs, base_subparser)
    # --threads, --no-version-check
    _add_common_arguments(run_sub, compile_sub, generate_sub, test_sub, rpc_sub)
    # --models, --exclude
    _add_selection_arguments(run_sub, compile_sub, generate_sub, test_sub)
    _add_selection_arguments(snapshot_sub, models_name="select")
    # --full-refresh
    _add_table_mutability_arguments(run_sub, compile_sub)

    _build_seed_subparser(subs, base_subparser)
    _build_docs_serve_subparser(docs_subs, base_subparser)
    _build_source_snapshot_freshness_subparser(source_subs, base_subparser)
    _build_run_operation_subparser(subs, base_subparser)

    if len(args) == 0:
        p.print_help()
        sys.exit(1)

    parsed = p.parse_args(args)
    parsed.profiles_dir = os.path.expanduser(parsed.profiles_dir)

    if not hasattr(parsed, "which"):
        # the user did not provide a valid subcommand. trigger the help message
        # and exit with a error
        p.print_help()
        p.exit(1)

    return parsed


# Traceback (FileNotFoundError)
2019-09-04 16:36:25,854704 (MainThread): Acquiring new postgres connection "seedtable".
2019-09-04 16:36:25,854894 (MainThread): Re-using an available connection from the pool (formerly model_2).
2019-09-04 16:36:25,963811 (MainThread): Unhandled error while executing seed.minimal.seedtable
[Errno 2] No such file or directory: 'data/seedtable.csv'
2019-09-04 16:36:25,964249 (MainThread):
Traceback (most recent call last):
File "/Users/jake/src/fishtown/dbt/core/dbt/node_runners.py", line 203, in safe_run
result = self.compile_and_execute(manifest, ctx)
File "/Users/jake/src/fishtown/dbt/core/dbt/node_runners.py", line 146, in compile_and_execute
result = self.run(ctx.node, manifest)
File "/Users/jake/src/fishtown/dbt/core/dbt/node_runners.py", line 245, in run
return self.execute(compiled_node, manifest)
File "/Users/jake/src/fishtown/dbt/core/dbt/node_runners.py", line 357, in execute
materialization_macro.generator(context)()
File "/Users/jake/src/fishtown/dbt/core/dbt/clients/jinja.py", line 127, in call
return macro(*args, **kwargs)
File "/Users/jake/.pyenv/versions/3.6.5/envs/dbt36/lib/python3.6/site-packages/jinja2/runtime.py", line 575, in __call__
return self._invoke(arguments, autoescape)
File "/Users/jake/.pyenv/versions/3.6.5/envs/dbt36/lib/python3.6/site-packages/jinja2/asyncsupport.py", line 110, in _invoke
return original_invoke(self, arguments, autoescape)
File "/Users/jake/.pyenv/versions/3.6.5/envs/dbt36/lib/python3.6/site-packages/jinja2/runtime.py", line 579, in _invoke
rv = self._func(*arguments)
File "<template>", line 346, in macro
File "/Users/jake/.pyenv/versions/3.6.5/envs/dbt36/lib/python3.6/site-packages/jinja2/sandbox.py", line 438, in call
return __context.call(__obj, *args, **kwargs)
File "/Users/jake/.pyenv/versions/3.6.5/envs/dbt36/lib/python3.6/site-packages/jinja2/runtime.py", line 262, in call
return __obj(*args, **kwargs)
File "/Users/jake/src/fishtown/dbt/core/dbt/context/common.py", line 364, in load_agate_table
table = dbt.clients.agate_helper.from_csv(path)
File "/Users/jake/src/fishtown/dbt/core/dbt/clients/agate_helper.py", line 65, in from_csv
with open(abspath, encoding='utf-8') as fp:
FileNotFoundError: [Errno 2] No such file or directory: 'data/seedtable.csv'

# Fixed code
def parse_args(args):
    p = DBTArgumentParser(
        prog="dbt",
        description="""
        An ELT tool for managing your SQL transformations and data models.
        For more documentation on these commands, visit: docs.getdbt.com
        """,
        epilog="""
        Specify one of these sub-commands and you can find more help from
        there.
        """,
    )

    p.add_argument(
        "--version",
        action="dbtversion",
        help="""
        Show version information
        """,
    )

    p.add_argument(
        "-r",
        "--record-timing-info",
        default=None,
        type=str,
        help="""
        When this option is passed, dbt will output low-level timing stats to
        the specified file. Example: `--record-timing-info output.profile`
        """,
    )

    p.add_argument(
        "-d",
        "--debug",
        action="store_true",
        help="""
        Display debug logging during dbt execution. Useful for debugging and
        making bug reports.
        """,
    )

    p.add_argument(
        "--no-write-json",
        action="store_false",
        dest="write_json",
        help="""
        If set, skip writing the manifest and run_results.json files to disk
        """,
    )

    p.add_argument(
        "-S",
        "--strict",
        action="store_true",
        help="""
        Run schema validations at runtime. This will surface bugs in dbt, but
        may incur a performance penalty.
        """,
    )

    p.add_argument(
        "--warn-error",
        action="store_true",
        help="""
        If dbt would normally warn, instead raise an exception. Examples
        include --models that selects nothing, deprecations, configurations
        with no associated models, invalid test configurations, and missing
        sources/refs in tests.
        """,
    )

    p.add_argument(
        "--partial-parse",
        action="store_true",
        help="""
        Allow for partial parsing by looking for and writing to a pickle file
        in the target directory.

        WARNING: This can result in unexpected behavior if you use env_var()!
        """,
    )

    # if set, run dbt in single-threaded mode: thread count is ignored, and
    # calls go through `map` instead of the thread pool. This is useful for
    # getting performance information about aspects of dbt that normally run in
    # a thread, as the profiler ignores child threads. Users should really
    # never use this.
    p.add_argument(
        "--single-threaded",
        action="store_true",
        help=argparse.SUPPRESS,
    )

    # if set, extract all models and blocks with the jinja block extractor, and
    # verify that we don't fail anywhere the actual jinja parser passes. The
    # reverse (passing files that ends up failing jinja) is fine.
    p.add_argument("--test-new-parser", action="store_true", help=argparse.SUPPRESS)

    subs = p.add_subparsers(title="Available sub-commands")

    base_subparser = _build_base_subparser()

    # make the subcommands that have their own subcommands
    docs_sub = _build_docs_subparser(subs, base_subparser)
    docs_subs = docs_sub.add_subparsers(title="Available sub-commands")
    source_sub = _build_source_subparser(subs, base_subparser)
    source_subs = source_sub.add_subparsers(title="Available sub-commands")

    _build_init_subparser(subs, base_subparser)
    _build_clean_subparser(subs, base_subparser)
    _build_debug_subparser(subs, base_subparser)
    _build_deps_subparser(subs, base_subparser)
    _build_list_subparser(subs, base_subparser)

    snapshot_sub = _build_snapshot_subparser(subs, base_subparser)
    rpc_sub = _build_rpc_subparser(subs, base_subparser)
    run_sub = _build_run_subparser(subs, base_subparser)
    compile_sub = _build_compile_subparser(subs, base_subparser)
    generate_sub = _build_docs_generate_subparser(docs_subs, base_subparser)
    test_sub = _build_test_subparser(subs, base_subparser)
    seed_sub = _build_seed_subparser(subs, base_subparser)
    # --threads, --no-version-check
    _add_common_arguments(
        run_sub, compile_sub, generate_sub, test_sub, rpc_sub, seed_sub
    )
    # --models, --exclude
    _add_selection_arguments(run_sub, compile_sub, generate_sub, test_sub)
    _add_selection_arguments(snapshot_sub, models_name="select")
    # --full-refresh
    _add_table_mutability_arguments(run_sub, compile_sub)

    _build_docs_serve_subparser(docs_subs, base_subparser)
    _build_source_snapshot_freshness_subparser(source_subs, base_subparser)
    _build_run_operation_subparser(subs, base_subparser)

    if len(args) == 0:
        p.print_help()
        sys.exit(1)

    parsed = p.parse_args(args)
    parsed.profiles_dir = os.path.expanduser(parsed.profiles_dir)

    if not hasattr(parsed, "which"):
        # the user did not provide a valid subcommand. trigger the help message
        # and exit with a error
        p.print_help()
        p.exit(1)

    return parsed