Example #1
0
def codegen(args):

    # Use reflection to fill in the metadata
    engine = create_engine(args.url)

    metadata = MetaData(engine)
    tables = args.tables.split(",") if args.tables else None
    metadata.reflect(engine, args.schema, not args.noviews, tables)
    if db.session.bind.dialect.name == "sqlite":
        # dirty hack for sqlite
        engine.execute("""PRAGMA journal_mode = OFF""")

    # Write the generated model code to the specified file or standard output

    capture = StringIO()
    # outfile = io.open(args.outfile, 'w', encoding='utf-8') if args.outfile else capture # sys.stdout
    generator = CodeGenerator(metadata, args.noindexes, args.noconstraints,
                              args.nojoined, args.noinflect, args.noclasses)
    generator.render(capture)
    generated = capture.getvalue()
    generated = fix_generated(generated)
    if args.outfile:
        outfile = io.open(args.outfile, "w", encoding="utf-8")
        outfile.write(generated)
    return generated
Example #2
0
def main():
    parser = argparse.ArgumentParser(description='Generates SQLAlchemy model code from an existing database.')
    parser.add_argument('url', nargs='?', help='SQLAlchemy url to the database')
    parser.add_argument('--version', action='store_true', help="print the version number and exit")
    parser.add_argument('--schema', help='load tables from an alternate schema')
    parser.add_argument('--tables', help='tables to process (comma-separated, default: all)')
    parser.add_argument('--noviews', action='store_true', help="ignore views")
    parser.add_argument('--noindexes', action='store_true', help='ignore indexes')
    parser.add_argument('--noconstraints', action='store_true', help='ignore constraints')
    parser.add_argument('--nojoined', action='store_true', help="don't autodetect joined table inheritance")
    parser.add_argument('--noinflect', action='store_true', help="don't try to convert tables names to singular form")
    parser.add_argument('--noclasses', action='store_true', help="don't generate classes, only tables")
    parser.add_argument('--alwaysclasses', action='store_true', help="always generate classes")
    parser.add_argument('--nosequences', action='store_true', help="don't auto-generate postgresql sequences")
    parser.add_argument('--outfile', help='file to write output to (default: stdout)')
    args = parser.parse_args()

    if args.version:
        print(sqlacodegen.version)
        return
    if not args.url:
        print('You must supply a url\n', file=sys.stderr)
        parser.print_help()
        return

    engine = create_engine(args.url)
    metadata = MetaData(engine)
    tables = args.tables.split(',') if args.tables else None
    metadata.reflect(engine, args.schema, not args.noviews, tables)
    outfile = codecs.open(args.outfile, 'w', encoding='utf-8') if args.outfile else sys.stdout
    generator = CodeGenerator(metadata, args.noindexes, args.noconstraints, args.nojoined, args.noinflect,
                              args.noclasses, args.alwaysclasses, args.nosequences)
    generator.render(outfile)
Example #3
0
def main():
    parser = argparse.ArgumentParser(
        description='Generates SQLAlchemy model code from an existing database.'
    )
    parser.add_argument('url',
                        nargs='?',
                        help='SQLAlchemy url to the database')
    parser.add_argument('--version',
                        action='store_true',
                        help="print the version number and exit")
    parser.add_argument('--schema',
                        help='load tables from an alternate schema')
    parser.add_argument(
        '--tables', help='tables to process (comma-separated, default: all)')
    parser.add_argument('--noviews', action='store_true', help="ignore views")
    parser.add_argument('--noindexes',
                        action='store_true',
                        help='ignore indexes')
    parser.add_argument('--noconstraints',
                        action='store_true',
                        help='ignore constraints')
    parser.add_argument('--nojoined',
                        action='store_true',
                        help="don't autodetect joined table inheritance")
    parser.add_argument(
        '--noinflect',
        action='store_true',
        help="don't try to convert tables names to singular form")
    parser.add_argument('--noclasses',
                        action='store_true',
                        help="don't generate classes, only tables")
    parser.add_argument('--column_lower',
                        action='store_true',
                        help="generate column lower classes")
    parser.add_argument('--outfile',
                        help='file to write output to (default: stdout)')
    args = parser.parse_args()

    if args.version:
        version = pkg_resources.get_distribution('sqlacodegen').parsed_version
        print(version.public)
        return
    if not args.url:
        print('You must supply a url\n', file=sys.stderr)
        parser.print_help()
        return

    engine = create_engine(args.url)
    metadata = MetaData(engine)
    tables = args.tables.split(',') if args.tables else None
    metadata.reflect(engine, args.schema, not args.noviews, tables)
    outfile = codecs.open(args.outfile, 'w',
                          encoding='utf-8') if args.outfile else sys.stdout
    generator = CodeGenerator(metadata, args.noindexes, args.noconstraints,
                              args.nojoined, args.noinflect, args.noclasses,
                              args.column_lower)
    generator.render(outfile)
Example #4
0
def _gen_models(metadata) -> None:
    """使用sqlacodegen生成sqlalchemy模型
    """

    from sqlacodegen.codegen import CodeGenerator
    generator = CodeGenerator(metadata)
    f = open("sqlalchemy_models.py", "w", encoding="utf-8")
    generator.render(f)
    f.close()
def generate_code(engine, **kwargs):
    """ CodeGenerator.__init__(self, metadata, noindexes=False, noconstraints=False,
                 nojoined=False, noinflect=False, nobackrefs=False,
                 flask=False, ignore_cols=None, noclasses=False, nocomments=False)
    """
    metadata = MetaData()
    metadata.reflect(bind=engine)
    codegen = CodeGenerator(metadata, **kwargs)
    sio = StringIO()
    codegen.render(sio)
    return sio.getvalue()
Example #6
0
def test_table_comment(metadata):
    Table('simple',
          metadata,
          Column('id', INTEGER, primary_key=True),
          comment="this is a 'comment'")

    codegen = CodeGenerator(metadata, noclasses=True)
    code = codegen.render_table(codegen.models[0])
    assert code == """\
t_simple = Table(
    'simple', metadata,
    Column('id', Integer, primary_key=True),
    comment='this is a \\'comment\\''
)
"""
    code = generate_code(metadata)
    assert code == """\
Example #7
0
def sql_backend_file_to_table_upload(upload_form, csvfiles):
    """

    :param upload_form: flask request form
    :param csvfiles: flask request files list
    :return: None. Raises a validation error if there are problems with the formatting
    """
    table_name = sanitize_string(upload_form.get(DATA_SOURCE))
    username = upload_form.get(USERNAME)
    notes = upload_form.get(NOTES)

    csv_sql_creator = CreateTablesFromCSVs(
        current_app.config[SQLALCHEMY_DATABASE_URI])
    data = validate_wizard_upload_submission(table_name=table_name,
                                             csvfiles=csvfiles,
                                             csv_sql_creator=csv_sql_creator)
    (
        upload_id,
        upload_time,
        table_name,
    ) = csv_sql_creator.create_and_fill_new_sql_table_from_df(
        table_name, data, REPLACE)

    # remove any existing metadata for this table name and write a new row
    SqlDataInventory.remove_metadata_rows_for_table_name(table_name)
    SqlDataInventory.write_upload_metadata_row(
        upload_id=upload_id,
        upload_time=upload_time,
        table_name=table_name,
        active=True,
        username=username,
        notes=notes,
    )
    # Generate a new models.py
    # update the metadata to include all tables in the db
    csv_sql_creator.meta.reflect()
    # write the database schema to models.py
    generator = CodeGenerator(csv_sql_creator.meta, noinflect=True)
    # Write the generated model code to the specified file or standard output
    models_filepath = os.path.join(APP_DEPLOY_DATA, "models.py")
    # remove and write new file to trigger file watcher and refresh flask app
    if os.path.exists(models_filepath):
        os.remove(models_filepath)
    with io_open(os.path.join(models_filepath), "w",
                 encoding="utf-8") as outfile:
        generator.render(outfile)
Example #8
0
def main():
    parser = argparse.ArgumentParser(description='Generates SQLAlchemy model code from an existing database.')
    parser.add_argument('url', nargs='?', help='SQLAlchemy url to the database')
    parser.add_argument('--version', action='store_true', help="print the version number and exit")
    parser.add_argument('--schema', help='load tables from an alternate schema')
    parser.add_argument('--tables', help='tables to process (comma-separated, default: all)')
    parser.add_argument('--noviews', action='store_true', help="ignore views")
    parser.add_argument('--noindexes', action='store_true', help='ignore indexes')
    parser.add_argument('--noconstraints', action='store_true', help='ignore constraints')
    parser.add_argument('--nojoined', action='store_true', help="don't autodetect joined table inheritance")
    parser.add_argument('--noinflect', action='store_true', help="don't try to convert tables names to singular form")
    parser.add_argument('--noclasses', action='store_true', help="don't generate classes, only tables")
    parser.add_argument('--outfile', help='file to write output to (default: stdout)')
    parser.add_argument('--nobackrefs', action='store_true', help="don't include backrefs")
    parser.add_argument('--flask', action='store_true', help="use Flask-SQLAlchemy columns")
    parser.add_argument('--ignore-cols', help="Don't check foreign key constraints on specified columns (comma-separated)")
    parser.add_argument('--nocomments', action='store_true', help="don't render column comments")
    args = parser.parse_args()

    if args.version:
        print(sqlacodegen.version)
        return
    if not args.url:
        print('You must supply a url\n', file=sys.stderr)
        parser.print_help()
        return

    engine = create_engine(args.url)
    import_dialect_specificities(engine)
    metadata = MetaData(engine)
    tables = args.tables.split(',') if args.tables else None
    ignore_cols = args.ignore_cols.split(',') if args.ignore_cols else None
    metadata.reflect(engine, args.schema, not args.noviews, tables)
    outfile = codecs.open(args.outfile, 'w', encoding='utf-8') if args.outfile else sys.stdout
    generator = CodeGenerator(metadata, args.noindexes, args.noconstraints,
                              args.nojoined, args.noinflect, args.nobackrefs,
                              args.flask, ignore_cols, args.noclasses, args.nocomments)
    generator.render(outfile)
Example #9
0
def main():
    parser = argparse.ArgumentParser(description='Generates SQLAlchemy model code from an existing database.')
    parser.add_argument('url', nargs='?', help='SQLAlchemy url to the database')
    parser.add_argument('--version', action='store_true', help="print the version number and exit")
    parser.add_argument('--schema', help='load tables from an alternate schema')
    parser.add_argument('--tables', help='tables to process (comma-separated, default: all)')
    parser.add_argument('--noviews', action='store_true', help="ignore views")
    parser.add_argument('--noindexes', action='store_true', help='ignore indexes')
    parser.add_argument('--noconstraints', action='store_true', help='ignore constraints')
    parser.add_argument('--nojoined', action='store_true', help="don't autodetect joined table inheritance")
    parser.add_argument('--noinflect', action='store_true', help="don't try to convert tables names to singular form")
    parser.add_argument('--nobackrefs', action='store_true', help="don't include backrefs")
    parser.add_argument('--flask', action='store_true', help="use Flask-SQLAlchemy columns")
    parser.add_argument('--ignorefk', help="Don't check fk constraints on specified columns (comma-separated)")
    parser.add_argument('--outfile', type=argparse.FileType('w'), default=sys.stdout,
                        help='file to write output to (default: stdout)')
    args = parser.parse_args()

    if args.version:
        print(sqlacodegen.version)
        return
    if not args.url:
        print('You must supply a url\n', file=sys.stderr)
        parser.print_help()
        return

    engine = create_engine(args.url)
    import_dialect_specificities(engine)
    metadata = MetaData(engine)
    tables = args.tables.split(',') if args.tables else None
    fkcols = args.ignorefk.split(',') if args.ignorefk else None
    metadata.reflect(engine, args.schema, not args.noviews, tables)
    generator = CodeGenerator(metadata, args.noindexes, args.noconstraints,
                              args.nojoined, args.noinflect, args.nobackrefs,
                              args.flask, fkcols)
    generator.render(args.outfile)
Example #10
0
def generate_code(metadata, **kwargs):
    codegen = CodeGenerator(metadata, **kwargs)
    sio = StringIO()
    codegen.render(sio)
    return remove_unicode_prefixes(sio.getvalue())
Example #11
0
 def generate_code(self, **kwargs):
     codegen = CodeGenerator(self.metadata, **kwargs)
     sio = StringIO()
     codegen.render(sio)
     return remove_unicode_prefixes(sio.getvalue())
Example #12
0
    def handle(self, *args, **options):

        version = options["version"]

        if not version:
            version = str(int(CONTENT_SCHEMA_VERSION) + 1)

        no_export_schema = version == CURRENT_SCHEMA_VERSION

        app_name = KolibriContentConfig.label

        if not no_export_schema:
            settings.DATABASES["default"] = {
                "ENGINE": "django.db.backends.sqlite3",
                "NAME": ":memory:",
            }
            # Force a reload of the default connection after changing settings.
            del connections["default"]

            settings.INSTALLED_APPS = ("kolibri.core.content.contentschema", )
            apps.app_configs = OrderedDict()
            apps.apps_ready = apps.models_ready = apps.loading = apps.ready = False
            apps.all_models = defaultdict(OrderedDict)
            apps.clear_cache()
            apps.populate(settings.INSTALLED_APPS)
            call_command("makemigrations", app_name, interactive=False)

        call_command("migrate", app_name)

        engine = create_engine(get_default_db_string(),
                               poolclass=SharingPool,
                               convert_unicode=True)

        metadata = MetaData()

        app_config = apps.get_app_config(app_name)
        # Exclude channelmetadatacache in case we are reflecting an older version of Kolibri
        table_names = [
            model._meta.db_table for name, model in app_config.models.items()
            if name != "channelmetadatacache"
        ]
        metadata.reflect(bind=engine, only=table_names)
        Base = prepare_base(metadata, name=version)
        # TODO map relationship backreferences using the django names
        session = sessionmaker(bind=engine, autoflush=False)()

        metadata.bind = engine

        generator = CodeGenerator(metadata,
                                  False,
                                  False,
                                  True,
                                  True,
                                  False,
                                  nocomments=False)

        with io.open(
                SQLALCHEMY_CLASSES_PATH_TEMPLATE.format(
                    name=coerce_version_name_to_valid_module_path(version)),
                "w",
        ) as f:
            generator.render(f)

        # Only do this if we are generating a new export schema version
        if not no_export_schema:

            # Load fixture data into the test database with Django
            call_command("loaddata",
                         "content_import_test.json",
                         interactive=False)

            data = {}

            for table_name, record in Base.classes.items():
                data[table_name] = [
                    get_dict(r) for r in session.query(record).all()
                ]

            data_path = DATA_PATH_TEMPLATE.format(name=version)
            # Handle Python 2 unicode issue by opening the file in binary mode
            # with no encoding as the data has already been encoded
            if sys.version[0] == "2":
                with io.open(data_path, mode="wb") as f:
                    json.dump(data, f)
            else:
                with io.open(data_path, mode="w", encoding="utf-8") as f:
                    json.dump(data, f)

            shutil.rmtree(
                os.path.join(os.path.dirname(__file__),
                             "../../contentschema/migrations"))

            os.system("kolibri manage generate_schema " +
                      CURRENT_SCHEMA_VERSION)
Example #13
0
def main():
    parser = argparse.ArgumentParser(
        description='Generates SQLAlchemy model code from an existing database.'
    )
    parser.add_argument('url',
                        nargs='?',
                        help='SQLAlchemy url to the database')
    parser.add_argument('--version',
                        action='store_true',
                        help="print the version number and exit")
    parser.add_argument('--schema',
                        help='load tables from an alternate schema')
    parser.add_argument(
        '--tables', help='tables to process (comma-separated, default: all)')
    parser.add_argument('--noviews', action='store_true', help="ignore views")
    parser.add_argument('--noindexes',
                        action='store_true',
                        help='ignore indexes')
    parser.add_argument('--noconstraints',
                        action='store_true',
                        help='ignore constraints')
    parser.add_argument('--nojoined',
                        action='store_true',
                        help="don't autodetect joined table inheritance")
    parser.add_argument(
        '--noinflect',
        action='store_true',
        help="don't try to convert tables names to singular form")
    parser.add_argument('--noclasses',
                        action='store_true',
                        help="don't generate classes, only tables")
    parser.add_argument('--outfile',
                        help='file to write output to (default: stdout)')
    parser.add_argument(
        '--table_backref_file',
        help=
        'CSV file with source table, target table, and back relationship name')
    parser.add_argument(
        "--add_version",
        action='store_true',
        help=
        'Adds version to printed model as a constant. Version is found querying the "version" table. There is no current way of modifying this besides chanfing the script.',
    )
    args = parser.parse_args()

    if args.version:
        version = pkg_resources.get_distribution('sqlacodegen').parsed_version
        print(version.public)
        return
    if not args.url:
        print('You must supply a url\n', file=sys.stderr)
        parser.print_help()
        return

    # Use reflection to fill in the metadata
    engine = create_engine(args.url)
    metadata = MetaData(engine)
    session = sessionmaker(bind=engine)()
    tables = args.tables.split(',') if args.tables else None
    metadata.reflect(engine, args.schema, not args.noviews, tables)

    # take care of the backref hack
    backrefs_tables = None
    if args.table_backref_file:
        backref_file = pathlib.Path(args.table_backref_file)
        backrefs_tables = load_backref_csv(backref_file)

    # Check if we need to add the version
    version = None
    if args.add_version:
        version = session.query(metadata.tables["version"]).all()[0][0]

    # Write the generated model code to the specified file or standard output
    outfile = io.open(args.outfile, 'w',
                      encoding='utf-8') if args.outfile else sys.stdout
    generator = CodeGenerator(metadata,
                              args.noindexes,
                              args.noconstraints,
                              args.nojoined,
                              args.noinflect,
                              args.noclasses,
                              backrefs_tables,
                              model_version=version)
    generator.render(outfile)
Example #14
0
def main():
    parser = argparse.ArgumentParser(description='Generates SQLAlchemy model code from an existing database.')
    parser.add_argument('url', nargs='?', help='SQLAlchemy url to the database')
    parser.add_argument('--version', action='store_true', help="print the version number and exit")
    parser.add_argument('--schema', help='load tables from an alternate schema')
    parser.add_argument('--tables', help='tables to process (comma-separated, default: all)')
    parser.add_argument('--noviews', action='store_true', help="ignore views")
    parser.add_argument('--noindexes', action='store_true', help='ignore indexes')
    parser.add_argument('--noconstraints', action='store_true', help='ignore constraints')
    parser.add_argument('--nojoined', action='store_true', help="don't autodetect joined table inheritance")
    parser.add_argument('--noinflect', action='store_true', help="don't try to convert tables names to singular form")
    parser.add_argument('--noclasses', action='store_true', help="don't generate classes, only tables")
    parser.add_argument('--outfile', help='file to write output to (default: stdout)')
    parser.add_argument('--audited', help='comma separated list of audited table names')
    parser.add_argument('--auditall', action='store_true', help='audit all tables')
    parser.add_argument('--relationship', action='append', nargs=4, metavar=('parent', 'child', 'name', 'kwargs'), help='Creates an association with the specified name')
    parser.add_argument('--loginuser', help='Model name that will instantiate the flask-login "UserMixin" (default: none)')
    parser.add_argument('--loginrole', help='Model name that will instantiate the flask-login "UserRole" (default: none)')
    parser.add_argument('--columntype',  action='append', nargs=3, metavar=('table', 'old_type', 'new_type'), help='TODO')
    args = parser.parse_args()

    if args.version:
        version = pkg_resources.get_distribution('sqlacodegen').parsed_version
        print(version.public)
        return
    if not args.url:
        print('You must supply a url\n', file=sys.stderr)
        parser.print_help()
        return
    _relationship = dict()
    _rel_set = set()
    args.relationship = [] if args.relationship is None else args.relationship
    for (key, child, name, kwargs) in args.relationship:
        val = { 'child' : child,
                'name' : name,
                'kwargs' : json.loads(kwargs)
              }
        if not (key in _relationship):
            _relationship[key] = []
        # There must not be conflicts where a table is given
        # forced relationships that share an an attribute name
        if (key, name) in _rel_set:
            raise KeyError(f'Tried to create a forced relationship "{name}" '
                           +f'within {key}, but another forced relationship '
                           +f'exists in {key} with the same name.')
        _rel_set.add((key, name))

        _relationship[key].append(val)
    args.relationship = _relationship
    engine = create_engine(args.url)
    metadata = MetaData(engine)
    tables = args.tables.split(',') if args.tables else None
    metadata.reflect(engine, args.schema, not args.noviews, tables)
    outfile = codecs.open(args.outfile, 'w', encoding='utf-8') if args.outfile else sys.stdout

    if args.audited:
        args.audited = set(args.audited.split(','))

    args.columntype = [] if args.columntype is None else args.columntype

    generator = CodeGenerator(metadata,
                              args.noindexes,
                              args.noconstraints,
                              args.nojoined,
                              args.noinflect,
                              args.noclasses,
                              audited=args.audited,
                              audit_all=args.auditall,
                              flask_login_user=args.loginuser,
                              flask_login_role=args.loginrole,
                              force_relationship=args.relationship,
                              special_column_types=args.columntype)
    generator.render(outfile)
Example #15
0
def main():
    parser = argparse.ArgumentParser(
        description="Generates SQLAlchemy model code from an existing database."
    )
    parser.add_argument("url",
                        nargs="?",
                        help="SQLAlchemy url to the database")
    parser.add_argument("--version",
                        action="store_true",
                        help="print the version number and exit")
    parser.add_argument("--schema",
                        help="load tables from an alternate schema")
    parser.add_argument(
        "--tables", help="tables to process (comma-separated, default: all)")
    parser.add_argument("--noviews", action="store_true", help="ignore views")
    parser.add_argument("--noindexes",
                        action="store_true",
                        help="ignore indexes")
    parser.add_argument("--noconstraints",
                        action="store_true",
                        help="ignore constraints")
    parser.add_argument("--nojoined",
                        action="store_true",
                        help="don't autodetect joined table inheritance")
    parser.add_argument(
        "--noinflect",
        action="store_true",
        help="don't try to convert tables names to singular form")
    parser.add_argument("--noclasses",
                        action="store_true",
                        help="don't generate classes, only tables")
    parser.add_argument("--outfile",
                        help="file to write output to (default: stdout)")
    args = parser.parse_args()

    if args.version:
        version = pkg_resources.get_distribution("sqlacodegen").parsed_version
        print(version.public)
        return
    if not args.url:
        print("You must supply a url\n", file=sys.stderr)
        parser.print_help()
        return

    # Use reflection to fill in the metadata
    engine = create_engine(args.url)
    try:
        # dirty hack for sqlite
        engine.execute("""PRAGMA journal_mode = OFF""")
    except:
        pass
    metadata = MetaData(engine)
    tables = args.tables.split(",") if args.tables else None
    metadata.reflect(engine, args.schema, not args.noviews, tables)

    # Write the generated model code to the specified file or standard output
    outfile = io.open(args.outfile, "w",
                      encoding="utf-8") if args.outfile else sys.stdout
    generator = CodeGenerator(metadata, args.noindexes, args.noconstraints,
                              args.nojoined, args.noinflect, args.noclasses)
    generator.render(outfile)
Example #16
0
def main():
    parser = argparse.ArgumentParser(description='Generates SQLAlchemy model code from an existing database.')
    parser.add_argument('url', nargs='?', help='SQLAlchemy url to the database')
    parser.add_argument('--version', action='store_true', help="print the version number and exit")
    parser.add_argument('--schema', help='load tables from an alternate schema')
    parser.add_argument('--tables', help='tables to process (comma-separated, default: all)')
    parser.add_argument('--noviews', action='store_true', help="ignore views")
    parser.add_argument('--noindexes', action='store_true', help='ignore indexes')
    parser.add_argument('--noconstraints', action='store_true', help='ignore constraints')
    parser.add_argument('--nojoined', action='store_true', help="don't autodetect joined table inheritance")
    parser.add_argument('--noinflect', action='store_true', help="don't try to convert tables names to singular form")
    parser.add_argument('--noclasses', action='store_true', help="don't generate classes, only tables")
    parser.add_argument('--outfile', help='file to write output to (default: stdout)')
    parser.add_argument('--audited', help='comma separated list of audited table names')
    parser.add_argument('--auditall', action='store_true', help='audit all tables')
    parser.add_argument('--relationship', action='append', nargs=3, metavar=('parent', 'child', 'name'), help='Creates an association with the specified name')
    args = parser.parse_args()

    if args.version:
        version = pkg_resources.get_distribution('sqlacodegen').parsed_version
        print(version.public)
        return
    if not args.url:
        print('You must supply a url\n', file=sys.stderr)
        parser.print_help()
        return
    _relationship = dict()
    for rel in args.relationship:
        key = rel[0]
        val = { 'child' : rel[1]
              ,'name' : rel[2]
              }
        if not (key in _relationship):
            _relationship[key] = []
        _relationship[key].append(val)
    args.relationship = _relationship
    engine = create_engine(args.url)
    metadata = MetaData(engine)
    tables = args.tables.split(',') if args.tables else None
    metadata.reflect(engine, args.schema, not args.noviews, tables)
    outfile = codecs.open(args.outfile, 'w', encoding='utf-8') if args.outfile else sys.stdout
    if args.auditall:
        generator = CodeGenerator(metadata,
                                  args.noindexes,
                                  args.noconstraints,
                                  args.nojoined,
                                  args.noinflect,
                                  args.noclasses,
                                  audit_all=args.auditall,
                                  force_relationship=args.relationship)
    elif args.audited:
        generator = CodeGenerator(metadata,
                                  args.noindexes,
                                  args.noconstraints,
                                  args.nojoined,
                                  args.noinflect,
                                  args.noclasses,
                                  audited=set(args.audited.split(',')),
                                  force_relationship=args.relationship)
    else:
        generator = CodeGenerator(metadata,
                                  args.noindexes,
                                  args.noconstraints,
                                  args.nojoined,
                                  args.noinflect,
                                  args.noclasses,
                                  force_relationship=args.relationship)
    generator.render(outfile)