# MySQL-Mimic
[](https://github.com/kelsin/mysql-mimic/actions/workflows/tests.yml)
Pure-python implementation of the MySQL server [wire protocol](https://dev.mysql.com/doc/internals/en/client-server-protocol.html).
This can be used to create applications that act as a MySQL server.
## Installation
```shell
pip install mysql-mimic
```
## Usage
A minimal use case might look like this:
```python
import asyncio
from mysql_mimic import MysqlServer, Session
class MySession(Session):
async def query(self, expression, sql, attrs):
print(f"Parsed abstract syntax tree: {expression}")
print(f"Original SQL string: {sql}")
print(f"Query attributes: {sql}")
print(f"Currently authenticated user: {self.username}")
print(f"Currently selected database: {self.database}")
return [("a", 1), ("b", 2)], ["col1", "col2"]
async def schema(self):
# Optionally provide the database schema.
# This is used to serve INFORMATION_SCHEMA and SHOW queries.
return {
"table": {
"col1": "TEXT",
"col2": "INT",
}
}
if __name__ == "__main__":
server = MysqlServer(session_factory=MySession)
asyncio.run(server.serve_forever())
```
Using [sqlglot](https://github.com/tobymao/sqlglot), the abstract `Session` class handles queries to metadata, variables, etc. that many MySQL clients expect.
To bypass this default behavior, you can implement the [`mysql_mimic.session.BaseSession`](mysql_mimic/session.py) interface.
See [examples](./examples) for more examples.
## Authentication
MySQL-mimic has built in support for several standard MySQL authentication plugins:
- [mysql_native_password](https://dev.mysql.com/doc/refman/8.0/en/native-pluggable-authentication.html)
- The client sends hashed passwords to the server, and the server stores hashed passwords. See the documentation for more details on how this works.
- [example](examples/auth_native_password.py)
- [mysql_clear_password](https://dev.mysql.com/doc/refman/8.0/en/cleartext-pluggable-authentication.html)
- The client sends passwords to the server as clear text, without hashing or encryption.
- This is typically used as the client plugin for a custom server plugin. As such, MySQL-mimic provides an abstract class, [`mysql_mimic.auth.AbstractClearPasswordAuthPlugin`](mysql_mimic/auth.py), which can be extended.
- [example](examples/auth_clear_password.py)
- [mysql_no_login](https://dev.mysql.com/doc/refman/8.0/en/no-login-pluggable-authentication.html)
- The server prevents clients from directly authenticating as an account. See the documentation for relevant use cases.
- [authentication_kerberos](https://dev.mysql.com/doc/mysql-security-excerpt/8.0/en/kerberos-pluggable-authentication.html)
- Kerberos uses tickets together with symmetric-key cryptography, enabling authentication without sending passwords over the network. Kerberos authentication supports userless and passwordless scenarios.
By default, a session naively accepts whatever username the client provides.
Plugins are provided to the server by implementing [`mysql_mimic.IdentityProvider`](mysql_mimic/auth.py), which configures all available plugins and a callback for fetching users.
Custom plugins can be created by extending [`mysql_mimic.auth.AuthPlugin`](mysql_mimic/auth.py).
## Development
You can install dependencies with `make deps`.
You can format your code with `make format`.
You can lint with `make lint`.
You can check type annotations with `make types`.
You can run tests with `make test`. This will build a coverage report in `./htmlcov/index.html`.
You can run all the checks with `make check`.
You can build a pip package with `make build`.
Raw data
{
"_id": null,
"home_page": "https://github.com/kelsin/mysql-mimic",
"name": "mysql-mimic",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": null,
"author": "Christopher Giroir",
"author_email": "kelsin@valefor.com",
"download_url": "https://files.pythonhosted.org/packages/c7/43/7b02b34f81229d6ed0901344902059a4b754896e1859850e9ddf512dd9fc/mysql-mimic-2.6.3.tar.gz",
"platform": null,
"description": "# MySQL-Mimic\n\n[](https://github.com/kelsin/mysql-mimic/actions/workflows/tests.yml)\n\nPure-python implementation of the MySQL server [wire protocol](https://dev.mysql.com/doc/internals/en/client-server-protocol.html).\n\nThis can be used to create applications that act as a MySQL server.\n\n## Installation\n\n```shell\npip install mysql-mimic\n```\n\n## Usage\n\nA minimal use case might look like this:\n\n```python\nimport asyncio\n\nfrom mysql_mimic import MysqlServer, Session\n\n\nclass MySession(Session):\n async def query(self, expression, sql, attrs):\n print(f\"Parsed abstract syntax tree: {expression}\")\n print(f\"Original SQL string: {sql}\")\n print(f\"Query attributes: {sql}\")\n print(f\"Currently authenticated user: {self.username}\")\n print(f\"Currently selected database: {self.database}\")\n return [(\"a\", 1), (\"b\", 2)], [\"col1\", \"col2\"]\n\n async def schema(self):\n # Optionally provide the database schema.\n # This is used to serve INFORMATION_SCHEMA and SHOW queries.\n return {\n \"table\": {\n \"col1\": \"TEXT\",\n \"col2\": \"INT\",\n }\n }\n\nif __name__ == \"__main__\":\n server = MysqlServer(session_factory=MySession)\n asyncio.run(server.serve_forever())\n```\n\nUsing [sqlglot](https://github.com/tobymao/sqlglot), the abstract `Session` class handles queries to metadata, variables, etc. that many MySQL clients expect.\n\nTo bypass this default behavior, you can implement the [`mysql_mimic.session.BaseSession`](mysql_mimic/session.py) interface.\n\nSee [examples](./examples) for more examples.\n\n## Authentication\n\nMySQL-mimic has built in support for several standard MySQL authentication plugins:\n- [mysql_native_password](https://dev.mysql.com/doc/refman/8.0/en/native-pluggable-authentication.html)\n - The client sends hashed passwords to the server, and the server stores hashed passwords. See the documentation for more details on how this works.\n - [example](examples/auth_native_password.py)\n- [mysql_clear_password](https://dev.mysql.com/doc/refman/8.0/en/cleartext-pluggable-authentication.html)\n - The client sends passwords to the server as clear text, without hashing or encryption.\n - This is typically used as the client plugin for a custom server plugin. As such, MySQL-mimic provides an abstract class, [`mysql_mimic.auth.AbstractClearPasswordAuthPlugin`](mysql_mimic/auth.py), which can be extended.\n - [example](examples/auth_clear_password.py)\n- [mysql_no_login](https://dev.mysql.com/doc/refman/8.0/en/no-login-pluggable-authentication.html)\n - The server prevents clients from directly authenticating as an account. See the documentation for relevant use cases.\n- [authentication_kerberos](https://dev.mysql.com/doc/mysql-security-excerpt/8.0/en/kerberos-pluggable-authentication.html)\n - Kerberos uses tickets together with symmetric-key cryptography, enabling authentication without sending passwords over the network. Kerberos authentication supports userless and passwordless scenarios.\n\n\nBy default, a session naively accepts whatever username the client provides.\n\nPlugins are provided to the server by implementing [`mysql_mimic.IdentityProvider`](mysql_mimic/auth.py), which configures all available plugins and a callback for fetching users.\n\nCustom plugins can be created by extending [`mysql_mimic.auth.AuthPlugin`](mysql_mimic/auth.py).\n\n## Development\n\nYou can install dependencies with `make deps`.\n\nYou can format your code with `make format`.\n\nYou can lint with `make lint`.\n\nYou can check type annotations with `make types`.\n\nYou can run tests with `make test`. This will build a coverage report in `./htmlcov/index.html`.\n\nYou can run all the checks with `make check`.\n\nYou can build a pip package with `make build`.\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A python implementation of the mysql server protocol",
"version": "2.6.3",
"project_urls": {
"Homepage": "https://github.com/kelsin/mysql-mimic"
},
"split_keywords": [],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "9824d21a65f8609196191b4af255d48bd3053928dee3e740c012ec155f3bbeee",
"md5": "a57ad662b705f842c49f2da18267cbb9",
"sha256": "11fda5f85f8259fa4b4a552281575bea03b3f2eb2e38a3aac81338383a1c34f7"
},
"downloads": -1,
"filename": "mysql_mimic-2.6.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a57ad662b705f842c49f2da18267cbb9",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 47735,
"upload_time": "2025-01-28T22:41:25",
"upload_time_iso_8601": "2025-01-28T22:41:25.836061Z",
"url": "https://files.pythonhosted.org/packages/98/24/d21a65f8609196191b4af255d48bd3053928dee3e740c012ec155f3bbeee/mysql_mimic-2.6.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c7437b02b34f81229d6ed0901344902059a4b754896e1859850e9ddf512dd9fc",
"md5": "8887db22f842a97ed0247309a0f55120",
"sha256": "ca232168d2081b473e5d644366ad386e40baad717f1b7ee3a7aa55013b79cae4"
},
"downloads": -1,
"filename": "mysql-mimic-2.6.3.tar.gz",
"has_sig": false,
"md5_digest": "8887db22f842a97ed0247309a0f55120",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 53801,
"upload_time": "2025-01-28T22:41:26",
"upload_time_iso_8601": "2025-01-28T22:41:26.969487Z",
"url": "https://files.pythonhosted.org/packages/c7/43/7b02b34f81229d6ed0901344902059a4b754896e1859850e9ddf512dd9fc/mysql-mimic-2.6.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-28 22:41:26",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "kelsin",
"github_project": "mysql-mimic",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "mysql-mimic"
}