# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['dbml_sqlite']

package_data = \
{'': ['*']}

install_requires = \
['click>=8.0.0,<9.0.0', 'pydbml>=0.3.4,<0.4.0']

entry_points = \
{'console_scripts': ['dbml_sqlite = dbml_sqlite.terminal:cli']}

setup_kwargs = {
    'name': 'dbml-sqlite',
    'version': '0.3.0',
    'description': 'A package that provides a CLI tool and a functional API for converting dbml files to SQLite DDL.',
    'long_description': '![DBML_SQLite](https://github.com/dvanderweele/DBML_SQLite/actions/workflows/test.yml/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/dvanderweele/DBML_SQLite/badge.svg?branch=main)](https://coveralls.io/github/dvanderweele/DBML_SQLite?branch=main)\n![PyPI](https://img.shields.io/pypi/v/DBML_SQLite)\n![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/dvanderweele/DBML_SQLite)\n![PyPI -Wheel](https://img.shields.io/pypi/wheel/DBML_SQLite) \n![PyPI -Python Version](https://img.shields.io/pypi/pyversions/DBML_SQLite) \n![License -MIT](https://img.shields.io/badge/License-MIT-blue)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/DBML_SQLite)\n\n# *dbml_sqlite*\n\nThis is a simple package built on top of [the PyDBML package by Vanderhoof](https://github.com/Vanderhoof/PyDBML). It allows you, within certain constraints, to generate valid SQLite from `.dbml` files for your Python programs.\n\n## Installation\n\nYou\'ll need Python 3.7 or higher.\n\n```\npip install dbml_sqlite\n```\n\nOr:\n\n```\npoetry add dbml_sqlite\n```\n\nNote that if you install the tool on your system globally with pip, you should be able to use the CLI anywhere.\n\n## Usage\n\nBasic use case:\n\n```py\nimport sqlite3\nfrom dbml_sqlite import toSQLite\n\nddl = toSQLite(\'dbdiagram.dbml\')\ncon = sqlite3.connect(\'./example.db\')\nwith con:\n    con.executescript(ddl)\ncon.close()\n```\n\nInstead of directly executing the produced SQLite DDL, feel free to write it to a file instead so you can manually inspect or manipulate it. The ddl output is valid SQLite, but it is still just a Python string so you could also programmatically manipulate it or compile it further if needed.\n\nGiven a DBML file, the `toSQLite` function converts the contents to valid SQLite.\n\nParameters:\n\n**dbml (str):** a valid string for converting to a Path object. Should point to a `.dbml` file containing valid DBML *or* a directory containing such files. Default is a period, in which case current working directory will be searched and all such files will be parsed.\n\n**emulation (str):** specifies emulation mode for enum functionality since it is not directly supported by SQLite. Default is "full", and the other option is "half".\n\nReturns:\n**str:** one valid sequence of SQLite syntax.\n\nThere are other functions in the package, but they are intended for internal use only within the package. In-depth coverage of the rest of the API is at the end of this README.\n\n## CLI\n\nAfter installation, you can use the CLI from your terminal as follows:\n\n```\ndbml_sqlite [OPTIONS] SRC\n```\n\nSRC is mandatory and is the file containing dbml you want converted.\n\n| Options | Meaning |\n| :---: | :--- |\n| -p, --print / -n, --no-print | Whether to print output to console.  [default: print] |\n| -w, --write PATH | (Optional) File you want output written to. |\n| -x, --execute PATH | (Optional) SQLite database file for executing output DDL on. Will create file if it doesn\'t exist. |\n| -f, --full / -h, --half | Full emulation mode (separate tables) or half emulation mode (check statements) for any enums defined in your dbml. [default: full] |\n| -t, --if-table-exists | (Optional) Add IF NOT EXISTS language to CREATE TABLE statements. |\n| -i, --if-index-exists | (Optional) Add IF NOT EXISTS language to CREATE INDEX statements. |\n| --help | Show this message and exit. |\n\n## Writing SQLite Compatible DBML\n\nNot all valid DBML will result in valid SQLite. However, this library attempts to coerce commonly used language in DBML for other SQL flavors to compatible SQLite statements. If this is not possible, an error will be raised. \n\nFor best results, it is recommended to stick to the following valid SQLite types, which are shown next to their corresponding Python types:\n\n| SQLite Type | Python Type |\n|     :-:     |     :-:     |\n| NULL        | None        |\n| INTEGER     | int         |\n| REAL        | float       |\n| TEXT        | str         |\n| BLOB        | bytes       |\n\nAny of the Python types above as well as any of the types in the table below, if found in your DBML, will be converted to the corresponding SQLite Type. Note the case insensitivity of the mappings; all types are uppercased for the purposes of comparison.\n\n| Foreign Type | SQLite Type |\n|      :-:     |      :-:    |\n| bool         | INTEGER     |\n| boolean      | INTEGER     |\n| int          | INTEGER     |\n| tinyint      | INTEGER     |\n| smallint     | INTEGER     |\n| mediumint    | INTEGER     |\n| bigint       | INTEGER     |\n| year         | INTEGER     |\n| float        | REAL        |\n| double       | REAL        |\n| decimal      | REAL        |\n| numeric      | REAL        |\n| date         | TEXT        |\n| datetime     | TEXT        |\n| timestamp    | TEXT        |\n| time         | TEXT        | \n| varchar      | TEXT        |\n| tinytext     | TEXT        |\n| mediumtext   | TEXT        |\n| longtext     | TEXT        |\n| tinyblob     | BLOB        |\n| mediumblob   | BLOB        |\n| longblob     | BLOB        |\n| byte         | BLOB        |\n\n## Enums\n\nEnums are an aspect of SQL that is not explicitly supported in SQLite. However, it is possible to emulate the functionality in several ways. [See this stackoverflow discussion for more info](https://stackoverflow.com/questions/5299267/how-to-create-enum-type-in-sqlite#17203007).\n\nBy default, this library will emulate enums that you specify in DBML by creating a separate table. For example, given the following DBML:\n\n```\nenum message_status {\n    unsent\n    pending\n    sent\n    delivered\n    failed\n}\n\nTable message {\n    id integer [primary key]\n    body text [not null]\n    status message_status [not null]\n    contact_id integer [not null]\n}\n\nenum zip_code {\n    920\n    414\n    800\n    900\n    555\n}\n\nTable contact {\n    id integer [primary key]\n    name varchar(0123) [default: "Joe Smith"]\n    phone mediumint [not null]\n    zip zip_code [not null]\n\n    indexes {\n        (name, phone) [name: \'unique_contact\', unique]\n    }\n}\n\nRef: message.contact_id > contact.id [delete: cascade, update: no action]\n```\n\nThe following SQLite will be generated:\n\n```sql\nCREATE TABLE IF NOT EXISTS message_status (\n  id INTEGER PRIMARY KEY,\n  type TEXT NOT NULL UNIQUE,\n  seq INTEGER NOT NULL UNIQUE\n);\nINSERT INTO message_status(type, seq) VALUES (\'unsent\', 1);\nINSERT INTO message_status(type, seq) VALUES (\'pending\', 2);\nINSERT INTO message_status(type, seq) VALUES (\'sent\', 3);\nINSERT INTO message_status(type, seq) VALUES (\'delivered\', 4);\nINSERT INTO message_status(type, seq) VALUES (\'failed\', 5);\n\nCREATE TABLE IF NOT EXISTS zip_code (\n  id INTEGER PRIMARY KEY,\n  type TEXT NOT NULL UNIQUE,\n  seq INTEGER NOT NULL UNIQUE\n);\nINSERT INTO zip_code(type, seq) VALUES (\'920\', 1);\nINSERT INTO zip_code(type, seq) VALUES (\'414\', 2);\nINSERT INTO zip_code(type, seq) VALUES (\'800\', 3);\nINSERT INTO zip_code(type, seq) VALUES (\'900\', 4);\nINSERT INTO zip_code(type, seq) VALUES (\'555\', 5);\n\nCREATE TABLE IF NOT EXISTS message (\n  id INTEGER PRIMARY KEY,\n  body TEXT NOT NULL,\n  status TEXT NOT NULL REFERENCES message_status(type),\n  contact_id INTEGER NOT NULL,\n  FOREIGN KEY(contact_id) REFERENCES contact(id) ON UPDATE NO ACTION ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS contact (\n  id INTEGER PRIMARY KEY,\n  name TEXT DEFAULT \'Joe Smith\',\n  phone INTEGER NOT NULL,\n  zip TEXT NOT NULL REFERENCES zip_code(type)\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS unique_contact ON contact (name, phone);\n```\n\nI refer to this as `full` emulation, and it is the default. The alternative is `half` emulation, and you use it as follows in your Python code:\n\n```py\nfrom dbml_sqlite import toSQLite\noutput = toSQLite(\'dbdiagram.dbml\', emulation="half")\n```\n\nIf used on the DBML above, the following SQLite is produced:\n\n```sql\nCREATE TABLE IF NOT EXISTS message (\n  id INTEGER PRIMARY KEY,\n  body TEXT NOT NULL,\n  status TEXT CHECK( status IN ( \'unsent\', \'pending\', \'sent\', \'delivered\', \'failed\' ) ) NOT NULL,\n  contact_id INTEGER NOT NULL,\n  FOREIGN KEY(contact_id) REFERENCES contact(id) ON UPDATE NO ACTION ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS contact (\n  id INTEGER PRIMARY KEY,\n  name TEXT DEFAULT \'Joe Smith\',\n  phone INTEGER NOT NULL,\n  zip TEXT CHECK( zip IN ( \'920\', \'414\', \'800\', \'900\', \'555\' ) ) NOT NULL\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS unique_contact ON contact (name, phone);\n```\n\nNote that in the case of `full` emulation, you will need to turn on the foreign key constraint as follows:\n\n```py\nconn = sqlite3.connect("default.db")\nconn.execute("PRAGMA foreign_keys = 1")\ncur = conn.cursor()\n```\n\n## Testing and Coverage\n\nAfter all dependencies (including development dependencies) are installed, run the tests:\n\n```bash\npoetry run pytest\n```\n\nAlternatively, run the tests with coverage:\n\n```bash\npoetry run coverage run --source dbml_sqlite -m pytest\n```\n\nView the coverage report:\n\n```bash\npoetry run coverage report -m\n```\n\n## API\n\n### toSQLite\n    \nGiven a DBML file, convert contents to valid SQLite.\n\n**Parameters:**\n+ *dbml (str):* a valid string for converting to a Path object. Should point to a `.dbml` file containing valid DBML *or* a directory containing such files. Default is a period, in which case current working directory will be searched and all such files will be parsed.\n+ *emulation (str):* specifies emulation mode for enum functionality since it is not directly supported by SQLite. Default is "full", and the other option is "half".\n+ *tableExists (bool):* Default is True. If True, all generated `CREATE TABLE` SQLite statements will have `IF NOT EXISTS` language included.\n+ *indexExists (bool):* Default is True. If True, all generated `CREATE INDEX` SQLite statements will have `IF NOT EXISTS` language included.\n+ *join (bool):* Default is True. If True, function will `join` the result list of string segments with an empty string and return the resulting string to you. Otherwise, the one-dimensional list of string segments will be returned to you directly.\n\n**Returns:**\n+ *str or list of str:* a valid sequence of SQLite syntax.\n\n### validDBMLFile\n    \nReturn a boolean indicating whether passed string has valid `.dbml` file extension. Case-sensitive (i.e. `.DBML` not accepted).\n\n**Parameters:**\n+ *s (str):* name of file.\n\n**Returns:**\n+ *bool:* True if s ends with \'.dbml\', else False.\n\n### processFile\n    \nGiven a target `.dbml` file, parse and generate a valid SQLite string.\n\n**Parameters:**\n+ *target (Path):* File with contents to convert to SQLite.\n+ *emulationMode (str):* Specifies "half" or "full" emulation for enum functionality in SQLite.\n+ *tableExists (bool):* Default is True. If True, all generated `CREATE TABLE` SQLite statements will have `IF NOT EXISTS` language included.\n+ *indexExists (bool):* Default is True. If True, all generated `CREATE INDEX` SQLite statements will have `IF NOT EXISTS` language included.\n+ *join (bool):* Default is True. If True, function will `join` the result list of string segments with an empty string and return the resulting string to you. Otherwise, the one-dimensional list of string segments will be returned to you directly.\n\n**Returns:**\n+ *str or list of str:* valid SQLite DDL.\n\n### processIndex\n\nGiven objects produced by the PyDBML library (or appropriately mocked), generate valid SQLite DDL for creating indexes.\n\n**Parameters:**\n+ *table (Table):* a Table object generated by the PyDBML library. This object should represent the SQLite table relevant to the index you want to create.\n+ *index (Index):* an Index object generated by the PyDBML library. This object should represent the SQLite index you want to create.\n+ *idxNameFunc (function):* defaults to `uuid.uuid4`. Can mock that function by passing a different function that returns a more predictable result. The result of calling this argument in either case is used as the name of an index if one is not provided for any `CREATE INDEX` statements.\n+ *indexExists (bool):* Default is True. If True, the generated `CREATE INDEX` SQLite statement will have `IF NOT EXISTS` language included.\n+ *join (bool):* Default is True. If True, function will `join` the result list of string segments with an empty string and return the resulting string to you. otherwise, the one-dimensional list of string segments will be returned to you directly.\n\n**Returns:**\n+ *str or list of str:* SQLite DDL for creating an index.\n\n### processEnum\n\nTake an Enum object generated by the PyDBML library and use it to generate SQLite DDL for creating an enum table for "full" enum emulation mode only.\n\n**Parameters:**\n+ *enum (Enum):* Enum object generated by PyDBML library representing an SQL enum.\n+ *tableExists (bool):* Default is True. If True, all generated `CREATE TABLE` SQLite statements will have `IF NOT EXISTS` language included.\n+ *join (bool):* Default is True. If True, function will `join` the result list of string segments with an empty string and return the resulting string to you. Otherwise, the one-dimensional list of string segments will be returned to you directly.\n\n**Returns:**\n+ *str or list of str:* SQLite DDL for creating a table to emulate SQL enum functionality.\n\n### processTable\n    \nGenerate SQLite DDL for creating a table.\n\n**Parameters:**\n+ *table (Table):* Table object generated by PyDBML, representing SQLite table you want to make.\n+ *emulationMode (str):* if SQL enums are defined by dbml parsed by PyDBML, there are two ways to emulate them. Passing "full" for this parameter emulates enum by making a separate enum table. Passing "half" simply uses SQLite CHECK statements within column definitions utilizing enum types.\n+ *tableExists (bool):* Default is True. If True, all generated `CREATE TABLE` SQLite statements will have `IF NOT EXISTS` language included.\n+ *join (bool):* Default is True. If True, function will `join` the result list of string segments with an empty string and return the resulting string to you. Otherwise, the one-dimensional list of string segments will be returned to you directly.\n\n**Return:**\n+ *str or list of str:* SQLite DDL for generating a table.\n\n### processRef\n    \nConvert a Ref object parsed by PyDBML from dbml into SQLite DDL.\n\n**Parameters:**\n+ *ref (Ref):* Ref object generated by PyDBML.\n+ *join (bool):* Default is True. If True, function will `join` the result list of string segments with an empty string and return the resulting string to you. Otherwise, the one-dimensional list of string segments will be returned to you directly.\n\n**Returns:**\n+ *str or list of str:* SQLite DDL for defining a foreign key within a `CREATE TABLE` statement.\n\n### processColumn\n\nGenerate SQLite DDL for creating a column.\n\n**Parameters:**\n+ *column (Column):* the Column object generated by PyDBML library.\n+ *emulationMode (str):* "half" or "full" emulation of SQL enums for SQLite. The former uses `CHECK` statements within column definitions, and the latter uses separate tables.\n+ *join (bool):* Default is True. If True, function will `join` the result list of string segments with an empty string and return the resulting string to you. Otherwise, the one-dimensional list of string segments will be returned to you directly.\n\n**Returns:**\n+ *str or list of str:* SQLite DDL for creating a column.\n\n### coerceColType(colType):\n\nGiven a colType, coerce to closest native SQLite type and return that, otherwise raise a ValueError.\n\n**Parameters:**\n+ *colType (str):* column type from DBML specification.\n\n**Returns:**\n+ *str:* valid SQLite column type.\n\n## References\n+ [PyDBML by Vanderhoof](https://github.com/Vanderhoof/PyDBML)\n+ [Database Markup Language — DBML](https://www.dbml.org/home/#intro)\n+ [SQLite Official](https://sqlite.org/index.html)\n+ [SQLite3 Python Library](https://docs.python.org/3/library/sqlite3.html)\n\n\n\n\nFri May 21 20:45:27 UTC 2021\n',
    'author': 'Dave VanderWeele',
    'author_email': 'weele.me@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/dvanderweele/DBML_SQLite',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'entry_points': entry_points,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
