This commit is contained in:
macbook_max
2026-10-15 20:36:59 +08:00
commit 6bf949949c
7923 changed files with 1369582 additions and 0 deletions
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -0,0 +1,46 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
from aiomysql import __version__
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'aiomysql'
copyright = '2015,2016 Nikolay Novik'
author = 'Nikolay Novik'
version = '.'.join(__version__.split('.')[:2])
release = __version__
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.viewcode',
'sphinx_copybutton',
]
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
}
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
language = 'en'
highlight_language = 'python3'
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = 'furo'
htmlhelp_basename = 'aiomysqldoc'
@@ -0,0 +1,206 @@
.. _api:
:mod:`aiomysql` --- API Reference
=================================
.. module:: aiomysql
:synopsis: A library for accessing a MySQL database from the asyncio
.. currentmodule:: aiomysql
.. _aiomysql-connection:
Connection
==========
The library provides a way to connect to MySQL database with simple factory
function :func:`aiomysql.connnect`. Use this function if you want just one
connection to the database, consider connection pool for multiple connections.
Example::
import asyncio
import aiomysql
loop = asyncio.get_event_loop()
async def test_example():
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='', db='mysql',
loop=loop)
cur = await conn.cursor()
await cur.execute("SELECT Host,User FROM user")
print(cur.description)
r = await cur.fetchall()
print(r)
await cur.close()
conn.close()
loop.run_until_complete(test_example())
.. function:: connect(host="localhost", user=None, password="",
db=None, port=3306, unix_socket=None,
charset='', sql_mode=None,
read_default_file=None, conv=decoders, use_unicode=None,
client_flag=0, cursorclass=Cursor, init_command=None,
connect_timeout=None, read_default_group=None,
autocommit=False, echo=False
local_infile=False, loop=None, ssl=None, auth_plugin='',
program_name='', server_public_key=None)
A :ref:`coroutine <coroutine>` that connects to MySQL.
The function accepts all parameters that :func:`pymysql.connect`
does plus optional keyword-only *loop* and *timeout* parameters.
:param str host: host where the database server is located,
default: `localhost`.
:param str user: username to log in as.
:param str password: password to use.
:param str db: database to use, None to not use a particular one.
:param int port: MySQL port to use, default is usually OK.
:param str unix_socket: optionally, you can use a unix socket rather
than TCP/IP.
:param str charset: charset you want to use, for example 'utf8'.
:param sql_mode: default sql-mode_ to use, like 'NO_BACKSLASH_ESCAPES'
:param read_default_file: specifies my.cnf file to read these
parameters from under the [client] section.
:param conv: decoders dictionary to use instead of the default one.
This is used to provide custom marshalling of types.
See `pymysql.converters`.
:param use_unicode: whether or not to default to unicode strings.
:param client_flag: custom flags to send to MySQL. Find
potential values in `pymysql.constants.CLIENT`. Refer to the
`local_infile` parameter for enabling loading of local data.
:param cursorclass: custom cursor class to use.
:param str init_command: initial SQL statement to run when connection is
established.
:param connect_timeout: Timeout in seconds before throwing an exception
when connecting.
:param str read_default_group: Group to read from in the configuration
file.
:param autocommit: Autocommit mode. None means use server default.
(default: ``False``)
:param local_infile: Boolean to enable the use of `LOAD DATA LOCAL`
command. This also enables the corresponding `client_flag`. aiomysql
does not perform any validation of files requested by the server. Do
not use this with untrusted servers. (default: ``False``)
:param ssl: Optional SSL Context to force SSL
:param auth_plugin: String to manually specify the authentication
plugin to use, i.e you will want to use mysql_clear_password
when using IAM authentication with Amazon RDS.
(default: Server Default)
:param program_name: Program name string to provide when
handshaking with MySQL. (omitted by default)
.. versionchanged:: 1.0
``sys.argv[0]`` is no longer passed by default
:param server_public_key: SHA256 authenticaiton plugin public key value.
:param loop: asyncio event loop instance or ``None`` for default one.
:returns: :class:`Connection` instance.
Representation of a socket with a mysql server. The proper way to get an
instance of this class is to call :func:`aiomysql.connnect`.
Its insterface is almost the same as `pymysql.connection` except all methods
are :ref:`coroutines <coroutine>`.
The most important methods are:
.. method:: cursor(cursor=None)
A :ref:`coroutine <coroutine>` that creates a new cursor object
using the connection.
By default, :class:`Cursor` is returned. It is possible to also give a
custom cursor through the `cursor` parameter, but it needs to
be a subclass of :class:`Cursor`
:param cursor: subclass of :class:`Cursor` or ``None`` for default
cursor.
:returns: :class:`Cursor` instance.
.. method:: close()
Immediately close the connection.
Close the connection now (rather than whenever `del` is executed).
The connection will be unusable from this point forward.
.. method:: ensure_closed()
A :ref:`coroutine <coroutine>` ends quit command and then closes
socket connection.
.. method:: autocommit(value)
A :ref:`coroutine <coroutine>` to enable/disable autocommit mode for
current MySQL session.
:param bool value: toggle atutocommit mode.
.. method:: get_autocommit()
Returns autocommit status for current MySQL sesstion.
:returns bool: current autocommit status.
.. method:: begin()
A :ref:`coroutine <coroutine>` to begin transaction.
.. method:: commit()
Commit changes to stable storage :ref:`coroutine <coroutine>`.
.. method:: rollback()
Roll back the current transaction :ref:`coroutine <coroutine>`.
.. method:: select_db(db)
A :ref:`coroutine <coroutine>` to set current db.
:param str db: database name
.. attribute:: closed
The readonly property that returns ``True`` if connections is closed.
.. attribute:: host
MySQL server IP address or name.
.. attribute:: port
MySQL server TCP/IP port.
.. attribute:: unix_socket
ySQL Unix socket file location.
.. attribute:: db
Current database name.
.. attribute:: user
User used while connecting to MySQL
.. attribute:: echo
Return echo mode status.
.. attribute:: encoding
Encoding employed for this connection.
.. attribute:: charset
Returns the character set for current connection.
.. _sql-mode: http://dev.mysql.com/doc/refman/5.0/en/sql-mode.html
@@ -0,0 +1,3 @@
.. _aiomysql-contributing:
.. include:: ../CONTRIBUTING.rst
@@ -0,0 +1,390 @@
.. _aiomysql-cursors:
Cursor
======
.. class:: Cursor
A cursor for connection.
Allows Python code to execute :term:`MySQL` command in a database
session. Cursors are created by the :meth:`Connection.cursor`
:ref:`coroutine <coroutine>`: they are bound to the connection for
the entire lifetime and all the commands are executed in the context
of the database session wrapped by the connection.
Cursors that are created from the same connection are not isolated,
i.e., any changes done to the database by a cursor are immediately
visible by the other cursors. Cursors created from different
connections can or can not be isolated, depending on the
connections’ isolation level.
.. code:: python
import asyncio
import aiomysql
loop = asyncio.get_event_loop()
async def test_example():
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='',
db='mysql', loop=loop)
# create default cursor
cursor = await conn.cursor()
# execute sql query
await cursor.execute("SELECT Host, User FROM user")
# fetch all results
r = await cursor.fetchall()
# detach cursor from connection
await cursor.close()
# close connection
conn.close()
loop.run_until_complete(test_example())
Use :meth:`Connection.cursor()` for getting cursor for connection.
.. attribute:: connection
This read-only attribute return a reference to the :class:`Connection`
object on which the cursor was created
.. attribute:: echo
Return echo mode status.
.. attribute:: description
This read-only attribute is a sequence of 7-item sequences.
Each of these sequences is a collections.namedtuple containing
information describing one result column:
0. name: the name of the column returned.
1. type_code: the type of the column.
2. display_size: the actual length of the column in bytes.
3. internal_size: the size in bytes of the column associated to
this column on the server.
4. precision: total number of significant digits in columns of
type ``NUMERIC``. None for other types.
5. scale: count of decimal digits in the fractional part in
columns of type ``NUMERIC``. None for other types.
6. null_ok: always None.
This attribute will be None for operations that do not
return rows or if the cursor has not had an operation invoked
via the :meth:`Cursor.execute()` method yet.
.. attribute:: rowcount
Returns the number of rows that has been produced of affected.
This read-only attribute specifies the number of rows that the
last :meth:`Cursor.execute()` produced (for Data Query Language
statements like SELECT) or affected (for Data Manipulation
Language statements like ``UPDATE`` or ``INSERT``).
The attribute is -1 in case no :meth:`Cursor.execute()` has been
performed on the cursor or the row count of the last operation if it
can't be determined by the interface.
.. attribute:: rownumber
Row index. This read-only attribute provides the current 0-based index
of the cursor in the result set or ``None`` if the index cannot be
determined.
.. attribute:: arraysize
How many rows will be returned by :meth:`Cursor.fetchmany()` call.
This read/write attribute specifies the number of rows to
fetch at a time with :meth:`Cursor.fetchmany()`. It defaults to
1 meaning to fetch a single row at a time.
.. attribute:: lastrowid
This read-only property returns the value generated for an
`AUTO_INCREMENT` column by the previous `INSERT` or `UPDATE` statement
or None when there is no such value available. For example,
if you perform an `INSERT` into a table that contains an
`AUTO_INCREMENT` column, :attr:`Cursor.lastrowid` returns the
`AUTO_INCREMENT` value for the new row.
.. attribute:: closed
The readonly property that returns ``True`` if connections was detached
from current cursor
.. method:: close()
:ref:`Coroutine <coroutine>` to close the cursor now (rather than
whenever ``del`` is executed). The cursor will be unusable from this
point forward; closing a cursor just exhausts all remaining data.
.. method:: execute(query, args=None)
:ref:`Coroutine <coroutine>`, executes the given operation substituting
any markers with the given parameters.
For example, getting all rows where id is 5::
await cursor.execute("SELECT * FROM t1 WHERE id=%s", (5,))
:param str query: sql statement
:param list args: tuple or list of arguments for sql query
:returns int: number of rows that has been produced of affected
.. method:: executemany(query, args)
The `executemany()` :ref:`coroutine <coroutine>` will execute the
operation iterating over the list of parameters in seq_params.
Example: Inserting 3 new employees and their phone number::
data = [
('Jane','555-001'),
('Joe', '555-001'),
('John', '555-003')
]
stmt = "INSERT INTO employees (name, phone)
VALUES ('%s','%s')"
await cursor.executemany(stmt, data)
`INSERT` statements are optimized by batching the data, that is
using the MySQL multiple rows syntax.
:param str query: sql statement
:param list args: tuple or list of arguments for sql query
.. method:: callproc(procname, args)
Execute stored procedure procname with args, this method is
:ref:`coroutine <coroutine>`.
Compatibility warning: PEP-249 specifies that any modified
parameters must be returned. This is currently impossible
as they are only available by storing them in a server
variable and then retrieved by a query. Since stored
procedures return zero or more result sets, there is no
reliable way to get at OUT or INOUT parameters via `callproc`.
The server variables are named `@_procname_n`, where `procname`
is the parameter above and n is the position of the parameter
(from zero). Once all result sets generated by the procedure
have been fetched, you can issue a `SELECT @_procname_0`, ...
query using :meth:`Cursor.execute()` to get any OUT or INOUT values.
Basic usage example::
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='',
db='mysql', loop=self.loop)
cur = await conn.cursor()
await cur.execute("""CREATE PROCEDURE myinc(p1 INT)
BEGIN
SELECT p1 + 1;
END
""")
await cur.callproc('myinc', [1])
(ret, ) = await cur.fetchone()
assert 2, ret
await cur.close()
conn.close()
Compatibility warning: The act of calling a stored procedure
itself creates an empty result set. This appears after any
result sets generated by the procedure. This is non-standard
behavior with respect to the DB-API. Be sure to use
:meth:`Cursor.nextset()` to advance through all result sets; otherwise
you may get disconnected.
:param str procname: name of procedure to execute on server
:param args: sequence of parameters to use with procedure
:returns: the original args.
.. method:: fetchone()
Fetch the next row :ref:`coroutine <coroutine>`.
.. method:: fetchmany(size=None)
:ref:`Coroutine <coroutine>` the next set of rows of a query result,
returning a list of tuples. When no more rows are available, it
returns an empty list.
The number of rows to fetch per call is specified by the parameter.
If it is not given, the cursor's :attr:`Cursor.arraysize` determines
the number of rows to be fetched. The method should try to fetch as
many rows as indicated by the size parameter. If this is not possible
due to the specified number of rows not being available, fewer rows
may be returned ::
cursor = await connection.cursor()
await cursor.execute("SELECT * FROM test;")
r = cursor.fetchmany(2)
print(r)
# [(1, 100, "abc'def"), (2, None, 'dada')]
r = await cursor.fetchmany(2)
print(r)
# [(3, 42, 'bar')]
r = await cursor.fetchmany(2)
print(r)
# []
:param int size: number of rows to return
:returns list: of fetched rows
.. method:: fetchall()
:ref:`Coroutine <coroutine>` returns all rows of a query result set::
await cursor.execute("SELECT * FROM test;")
r = await cursor.fetchall()
print(r)
# [(1, 100, "abc'def"), (2, None, 'dada'), (3, 42, 'bar')]
:returns list: list of fetched rows
.. method:: scroll(value, mode='relative')
Scroll the cursor in the result set to a new position according
to mode. This method is :ref:`coroutine <coroutine>`.
If mode is ``relative`` (default), value is taken as offset to the
current position in the result set, if set to ``absolute``, value
states an absolute target position. An IndexError should be raised in
case a scroll operation would leave the result set. In this case,
the cursor position is left undefined (ideal would be to
not move the cursor at all).
.. note::
According to the :term:`DBAPI`, the exception raised for a cursor out
of bound should have been :exc:`IndexError`. The best option is
probably to catch both exceptions in your code::
try:
await cur.scroll(1000 * 1000)
except (ProgrammingError, IndexError), exc:
deal_with_it(exc)
:param int value: move cursor to next position according to mode.
:param str mode: scroll mode, possible modes: `relative` and `absolute`
.. class:: DictCursor
A cursor which returns results as a dictionary. All methods and arguments
same as :class:`Cursor`, see example::
import asyncio
import aiomysql
loop = asyncio.get_event_loop()
async def test_example():
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='',
db='mysql', loop=loop)
# create dict cursor
cursor = await conn.cursor(aiomysql.DictCursor)
# execute sql query
await cursor.execute(
"SELECT * from people where name='bob'")
# fetch all results
r = await cursor.fetchone()
print(r)
# {'age': 20, 'DOB': datetime.datetime(1990, 2, 6, 23, 4, 56),
# 'name': 'bob'}
loop.run_until_complete(test_example())
You can customize your dictionary, see example::
import asyncio
import aiomysql
class AttrDict(dict):
"""Dict that can get attribute by dot, and doesn't raise KeyError"""
def __getattr__(self, name):
try:
return self[name]
except KeyError:
return None
class AttrDictCursor(aiomysql.DictCursor):
dict_type = AttrDict
loop = asyncio.get_event_loop()
async def test_example():
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='',
db='mysql', loop=loop)
# create your dict cursor
cursor = await conn.cursor(AttrDictCursor)
# execute sql query
await cursor.execute(
"SELECT * from people where name='bob'")
# fetch all results
r = await cursor.fetchone()
print(r)
# {'age': 20, 'DOB': datetime.datetime(1990, 2, 6, 23, 4, 56),
# 'name': 'bob'}
print(r.age)
# 20
print(r.foo)
# None
loop.run_until_complete(test_example())
.. class:: SSCursor
Unbuffered Cursor, mainly useful for queries that return a lot of
data, or for connections to remote servers over a slow network.
Instead of copying every row of data into a buffer, this will fetch
rows as needed. The upside of this, is the client uses much less memory,
and rows are returned much faster when traveling over a slow network,
or if the result set is very big.
There are limitations, though. The MySQL protocol doesn't support
returning the total number of rows, so the only way to tell how many rows
there are is to iterate over every row returned. Also, it currently isn't
possible to scroll backwards, as only the current row is held in memory.
All methods are the same as in :class:`Cursor` but with different
behaviour.
.. method:: fetchall()
Same as :meth:`Cursor.fetchall` :ref:`coroutine <coroutine>`,
useless for large queries, as all rows fetched one by one.
.. method:: fetchmany(size=None, mode='relative')
Same as :meth:`Cursor.fetchall`, but each row fetched one by one.
.. method:: scroll(size=None)
Same as :meth:`Cursor.scroll`, but move cursor on server side one by
one. If you want to move 20 rows forward scroll will make 20 queries
to move cursor. Currently only forward scrolling is supported.
.. class:: SSDictCursor
An unbuffered cursor, which returns results as a dictionary.
@@ -0,0 +1,38 @@
Examples of aiomysql usage
==========================
Below is a list of examples from `aiomysql/examples
<https://github.com/aio-libs/aiomysql/tree/main/examples>`_
Every example is a correct tiny python program that demonstrates specific
feature of library.
.. _aiomysql-examples-simple:
Low-level API
-------------
Basic example, fetch host and user information from internal table: user.
.. literalinclude:: ../examples/example.py
Example of stored procedure, which just increments input value.
.. literalinclude:: ../examples/example_callproc.py
Example of using `executemany` method:
.. literalinclude:: ../examples/example_executemany.py
Example of using transactions `rollback` and `commit` methods:
.. literalinclude:: ../examples/example_transaction.py
Example of using connection pool:
.. literalinclude:: ../examples/example_pool.py
sqlalchemy usage
----------------
.. literalinclude:: ../examples/example_simple_sa.py
@@ -0,0 +1,58 @@
.. _glossary:
********
Glossary
********
.. if you add new entries, keep the alphabetical sorting!
.. glossary::
DBAPI
:pep:`249` -- Python Database API Specification v2.0
ipdb
ipdb exports functions to access the IPython debugger, which
features tab completion, syntax highlighting, better tracebacks,
better introspection with the same interface as the pdb module.
MySQL
A popular database server.
http://www.mysql.com/
pep8
Python style guide checker
*pep8* is a tool to check your Python code against some of the
style conventions in :pep:`8` -- Style Guide for Python Code.
pyflakes
passive checker of Python programs
A simple program which checks Python source files for errors.
Pyflakes analyzes programs and detects various errors. It works
by parsing the source file, not importing it, so it is safe to
use on modules with side effects. It's also much faster.
https://pypi.python.org/pypi/pyflakes
PyMySQL
Pure-Python MySQL client library. The goal of PyMySQL is to be a drop-in
replacement for MySQLdb and work on CPython, PyPy, IronPython and Jython.
https://github.com/PyMySQL/PyMySQL
sqlalchemy
The Python SQL Toolkit and Object Relational Mapper.
http://www.sqlalchemy.org/
@@ -0,0 +1,144 @@
.. _aiomysql-index:
.. aiomysql documentation master file, created by
sphinx-quickstart on Sun Jun 11 16:24:33 2023.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to aiomysql's documentation!
====================================
.. _GitHub: https://github.com/aio-libs/aiomysql
.. _asyncio: http://docs.python.org/3.5/library/asyncio.html
.. _aiopg: https://github.com/aio-libs/aiopg
.. _Tornado-MySQL: https://github.com/PyMySQL/Tornado-MySQL
.. _aio-libs: https://github.com/aio-libs
**aiomysql** is a library for accessing a :term:`MySQL` database
from the asyncio_ (PEP-3156/tulip) framework. It depends and reuses most parts
of :term:`PyMySQL` . **aiomysql** tries to be like awesome aiopg_ library and preserve
same api, look and feel.
Internally **aiomysql** is copy of PyMySQL, underlying io calls switched
to async, basically ``await`` and ``async def coroutine`` added in
proper places. :term:`sqlalchemy` support ported from aiopg_.
Features
--------
* Implements *asyncio* :term:`DBAPI` *like* interface for
:term:`MySQL`. It includes :ref:`aiomysql-connection`,
:ref:`aiomysql-cursors` and :ref:`aiomysql-pool` objects.
* Implements *optional* support for charming :term:`sqlalchemy`
functional sql layer.
Basics
------
**aiomysql** based on :term:`PyMySQL` , and provides same api, you just need
to use ``await conn.f()`` instead of just call ``conn.f()`` for
every method.
Properties are unchanged, so ``conn.prop`` is correct as well as
``conn.prop = val``.
See example:
.. code:: python
import asyncio
import aiomysql
loop = asyncio.get_event_loop()
async def test_example():
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='', db='mysql',
loop=loop)
cur = await conn.cursor()
await cur.execute("SELECT Host,User FROM user")
print(cur.description)
r = await cur.fetchall()
print(r)
await cur.close()
conn.close()
loop.run_until_complete(test_example())
Installation
------------
.. code::
pip3 install aiomysql
.. note:: :mod:`aiomysql` requires :term:`PyMySQL` library.
Also you probably want to use :mod:`aiomysql.sa`.
.. _aiomysql-install-sqlalchemy:
:mod:`aiomysql.sa` module is **optional** and requires
:term:`sqlalchemy`. You can install *sqlalchemy* by running::
pip3 install sqlalchemy
Source code
-----------
The project is hosted on GitHub_
Please feel free to file an issue on `bug tracker
<https://github.com/aio-libs/aiomysql/issues>`_ if you have found a bug
or have some suggestion for library improvement.
The library uses `GitHub Actions
<https://github.com/aio-libs/aiomysql/actions>`_ for Continuous Integration
and `Codecov <https://app.codecov.io/gh/aio-libs/aiomysql/branch/main>`_ for
coverage reports.
Dependencies
------------
- Python 3.9+
- :term:`PyMySQL`
- aiomysql.sa requires :term:`sqlalchemy`.
Authors and License
-------------------
The ``aiomysql`` package is written by Nikolay Novik, :term:`PyMySQL` and
aio-libs_ contributors. It's MIT licensed (same as PyMySQL).
Feel free to improve this package and send a pull request to GitHub_.
Contents:
---------
.. toctree::
:maxdepth: 2
:titlesonly:
connection
cursors
pool
tutorial
sa
examples
glossary
contributing
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
@@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd
@@ -0,0 +1,146 @@
.. _aiomysql-pool:
Pool
====
The library provides *connection pool* as well as plain
:class:`Connection` objects.
The basic usage is::
import asyncio
import aiomysql
loop = asyncio.get_event_loop()
async def go():
pool = await aiomysql.create_pool(host='127.0.0.1', port=3306,
user='root', password='',
db='mysql', loop=loop, autocommit=False)
async with pool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute("SELECT 10")
# print(cur.description)
(r,) = await cur.fetchone()
assert r == 10
pool.close()
await pool.wait_closed()
loop.run_until_complete(go())
.. function:: create_pool(minsize=1, maxsize=10, loop=None, **kwargs)
A :ref:`coroutine <coroutine>` that creates a pool of connections to
:term:`MySQL` database.
:param int minsize: minimum sizes of the *pool*.
:param int maxsize: maximum sizes of the *pool*.
:param loop: is an optional *event loop* instance,
:func:`asyncio.get_event_loop` is used if *loop* is not specified.
:param bool echo: -- executed log SQL queryes (``False`` by default).
:param kwargs: The function accepts all parameters that
:func:`aiomysql.connect` does plus optional keyword-only parameters
*loop*, *minsize*, *maxsize*.
:param float pool_recycle: number of seconds after which connection is
recycled, helps to deal with stale connections in pool, default
value is -1, means recycling logic is disabled.
:returns: :class:`Pool` instance.
.. class:: Pool
A connection pool.
After creation pool has *minsize* free connections and can grow up
to *maxsize* ones.
If *minsize* is ``0`` the pool doesn't creates any connection on startup.
If *maxsize* is ``0`` than size of pool is unlimited (but it
recycles used connections of course).
The most important way to use it is getting connection in *with statement*::
async with pool.acquire() as conn:
async with conn.cursor() as cur:
pass
See also :meth:`Pool.acquire` and :meth:`Pool.release` for acquiring
:class:`Connection` without *with statement*.
.. attribute:: echo
Return *echo mode* status. Log all executed queries to logger
named ``aiomysql`` if ``True``
.. attribute:: minsize
A minimal size of the pool (*read-only*), ``1`` by default.
.. attribute:: maxsize
A maximal size of the pool (*read-only*), ``10`` by default.
.. attribute:: size
A current size of the pool (*readonly*). Includes used and free
connections.
.. attribute:: freesize
A count of free connections in the pool (*readonly*).
.. method:: clear()
A :ref:`coroutine <coroutine>` that closes all *free* connections
in the pool. At next connection acquiring at least :attr:`minsize` of
them will be recreated.
.. method:: close()
Close pool.
Mark all pool connections to be closed on getting back to pool.
Closed pool doesn't allow to acquire new connections.
If you want to wait for actual closing of acquired connection please
call :meth:`wait_closed` after :meth:`close`.
.. warning:: The method is not a :ref:`coroutine <coroutine>`.
.. method:: terminate()
Terminate pool.
Close pool with instantly closing all acquired connections also.
:meth:`wait_closed` should be called after :meth:`terminate` for
waiting for actual finishing.
.. warning:: The method is not a :ref:`coroutine <coroutine>`.
.. method:: wait_closed()
A :ref:`coroutine <coroutine>` that waits for releasing and
closing all acquired connections.
Should be called after :meth:`close` for waiting for actual pool
closing.
.. method:: acquire()
A :ref:`coroutine <coroutine>` that acquires a connection from
*free pool*. Creates new connection if needed and :attr:`size`
of pool is less than :attr:`maxsize`.
Returns a :class:`Connection` instance.
.. method:: release(conn)
Reverts connection *conn* to *free pool* for future recycling.
.. warning:: The method is not a :ref:`coroutine <coroutine>`.
@@ -0,0 +1,632 @@
.. _aiomysql-sa:
:mod:`aiomysql.sa` --- support for SQLAlchemy functional SQL layer
==================================================================
.. module:: aiomysql.sa
:synopsis: support for SQLAlchemy functional SQL layer
.. currentmodule:: aiomysql.sa
Intro
-----
.. note:: :term:`sqlalchemy` support ported from aiopg_, so api should be
very familiar for aiopg_ user.
While :ref:`core API <aiomysql-index>` provides a core support for
access to :term:`MySQL` database, manipulations with raw SQL strings
too annoying.
Fortunately we can use excellent :ref:`aiomysql <aiomysql-index>` as **SQL query builder**.
Example::
import asyncio
import sqlalchemy as sa
from aiomysql.sa import create_engine
metadata = sa.MetaData()
tbl = sa.Table(
"tbl",
metadata,
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("val", sa.String(255)),
)
async def go():
engine = await create_engine(
user="root",
db="test_pymysql",
host="127.0.0.1",
password="",
)
async with engine.acquire() as conn:
async with conn.begin() as transaction:
await conn.execute(tbl.insert().values(val="abc"))
await transaction.commit()
res = await conn.execute(tbl.select())
async for row in res:
print(row.id, row.val)
engine.close()
await engine.wait_closed()
asyncio.run(go())
So you can execute SQL query built by
``tbl.insert().values(val='abc')`` or ``tbl.select()`` expressions.
:term:`sqlalchemy` has rich and very powerful set of SQL construction
functions, please read :ref:`tutorial <aiomysql-index>` for full list
of available operations.
Also we provide SQL transactions support. Please take a look on
:meth:`SAConnection.begin` method and family.
.. _aiopg: https://github.com/aio-libs/aiopg
Engine
------
.. function:: create_engine(*, minsize=1, maxsize=10, loop=None, \
dialect=dialect, **kwargs)
A :ref:`coroutine <coroutine>` for :class:`Engine` creation.
Returns :class:`Engine` instance with embedded connection pool.
The pool has *minsize* opened connections to :term:`MySQL` server.
At *kwargs* function accepts all parameters that
:func:`aiomysql.connect` does.
.. data:: dialect
An instance of :term:`SQLAlchemy` dialect set up for :term:`pymysql` usage.
An :class:`sqlalchemy.engine.interfaces.Dialect` instance.
.. seealso:: :mod:`sqlalchemy.dialects.mysql.pymysql`
PyMySQL dialect.
.. class:: Engine
Connects a :class:`aiomysql.Pool` and
:class:`sqlalchemy.engine.interfaces.Dialect` together to provide a
source of database connectivity and behavior.
An :class:`Engine` object is instantiated publicly using the
:func:`create_engine` coroutine.
.. attribute:: dialect
A :class:`sqlalchemy.engine.interfaces.Dialect` for the engine,
readonly property.
.. attribute:: name
A name of the dialect, readonly property.
.. attribute:: driver
A driver of the dialect, readonly property.
.. attribute:: minsize
A minimal size of the pool (*read-only*), ``1`` by default.
.. attribute:: maxsize
A maximal size of the pool (*read-only*), ``10`` by default.
.. attribute:: size
A current size of the pool (*readonly*). Includes used and free
connections.
.. attribute:: freesize
A count of free connections in the pool (*readonly*).
.. method:: close()
Close engine.
Mark all engine connections to be closed on getting back to engine.
Closed engine doesn't allow to acquire new connections.
If you want to wait for actual closing of acquired connection please
call :meth:`wait_closed` after :meth:`close`.
.. warning:: The method is not a :ref:`coroutine <coroutine>`.
.. method:: terminate()
Terminate engine.
Close engine's pool with instantly closing all acquired connections
also.
:meth:`wait_closed` should be called after :meth:`terminate` for
waiting for actual finishing.
.. warning:: The method is not a :ref:`coroutine <coroutine>`.
.. method:: wait_closed()
A :ref:`coroutine <coroutine>` that waits for releasing and
closing all acquired connections.
Should be called after :meth:`close` for waiting for actual engine
closing.
.. method:: acquire()
Get a connection from pool.
This method is a :ref:`coroutine <coroutine>`.
Returns a :class:`SAConnection` instance.
.. method:: release()
Revert back connection *conn* to pool.
.. warning:: The method is not a :ref:`coroutine <coroutine>`.
Connection
----------
.. class:: SAConnection
A wrapper for :class:`aiomysql.Connection` instance.
The class provides methods for executing *SQL queries* and working with
*SQL transactions*.
.. method:: execute(query, *multiparams, **params)
Executes a *SQL* *query* with optional parameters.
This method is a :ref:`coroutine <coroutine>`.
:param query: a SQL query string or any :term:`sqlalchemy`
expression (see :ref:`aiomysql core <aiomysql-index>`)
:param \*multiparams/\**params: represent bound parameter values
to be used in the execution. Typically, the format is either a
dictionary passed to \*multiparams::
await conn.execute(
table.insert(),
{"id":1, "value":"v1"}
)
...or individual key/values interpreted by \**params::
await conn.execute(
table.insert(), id=1, value="v1"
)
In the case that a plain SQL string is passed, a tuple or
individual values in \*multiparams may be passed::
await conn.execute(
"INSERT INTO table (id, value) VALUES (%d, %s)",
(1, "v1")
)
await conn.execute(
"INSERT INTO table (id, value) VALUES (%s, %s)",
1, "v1"
)
:returns: :class:`ResultProxy` instance with results of SQL
query execution.
.. method:: scalar(query, *multiparams, **params)
Executes a *SQL* *query* and returns a scalar value.
This method is a :ref:`coroutine <coroutine>`.
.. seealso:: :meth:`SAConnection.execute` and :meth:`ResultProxy.scalar`.
.. attribute:: closed
The readonly property that returns ``True`` if connections is closed.
.. method:: begin()
Begin a transaction and return a transaction handle.
This method is a :ref:`coroutine <coroutine>`.
The returned object is an instance of :class:`.Transaction`.
This object represents the "scope" of the transaction,
which completes when either the :meth:`.Transaction.rollback`
or :meth:`.Transaction.commit` method is called.
Nested calls to :meth:`.begin` on the same :class:`.SAConnection`
will return new :class:`.Transaction` objects that represent
an emulated transaction within the scope of the enclosing
transaction, that is::
trans = await conn.begin() # outermost transaction
trans2 = await conn.begin() # "inner"
await trans2.commit() # does nothing
await trans.commit() # actually commits
Calls to :meth:`.Transaction.commit` only have an effect
when invoked via the outermost :class:`.Transaction` object, though the
:meth:`.Transaction.rollback` method of any of the
:class:`.Transaction` objects will roll back the
transaction.
.. seealso::
:meth:`.SAConnection.begin_nested` - use a SAVEPOINT
:meth:`.SAConnection.begin_twophase` - use a two phase (XA)
transaction
.. method:: begin_nested()
Begin a nested transaction and return a transaction handle.
This method is a :ref:`coroutine <coroutine>`.
The returned object is an instance of :class:`.NestedTransaction`.
Any transaction in the hierarchy may ``commit`` and
``rollback``, however the outermost transaction still controls
the overall ``commit`` or ``rollback`` of the transaction of a
whole. It utilizes SAVEPOINT facility of :term:`MySQL` server.
.. seealso::
:meth:`.SAConnection.begin`, :meth:`.SAConnection.begin_twophase`.
.. method:: begin_twophase(xid=None)
Begin a two-phase or XA transaction and return a transaction
handle.
This method is a :ref:`coroutine <coroutine>`.
The returned object is an instance of
:class:`.TwoPhaseTransaction`, which in addition to the methods
provided by :class:`.Transaction`, also provides a
:meth:`~.TwoPhaseTransaction.prepare` method.
:param xid: the two phase transaction id. If not supplied, a
random id will be generated.
.. seealso::
:meth:`.SAConnection.begin`, :meth:`.SAConnection.begin_twophase`.
.. method:: recover_twophase()
Return a list of prepared twophase transaction ids.
This method is a :ref:`coroutine <coroutine>`.
.. method:: rollback_prepared(xid)
Rollback prepared twophase transaction *xid*.
This method is a :ref:`coroutine <coroutine>`.
.. method:: commit_prepared(xid)
Commit prepared twophase transaction *xid*.
This method is a :ref:`coroutine <coroutine>`.
.. attribute:: in_transaction
The readonly property that returns ``True`` if a transaction is
in progress.
.. method:: close()
Close this :class:`SAConnection`.
This method is a :ref:`coroutine <coroutine>`.
This results in a release of the underlying database
resources, that is, the :class:`aiomysql.Connection` referenced
internally. The :class:`aiomysql.Connection` is typically restored
back to the connection-holding :class:`aiomysql.Pool` referenced
by the :class:`.Engine` that produced this
:class:`SAConnection`. Any transactional state present on
the :class:`aiomysql.Connection` is also unconditionally released via
calling :meth:`Transaction.rollback` method.
After :meth:`~.SAConnection.close` is called, the
:class:`.SAConnection` is permanently in a closed state,
and will allow no further operations.
ResultProxy
-----------
.. class:: ResultProxy
Wraps a *DB-API like* :class:`Cursor` object to provide easier
access to row columns.
Individual columns may be accessed by their integer position,
case-sensitive column name, or by :class:`sqlalchemy.schema.Column``
object. e.g.::
async for row in conn.execute(...):
col1 = row[0] # access via integer position
col2 = row['col2'] # access via name
col3 = row[mytable.c.mycol] # access via Column object.
:class:`ResultProxy` also handles post-processing of result column
data using :class:`sqlalchemy.types.TypeEngine` objects, which are
referenced from the originating SQL statement that produced this
result set.
.. attribute:: dialect
The readonly property that returns
:class:`sqlalchemy.engine.interfaces.Dialect` dialect
for the :class:`ResultProxy` instance.
.. seealso:: :data:`dialect` global data.
.. method:: keys()
Return the current set of string keys for rows.
.. attribute:: rowcount
The readonly property that returns the 'rowcount' for this result.
The 'rowcount' reports the number of rows *matched*
by the WHERE criterion of an UPDATE or DELETE statement.
.. note::
Notes regarding :attr:`ResultProxy.rowcount`:
* This attribute returns the number of rows *matched*,
which is not necessarily the same as the number of rows
that were actually *modified* - an UPDATE statement, for example,
may have no net change on a given row if the SET values
given are the same as those present in the row already.
Such a row would be matched but not modified.
* :attr:`ResultProxy.rowcount` is *only* useful in conjunction
with an UPDATE or DELETE statement. Contrary to what the Python
DBAPI says, it does *not* return the
number of rows available from the results of a SELECT statement
as DBAPIs cannot support this functionality when rows are
unbuffered.
* Statements that use RETURNING does not return a correct
rowcount.
.. attribute:: lastrowid
Returns the 'lastrowid' accessor on the DBAPI cursor.
value generated for an *AUTO_INCREMENT* column by the previous INSERT
or UPDATE statement or None when there is no such value available. For
example, if you perform an *INSERT* into a table that contains an
AUTO_INCREMENT column, `lastrowid` returns the *AUTO_INCREMENT* value
for the new row.
.. attribute:: returns_rows
A readonly property that returns ``True`` if this
:class:`ResultProxy` returns rows.
I.e. if it is legal to call the methods
:meth:`ResultProxy.fetchone`,
:meth:`ResultProxy.fetchmany`,
:meth:`ResultProxy.fetchall`.
.. attribute:: closed
Return ``True`` if this :class:`ResultProxy` is closed (no
pending rows in underlying cursor).
.. method:: close()
Close this :class:`ResultProxy`.
Closes the underlying :class:`aiomysql.Cursor` corresponding to the
execution.
Note that any data cached within this :class:`ResultProxy` is
still available. For some types of results, this may include
buffered rows.
This method is called automatically when:
* all result rows are exhausted using the fetchXXX() methods.
* cursor.description is None.
.. method:: fetchall()
Fetch all rows, just like :meth:`aiomysql.Cursor.fetchall`.
This method is a :ref:`coroutine <coroutine>`.
The connection is closed after the call.
Returns a list of :class:`RowProxy`.
.. method:: fetchone()
Fetch one row, just like :meth:`aiomysql.Cursor.fetchone`.
This method is a :ref:`coroutine <coroutine>`.
If a row is present, the cursor remains open after this is called.
Else the cursor is automatically closed and ``None`` is returned.
Returns an :class:`RowProxy` instance or ``None``.
.. method:: fetchmany(size=None)
Fetch many rows, just like :meth:`aiomysql.Cursor.fetchmany`.
This method is a :ref:`coroutine <coroutine>`.
If rows are present, the cursor remains open after this is called.
Else the cursor is automatically closed and an empty list is returned.
Returns a list of :class:`RowProxy`.
.. method:: first()
Fetch the first row and then close the result set unconditionally.
This method is a :ref:`coroutine <coroutine>`.
Returns ``None`` if no row is present or an :class:`RowProxy` instance.
.. method:: scalar()
Fetch the first column of the first row, and close the result set.
Returns ``None`` if no row is present or an :class:`RowProxy` instance.
.. class:: RowProxy
A :class:`collections.abc.Mapping` for representing a row in query result.
Keys are column names, values are result values.
Individual columns may be accessed by their integer position,
case-sensitive column name, or by :class:`sqlalchemy.schema.Column``
object.
Has overloaded operators ``__eq__`` and ``__ne__`` for comparing two rows.
The :class:`RowProxy` is *not hashable*.
..method:: as_tuple()
Return a tuple with values from :meth:`RowProxy.values`.
Transaction objects
-------------------
.. class:: Transaction
Represent a database transaction in progress.
The :class:`Transaction` object is procured by
calling the :meth:`SAConnection.begin` method of
:class:`SAConnection`::
async with engine.acquire() as conn:
trans = await conn.begin()
try:
await conn.execute("insert into x (a, b) values (1, 2)")
except Exception:
await trans.rollback()
else:
await trans.commit()
The object provides :meth:`.rollback` and :meth:`.commit`
methods in order to control transaction boundaries.
.. seealso::
:meth:`SAConnection.begin`, :meth:`SAConnection.begin_twophase`,
:meth:`SAConnection.begin_nested`.
.. attribute:: is_active
A readonly property that returns ``True`` if a transaction is active.
.. attribute:: connection
A readonly property that returns :class:`SAConnection` for transaction.
.. method:: close()
Close this :class:`Transaction`.
This method is a :ref:`coroutine <coroutine>`.
If this transaction is the base transaction in a begin/commit
nesting, the transaction will :meth:`Transaction.rollback`.
Otherwise, the method returns.
This is used to cancel a :class:`Transaction` without affecting
the scope of an enclosing transaction.
.. method:: rollback()
Roll back this :class:`Transaction`.
This method is a :ref:`coroutine <coroutine>`.
.. method:: commit()
Commit this :class:`Transaction`.
This method is a :ref:`coroutine <coroutine>`.
.. class:: NestedTransaction
Represent a 'nested', or SAVEPOINT transaction.
A new :class:`NestedTransaction` object may be procured
using the :meth:`SAConnection.begin_nested` method.
The interface is the same as that of :class:`Transaction`.
.. seealso:: `SAVEPOINT, ROLLBACK TO SAVEPOINT, and RELEASE SAVEPOINT`__
on :term:`MySQL`:
.. __: https://dev.mysql.com/doc/refman/8.4/en/savepoint.html
.. class:: TwoPhaseTransaction
Represent a two-phase transaction.
A new :class:`TwoPhaseTransaction` object may be procured
using the :meth:`SAConnection.begin_twophase` method.
The interface is the same as that of :class:`Transaction`
with the addition of the :meth:`TwoPhaseTransaction.prepare` method.
.. attribute:: xid
A readonly property that returns twophase transaction id.
.. method:: prepare()
Prepare this :class:`TwoPhaseTransaction`.
This method is a :ref:`coroutine <coroutine>`.
After a `PREPARE`, the transaction can be committed.
.. seealso:: :term:`MySQL` commands for two phase transactions:
https://dev.mysql.com/doc/refman/8.4/en/xa-statements.html
@@ -0,0 +1,146 @@
.. _aiomysql-tutorial:
Tutorial
========
Python database access modules all have similar interfaces, described by the
:term:`DBAPI`. Most relational databases use the same synchronous interface,
*aiomysql* tries to provide same api you just need
to use ``await conn.f()`` instead of just call ``conn.f()`` for
every method.
Installation
------------
.. code::
pip3 install aiomysql
.. note:: :mod:`aiomysql` requires :term:`PyMySQL` library.
Getting Started
---------------
Lets start from basic example::
import asyncio
import aiomysql
loop = asyncio.get_event_loop()
async def test_example():
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='', db='mysql',
loop=loop)
cur = await conn.cursor()
await cur.execute("SELECT Host,User FROM user")
print(cur.description)
r = await cur.fetchall()
print(r)
await cur.close()
conn.close()
loop.run_until_complete(test_example())
Connection is established by invoking the :func:`connect()` coroutine,
arguments list are keyword arguments, almost same as in :term:`PyMySQL`
corresponding method. Example makes connection to :term:`MySQL` server on
local host to access `mysql` database with user name `root`' and empty password.
If :func:`connect()` coroutine succeeds, it returns a :class:`Connection`
instance as the basis for further interaction with :term:`MySQL`.
After the connection object has been obtained, code in example invokes
:meth:`Connection.cursor()` coroutine method to create a cursor object for
processing statements. Example uses cursor to issue a
``SELECT Host,User FROM user;`` statement, which returns a list of `host` and
`user` from :term:`MySQL` system table ``user``::
cur = await conn.cursor()
await cur.execute("SELECT Host,User FROM user")
print(cur.description)
r = await cur.fetchall()
The cursor object's :meth:`Cursor.execute()` method sends the query the server
and :meth:`Cursor.fetchall()` retrieves rows.
Finally, the script invokes :meth:`Cursor.close()` coroutine and
connection object's :meth:`Connection.close()` method to disconnect
from the server::
await cur.close()
conn.close()
After that, ``conn`` becomes invalid and should not be used to access the
server.
Inserting Data
--------------
Let's take basic example of :meth:`Cursor.execute` method::
import asyncio
import aiomysql
async def test_example_execute(loop):
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='',
db='test_pymysql', loop=loop)
cur = await conn.cursor()
async with conn.cursor() as cur:
await cur.execute("DROP TABLE IF EXISTS music_style;")
await cur.execute("""CREATE TABLE music_style
(id INT,
name VARCHAR(255),
PRIMARY KEY (id));""")
await conn.commit()
# insert 3 rows one by one
await cur.execute("INSERT INTO music_style VALUES(1,'heavy metal')")
await cur.execute("INSERT INTO music_style VALUES(2,'death metal');")
await cur.execute("INSERT INTO music_style VALUES(3,'power metal');")
await conn.commit()
conn.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(test_example_execute(loop))
Please note that you need to manually call :func:`commit()` bound to your :class:`Connection` object, because by default it's set to ``False`` or in :meth:`aiomysql.connect()` you can transfer addition keyword argument ``autocommit=True``.
Example with ``autocommit=True``::
import asyncio
import aiomysql
async def test_example_execute(loop):
conn = await aiomysql.connect(host='127.0.0.1', port=3306,
user='root', password='',
db='test_pymysql', loop=loop,
autocommit=True)
cur = await conn.cursor()
async with conn.cursor() as cur:
await cur.execute("DROP TABLE IF EXISTS music_style;")
await cur.execute("""CREATE TABLE music_style
(id INT,
name VARCHAR(255),
PRIMARY KEY (id));""")
# insert 3 rows one by one
await cur.execute("INSERT INTO music_style VALUES(1,'heavy metal')")
await cur.execute("INSERT INTO music_style VALUES(2,'death metal');")
await cur.execute("INSERT INTO music_style VALUES(3,'power metal');")
conn.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(test_example_execute(loop))