From 7a846cf5e35ebcad852309aebaa0bac8a7244744 Mon Sep 17 00:00:00 2001 From: Evax Software Date: Thu, 4 Oct 2012 13:34:39 -0400 Subject: Allow pip install from git Merged with modifications from https://github.com/evax/MySQLdb1/commit/a8152690101733904b16a32ff8467220ca07242c --- MySQLdb/GPL-2.0 | 339 --- MySQLdb/HISTORY | 161 -- MySQLdb/MANIFEST.in | 12 - MySQLdb/MySQLdb/__init__.py | 98 - MySQLdb/MySQLdb/connections.py | 333 --- MySQLdb/MySQLdb/constants/.cvsignore | 1 - MySQLdb/MySQLdb/constants/CLIENT.py | 29 - MySQLdb/MySQLdb/constants/CR.py | 30 - MySQLdb/MySQLdb/constants/ER.py | 467 ----- MySQLdb/MySQLdb/constants/FIELD_TYPE.py | 37 - MySQLdb/MySQLdb/constants/FLAG.py | 23 - MySQLdb/MySQLdb/constants/REFRESH.py | 17 - MySQLdb/MySQLdb/constants/__init__.py | 1 - MySQLdb/MySQLdb/converters.py | 181 -- MySQLdb/MySQLdb/cursors.py | 533 ----- MySQLdb/MySQLdb/release.py | 4 - MySQLdb/MySQLdb/times.py | 111 - MySQLdb/README | 253 --- MySQLdb/__init__.py | 98 + MySQLdb/_mysql.c | 3105 ---------------------------- MySQLdb/_mysql_exceptions.py | 87 - MySQLdb/connections.py | 333 +++ MySQLdb/constants/CLIENT.py | 29 + MySQLdb/constants/CR.py | 30 + MySQLdb/constants/ER.py | 467 +++++ MySQLdb/constants/FIELD_TYPE.py | 37 + MySQLdb/constants/FLAG.py | 23 + MySQLdb/constants/REFRESH.py | 17 + MySQLdb/constants/__init__.py | 1 + MySQLdb/converters.py | 181 ++ MySQLdb/cursors.py | 533 +++++ MySQLdb/distribute_setup.py | 515 ----- MySQLdb/doc/FAQ.txt | 143 -- MySQLdb/doc/MySQLdb.txt | 718 ------- MySQLdb/ez_setup.py | 284 --- MySQLdb/metadata.cfg | 58 - MySQLdb/pymemcompat.h | 87 - MySQLdb/release.py | 4 + MySQLdb/setup.cfg | 20 - MySQLdb/setup.py | 21 - MySQLdb/setup_common.py | 37 - MySQLdb/setup_posix.py | 102 - MySQLdb/setup_windows.py | 46 - MySQLdb/site.cfg | 17 - MySQLdb/tests/capabilities.py | 281 --- MySQLdb/tests/configdb.py | 25 - MySQLdb/tests/dbapi20.py | 853 -------- MySQLdb/tests/default.cnf | 10 - MySQLdb/tests/test_MySQLdb_capabilities.py | 102 - MySQLdb/tests/test_MySQLdb_dbapi20.py | 202 -- MySQLdb/tests/test_MySQLdb_nonstandard.py | 86 - MySQLdb/tests/travis.cnf | 10 - MySQLdb/times.py | 111 + 53 files changed, 1864 insertions(+), 9439 deletions(-) delete mode 100644 MySQLdb/GPL-2.0 delete mode 100644 MySQLdb/HISTORY delete mode 100644 MySQLdb/MANIFEST.in delete mode 100644 MySQLdb/MySQLdb/__init__.py delete mode 100644 MySQLdb/MySQLdb/connections.py delete mode 100644 MySQLdb/MySQLdb/constants/.cvsignore delete mode 100644 MySQLdb/MySQLdb/constants/CLIENT.py delete mode 100644 MySQLdb/MySQLdb/constants/CR.py delete mode 100644 MySQLdb/MySQLdb/constants/ER.py delete mode 100644 MySQLdb/MySQLdb/constants/FIELD_TYPE.py delete mode 100644 MySQLdb/MySQLdb/constants/FLAG.py delete mode 100644 MySQLdb/MySQLdb/constants/REFRESH.py delete mode 100644 MySQLdb/MySQLdb/constants/__init__.py delete mode 100644 MySQLdb/MySQLdb/converters.py delete mode 100644 MySQLdb/MySQLdb/cursors.py delete mode 100644 MySQLdb/MySQLdb/release.py delete mode 100644 MySQLdb/MySQLdb/times.py delete mode 100644 MySQLdb/README create mode 100644 MySQLdb/__init__.py delete mode 100644 MySQLdb/_mysql.c delete mode 100644 MySQLdb/_mysql_exceptions.py create mode 100644 MySQLdb/connections.py create mode 100644 MySQLdb/constants/CLIENT.py create mode 100644 MySQLdb/constants/CR.py create mode 100644 MySQLdb/constants/ER.py create mode 100644 MySQLdb/constants/FIELD_TYPE.py create mode 100644 MySQLdb/constants/FLAG.py create mode 100644 MySQLdb/constants/REFRESH.py create mode 100644 MySQLdb/constants/__init__.py create mode 100644 MySQLdb/converters.py create mode 100644 MySQLdb/cursors.py delete mode 100644 MySQLdb/distribute_setup.py delete mode 100644 MySQLdb/doc/FAQ.txt delete mode 100644 MySQLdb/doc/MySQLdb.txt delete mode 100644 MySQLdb/ez_setup.py delete mode 100644 MySQLdb/metadata.cfg delete mode 100644 MySQLdb/pymemcompat.h create mode 100644 MySQLdb/release.py delete mode 100644 MySQLdb/setup.cfg delete mode 100644 MySQLdb/setup.py delete mode 100644 MySQLdb/setup_common.py delete mode 100644 MySQLdb/setup_posix.py delete mode 100644 MySQLdb/setup_windows.py delete mode 100644 MySQLdb/site.cfg delete mode 100644 MySQLdb/tests/capabilities.py delete mode 100644 MySQLdb/tests/configdb.py delete mode 100644 MySQLdb/tests/dbapi20.py delete mode 100644 MySQLdb/tests/default.cnf delete mode 100644 MySQLdb/tests/test_MySQLdb_capabilities.py delete mode 100644 MySQLdb/tests/test_MySQLdb_dbapi20.py delete mode 100644 MySQLdb/tests/test_MySQLdb_nonstandard.py delete mode 100644 MySQLdb/tests/travis.cnf create mode 100644 MySQLdb/times.py (limited to 'MySQLdb') diff --git a/MySQLdb/GPL-2.0 b/MySQLdb/GPL-2.0 deleted file mode 100644 index d159169..0000000 --- a/MySQLdb/GPL-2.0 +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/MySQLdb/HISTORY b/MySQLdb/HISTORY deleted file mode 100644 index f90b466..0000000 --- a/MySQLdb/HISTORY +++ /dev/null @@ -1,161 +0,0 @@ -===================== - What's new in 1.2.4 -===================== - -beta 3 -====== - -Unified test database configuration, and set up CI testing with Travis. - -Applied several patches from André Malo (ndparker@users.sf.net) which fix some issues -with exception handling and reference counting and TEXT/BLOB conversion. - - -beta 2 -====== - -Reverted an accidental change in the exception format. (issue #1) - -Reverted some raise statements so that they will continue to work with Python < 2.6 - - -beta 1 -====== - -A lot of work has been done towards Python 3 compatibility, and avoiding warnings with Python 2.7. -This includes import changes, converting dict.has_kay(k) to k in dict, updating some test suite methods, etc. - -Due to the difficulties of supporting Python 3 and Python < 2.7, 1.2.4 will support Python 2.4 though 2.7. -1.3.0 will support Python 3 and Python 2.7 and 2.6. - -MySQLdb-2.0 is instead going to become moist-1.0. See https://github.com/farcepest/moist - -The Windows build has been simplified, and I plan to correct pre-built i386 packages built -against the python.org Python-2.7 package and MySQL Connector/C-6.0. Contact me if you -need ia64 packages. - -The connection's cursorclass (if not default) was being lost on reconnect. - -Newer versions of MySQL don't use OpenSSL and therefore don't have HAVE_SSL defined, but they do have -a different SSL library. Fixed this so SSL support would be enabled in this case. - -The regex that looked for SQL INSERT statement and VALUES in cursor.executemany() was made case-insensitive -again. - - -===================== - What's new in 1.2.3 -===================== - -ez_setup.py has been update to include various fixes that affect the build. - -Better Python version and dependency detection as well as eliminate exception -warnings under Python 2.6. - -Eliminated memory leaks related to Unicode and failed connections. - -Corrected connection .escape() functionality. - -Miscellaneous cleanups and and expanded testing suite to ensure ongoing release -quality. - -===================== - What's new in 1.2.2 -===================== - -The build system has been completely redone and should now build -on Windows without any patching; uses setuptools. - -Added compatibility for Python 2.5, including support for with statement. - -connection.ping() now takes an optional boolean argument which can -enable (or disable) automatic reconnection. - -Support returning SET columns as Python sets was removed due to an -API bug in MySQL; corresponding test removed. - -Added a test for single-character CHAR columns. - -BLOB columns are now returned as Python strings instead of byte arrays. - -BINARY character columns are always returned as Python strings, and not -unicode. - -Fixed a bug introduced in 1.2.1 where the new SHOW WARNINGS support broke -SSCursor. - -Only encode the query (convert to a string) when it is a unicode instance; -re-encoding encoded strings would break things. - -Make a deep copy of conv when connecting, since it can be modified. - -Added support for new VARCHAR and BIT column types. - -DBAPISet objects were broken, but nobody noticed. - - -======================== - What's new in 1.2.1_p2 -======================== - -There are some minor build fixes which probably only affect MySQL -older than 4.0. - -If you had MySQL older than 4.1, the new charset and sql_mode -parameters didn't work right. In fact, it was impossible to create -a connection due to the charset problem. - -If you are using MySQL-4.1 or newer, there is no practical difference -between 1.2.1 and 1.2.1_p2, and you don't need to upgrade. - - -===================== - What's new in 1.2.1 -===================== - -Switched to Subversion. Was going to do this for 1.3, but a -SourceForge CVS outage has forced the issue. - -Mapped a lot of new 4.1 and 5.0 error codes to Python exceptions - -Added an API call for mysql_set_character_set(charset) (MySQL > 5.0.7) - -Added an API call for mysql_get_character_set_info() (MySQL > 5.0.10) - -Revamped the build system. Edit site.cfg if necessary (probably not -in most cases) - -Python-2.3 is now the minimum version. - -Dropped support for mx.Datetime and stringtimes; always uses Python -datetime module now. - -Improved unit tests - -New connect() options: -* charset: sets character set, implies use_unicode -* sql_mode: sets SQL mode (i.e. ANSI, etc.; see MySQL docs) - -When using MySQL-4.1 or newer, enables MULTI_STATEMENTS - -When using MySQL-5.0 or newer, enables MULTI_RESULTS - -When using MySQL-4.1 or newer, more detailed warning messages -are produced - -SET columns returned as Python Set types; you can pass a Set as -a parameter to cursor.execute(). - -Support for the new MySQL-5.0 DECIMAL implementation - -Support for Python Decimal type - -Some use of weak references internally. Cursors no longer leak -if you don't close them. Connections still do, unfortunately. - -ursor.fetchXXXDict() methods raise DeprecationWarning - -cursor.begin() is making a brief reappearence. - -cursor.callproc() now works, with some limitations. - diff --git a/MySQLdb/MANIFEST.in b/MySQLdb/MANIFEST.in deleted file mode 100644 index 4e9fa05..0000000 --- a/MySQLdb/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -recursive-include doc *.txt -recursive-include tests *.py -include MANIFEST.in -include HISTORY -include GPL-2.0 -include pymemcompat.h -include metadata.cfg -include site.cfg -include distribute_setup.py -include setup_common.py -include setup_posix.py -include setup_windows.py diff --git a/MySQLdb/MySQLdb/__init__.py b/MySQLdb/MySQLdb/__init__.py deleted file mode 100644 index 8761671..0000000 --- a/MySQLdb/MySQLdb/__init__.py +++ /dev/null @@ -1,98 +0,0 @@ -"""MySQLdb - A DB API v2.0 compatible interface to MySQL. - -This package is a wrapper around _mysql, which mostly implements the -MySQL C API. - -connect() -- connects to server - -See the C API specification and the MySQL documentation for more info -on other items. - -For information on how MySQLdb handles type conversion, see the -MySQLdb.converters module. - -""" - -__revision__ = """$Revision$"""[11:-2] -from MySQLdb.release import __version__, version_info, __author__ - -import _mysql - -if version_info != _mysql.version_info: - raise ImportError("this is MySQLdb version %s, but _mysql is version %r" % - (version_info, _mysql.version_info)) - -threadsafety = 1 -apilevel = "2.0" -paramstyle = "format" - -from _mysql import * -from MySQLdb.constants import FIELD_TYPE -from MySQLdb.times import Date, Time, Timestamp, \ - DateFromTicks, TimeFromTicks, TimestampFromTicks - -try: - frozenset -except NameError: - from sets import ImmutableSet as frozenset - -class DBAPISet(frozenset): - - """A special type of set for which A == x is true if A is a - DBAPISet and x is a member of that set.""" - - def __eq__(self, other): - if isinstance(other, DBAPISet): - return not self.difference(other) - return other in self - - -STRING = DBAPISet([FIELD_TYPE.ENUM, FIELD_TYPE.STRING, - FIELD_TYPE.VAR_STRING]) -BINARY = DBAPISet([FIELD_TYPE.BLOB, FIELD_TYPE.LONG_BLOB, - FIELD_TYPE.MEDIUM_BLOB, FIELD_TYPE.TINY_BLOB]) -NUMBER = DBAPISet([FIELD_TYPE.DECIMAL, FIELD_TYPE.DOUBLE, FIELD_TYPE.FLOAT, - FIELD_TYPE.INT24, FIELD_TYPE.LONG, FIELD_TYPE.LONGLONG, - FIELD_TYPE.TINY, FIELD_TYPE.YEAR]) -DATE = DBAPISet([FIELD_TYPE.DATE, FIELD_TYPE.NEWDATE]) -TIME = DBAPISet([FIELD_TYPE.TIME]) -TIMESTAMP = DBAPISet([FIELD_TYPE.TIMESTAMP, FIELD_TYPE.DATETIME]) -DATETIME = TIMESTAMP -ROWID = DBAPISet() - -def test_DBAPISet_set_equality(): - assert STRING == STRING - -def test_DBAPISet_set_inequality(): - assert STRING != NUMBER - -def test_DBAPISet_set_equality_membership(): - assert FIELD_TYPE.VAR_STRING == STRING - -def test_DBAPISet_set_inequality_membership(): - assert FIELD_TYPE.DATE != STRING - -def Binary(x): - return str(x) - -def Connect(*args, **kwargs): - """Factory function for connections.Connection.""" - from MySQLdb.connections import Connection - return Connection(*args, **kwargs) - -connect = Connection = Connect - -__all__ = [ 'BINARY', 'Binary', 'Connect', 'Connection', 'DATE', - 'Date', 'Time', 'Timestamp', 'DateFromTicks', 'TimeFromTicks', - 'TimestampFromTicks', 'DataError', 'DatabaseError', 'Error', - 'FIELD_TYPE', 'IntegrityError', 'InterfaceError', 'InternalError', - 'MySQLError', 'NULL', 'NUMBER', 'NotSupportedError', 'DBAPISet', - 'OperationalError', 'ProgrammingError', 'ROWID', 'STRING', 'TIME', - 'TIMESTAMP', 'Warning', 'apilevel', 'connect', 'connections', - 'constants', 'converters', 'cursors', 'debug', 'escape', 'escape_dict', - 'escape_sequence', 'escape_string', 'get_client_info', - 'paramstyle', 'string_literal', 'threadsafety', 'version_info'] - - - - diff --git a/MySQLdb/MySQLdb/connections.py b/MySQLdb/MySQLdb/connections.py deleted file mode 100644 index 1d6fa82..0000000 --- a/MySQLdb/MySQLdb/connections.py +++ /dev/null @@ -1,333 +0,0 @@ -""" - -This module implements connections for MySQLdb. Presently there is -only one class: Connection. Others are unlikely. However, you might -want to make your own subclasses. In most cases, you will probably -override Connection.default_cursor with a non-standard Cursor class. - -""" -from MySQLdb import cursors -from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ - DatabaseError, OperationalError, IntegrityError, InternalError, \ - NotSupportedError, ProgrammingError -import types, _mysql -import re - - -def defaulterrorhandler(connection, cursor, errorclass, errorvalue): - """ - - If cursor is not None, (errorclass, errorvalue) is appended to - cursor.messages; otherwise it is appended to - connection.messages. Then errorclass is raised with errorvalue as - the value. - - You can override this with your own error handler by assigning it - to the instance. - - """ - error = errorclass, errorvalue - if cursor: - cursor.messages.append(error) - else: - connection.messages.append(error) - del cursor - del connection - raise errorclass, errorvalue - -re_numeric_part = re.compile(r"^(\d+)") - -def numeric_part(s): - """Returns the leading numeric part of a string. - - >>> numeric_part("20-alpha") - 20 - >>> numeric_part("foo") - >>> numeric_part("16b") - 16 - """ - - m = re_numeric_part.match(s) - if m: - return int(m.group(1)) - return None - - -class Connection(_mysql.connection): - - """MySQL Database Connection Object""" - - default_cursor = cursors.Cursor - - def __init__(self, *args, **kwargs): - """ - - Create a connection to the database. It is strongly recommended - that you only use keyword parameters. Consult the MySQL C API - documentation for more information. - - host - string, host to connect - - user - string, user to connect as - - passwd - string, password to use - - db - string, database to use - - port - integer, TCP/IP port to connect to - - unix_socket - string, location of unix_socket to use - - conv - conversion dictionary, see MySQLdb.converters - - connect_timeout - number of seconds to wait before the connection attempt - fails. - - compress - if set, compression is enabled - - named_pipe - if set, a named pipe is used to connect (Windows only) - - init_command - command which is run once the connection is created - - read_default_file - file from which default client values are read - - read_default_group - configuration group to use from the default file - - cursorclass - class object, used to create cursors (keyword only) - - use_unicode - If True, text-like columns are returned as unicode objects - using the connection's character set. Otherwise, text-like - columns are returned as strings. columns are returned as - normal strings. Unicode objects will always be encoded to - the connection's character set regardless of this setting. - - charset - If supplied, the connection character set will be changed - to this character set (MySQL-4.1 and newer). This implies - use_unicode=True. - - sql_mode - If supplied, the session SQL mode will be changed to this - setting (MySQL-4.1 and newer). For more details and legal - values, see the MySQL documentation. - - client_flag - integer, flags to use or 0 - (see MySQL docs or constants/CLIENTS.py) - - ssl - dictionary or mapping, contains SSL connection parameters; - see the MySQL documentation for more details - (mysql_ssl_set()). If this is set, and the client does not - support SSL, NotSupportedError will be raised. - - local_infile - integer, non-zero enables LOAD LOCAL INFILE; zero disables - - There are a number of undocumented, non-standard methods. See the - documentation for the MySQL C API for some hints on what they do. - - """ - from MySQLdb.constants import CLIENT, FIELD_TYPE - from MySQLdb.converters import conversions - from weakref import proxy, WeakValueDictionary - - import types - - kwargs2 = kwargs.copy() - - if 'conv' in kwargs: - conv = kwargs['conv'] - else: - conv = conversions - - conv2 = {} - for k, v in conv.items(): - if isinstance(k, int) and isinstance(v, list): - conv2[k] = v[:] - else: - conv2[k] = v - kwargs2['conv'] = conv2 - - cursorclass = kwargs2.pop('cursorclass', self.default_cursor) - charset = kwargs2.pop('charset', '') - - if charset: - use_unicode = True - else: - use_unicode = False - - use_unicode = kwargs2.pop('use_unicode', use_unicode) - sql_mode = kwargs2.pop('sql_mode', '') - - client_flag = kwargs.get('client_flag', 0) - client_version = tuple([ numeric_part(n) for n in _mysql.get_client_info().split('.')[:2] ]) - if client_version >= (4, 1): - client_flag |= CLIENT.MULTI_STATEMENTS - if client_version >= (5, 0): - client_flag |= CLIENT.MULTI_RESULTS - - kwargs2['client_flag'] = client_flag - - super(Connection, self).__init__(*args, **kwargs2) - self.cursorclass = cursorclass - self.encoders = dict([ (k, v) for k, v in conv.items() - if type(k) is not int ]) - - self._server_version = tuple([ numeric_part(n) for n in self.get_server_info().split('.')[:2] ]) - - db = proxy(self) - def _get_string_literal(): - def string_literal(obj, dummy=None): - return db.string_literal(obj) - return string_literal - - def _get_unicode_literal(): - def unicode_literal(u, dummy=None): - return db.literal(u.encode(unicode_literal.charset)) - return unicode_literal - - def _get_string_decoder(): - def string_decoder(s): - return s.decode(string_decoder.charset) - return string_decoder - - string_literal = _get_string_literal() - self.unicode_literal = unicode_literal = _get_unicode_literal() - self.string_decoder = string_decoder = _get_string_decoder() - if not charset: - charset = self.character_set_name() - self.set_character_set(charset) - - if sql_mode: - self.set_sql_mode(sql_mode) - - if use_unicode: - self.converter[FIELD_TYPE.STRING].append((None, string_decoder)) - self.converter[FIELD_TYPE.VAR_STRING].append((None, string_decoder)) - self.converter[FIELD_TYPE.VARCHAR].append((None, string_decoder)) - self.converter[FIELD_TYPE.BLOB].append((None, string_decoder)) - - self.encoders[types.StringType] = string_literal - self.encoders[types.UnicodeType] = unicode_literal - self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS - if self._transactional: - # PEP-249 requires autocommit to be initially off - self.autocommit(False) - self.messages = [] - - def cursor(self, cursorclass=None): - """ - - Create a cursor on which queries may be performed. The - optional cursorclass parameter is used to create the - Cursor. By default, self.cursorclass=cursors.Cursor is - used. - - """ - return (cursorclass or self.cursorclass)(self) - - def __enter__(self): return self.cursor() - - def __exit__(self, exc, value, tb): - if exc: - self.rollback() - else: - self.commit() - - def literal(self, o): - """ - - If o is a single object, returns an SQL literal as a string. - If o is a non-string sequence, the items of the sequence are - converted and returned as a sequence. - - Non-standard. For internal use; do not use this in your - applications. - - """ - return self.escape(o, self.encoders) - - def begin(self): - """Explicitly begin a connection. Non-standard. - DEPRECATED: Will be removed in 1.3. - Use an SQL BEGIN statement instead.""" - from warnings import warn - warn("begin() is non-standard and will be removed in 1.3", - DeprecationWarning, 2) - self.query("BEGIN") - - if not hasattr(_mysql.connection, 'warning_count'): - - def warning_count(self): - """Return the number of warnings generated from the - last query. This is derived from the info() method.""" - from string import atoi - info = self.info() - if info: - return atoi(info.split()[-1]) - else: - return 0 - - def set_character_set(self, charset): - """Set the connection character set to charset. The character - set can only be changed in MySQL-4.1 and newer. If you try - to change the character set from the current value in an - older version, NotSupportedError will be raised.""" - if self.character_set_name() != charset: - try: - super(Connection, self).set_character_set(charset) - except AttributeError: - if self._server_version < (4, 1): - raise NotSupportedError("server is too old to set charset") - self.query('SET NAMES %s' % charset) - self.store_result() - self.string_decoder.charset = charset - self.unicode_literal.charset = charset - - def set_sql_mode(self, sql_mode): - """Set the connection sql_mode. See MySQL documentation for - legal values.""" - if self._server_version < (4, 1): - raise NotSupportedError("server is too old to set sql_mode") - self.query("SET SESSION sql_mode='%s'" % sql_mode) - self.store_result() - - def show_warnings(self): - """Return detailed information about warnings as a - sequence of tuples of (Level, Code, Message). This - is only supported in MySQL-4.1 and up. If your server - is an earlier version, an empty sequence is returned.""" - if self._server_version < (4,1): return () - self.query("SHOW WARNINGS") - r = self.store_result() - warnings = r.fetch_row(0) - return warnings - - Warning = Warning - Error = Error - InterfaceError = InterfaceError - DatabaseError = DatabaseError - DataError = DataError - OperationalError = OperationalError - IntegrityError = IntegrityError - InternalError = InternalError - ProgrammingError = ProgrammingError - NotSupportedError = NotSupportedError - - errorhandler = defaulterrorhandler diff --git a/MySQLdb/MySQLdb/constants/.cvsignore b/MySQLdb/MySQLdb/constants/.cvsignore deleted file mode 100644 index 0d20b64..0000000 --- a/MySQLdb/MySQLdb/constants/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -*.pyc diff --git a/MySQLdb/MySQLdb/constants/CLIENT.py b/MySQLdb/MySQLdb/constants/CLIENT.py deleted file mode 100644 index 6559917..0000000 --- a/MySQLdb/MySQLdb/constants/CLIENT.py +++ /dev/null @@ -1,29 +0,0 @@ -"""MySQL CLIENT constants - -These constants are used when creating the connection. Use bitwise-OR -(|) to combine options together, and pass them as the client_flags -parameter to MySQLdb.Connection. For more information on these flags, -see the MySQL C API documentation for mysql_real_connect(). - -""" - -LONG_PASSWORD = 1 -FOUND_ROWS = 2 -LONG_FLAG = 4 -CONNECT_WITH_DB = 8 -NO_SCHEMA = 16 -COMPRESS = 32 -ODBC = 64 -LOCAL_FILES = 128 -IGNORE_SPACE = 256 -CHANGE_USER = 512 -INTERACTIVE = 1024 -SSL = 2048 -IGNORE_SIGPIPE = 4096 -TRANSACTIONS = 8192 # mysql_com.h was WRONG prior to 3.23.35 -RESERVED = 16384 -SECURE_CONNECTION = 32768 -MULTI_STATEMENTS = 65536 -MULTI_RESULTS = 131072 - - diff --git a/MySQLdb/MySQLdb/constants/CR.py b/MySQLdb/MySQLdb/constants/CR.py deleted file mode 100644 index 249dfec..0000000 --- a/MySQLdb/MySQLdb/constants/CR.py +++ /dev/null @@ -1,30 +0,0 @@ -"""MySQL Connection Errors - -Nearly all of these raise OperationalError. COMMANDS_OUT_OF_SYNC -raises ProgrammingError. - -""" - -MIN_ERROR = 2000 -MAX_ERROR = 2999 -UNKNOWN_ERROR = 2000 -SOCKET_CREATE_ERROR = 2001 -CONNECTION_ERROR = 2002 -CONN_HOST_ERROR = 2003 -IPSOCK_ERROR = 2004 -UNKNOWN_HOST = 2005 -SERVER_GONE_ERROR = 2006 -VERSION_ERROR = 2007 -OUT_OF_MEMORY = 2008 -WRONG_HOST_INFO = 2009 -LOCALHOST_CONNECTION = 2010 -TCP_CONNECTION = 2011 -SERVER_HANDSHAKE_ERR = 2012 -SERVER_LOST = 2013 -COMMANDS_OUT_OF_SYNC = 2014 -NAMEDPIPE_CONNECTION = 2015 -NAMEDPIPEWAIT_ERROR = 2016 -NAMEDPIPEOPEN_ERROR = 2017 -NAMEDPIPESETSTATE_ERROR = 2018 -CANT_READ_CHARSET = 2019 -NET_PACKET_TOO_LARGE = 2020 diff --git a/MySQLdb/MySQLdb/constants/ER.py b/MySQLdb/MySQLdb/constants/ER.py deleted file mode 100644 index ed45f3a..0000000 --- a/MySQLdb/MySQLdb/constants/ER.py +++ /dev/null @@ -1,467 +0,0 @@ -"""MySQL ER Constants - -These constants are error codes for the bulk of the error conditions -that may occur. - -""" - -HASHCHK = 1000 -NISAMCHK = 1001 -NO = 1002 -YES = 1003 -CANT_CREATE_FILE = 1004 -CANT_CREATE_TABLE = 1005 -CANT_CREATE_DB = 1006 -DB_CREATE_EXISTS = 1007 -DB_DROP_EXISTS = 1008 -DB_DROP_DELETE = 1009 -DB_DROP_RMDIR = 1010 -CANT_DELETE_FILE = 1011 -CANT_FIND_SYSTEM_REC = 1012 -CANT_GET_STAT = 1013 -CANT_GET_WD = 1014 -CANT_LOCK = 1015 -CANT_OPEN_FILE = 1016 -FILE_NOT_FOUND = 1017 -CANT_READ_DIR = 1018 -CANT_SET_WD = 1019 -CHECKREAD = 1020 -DISK_FULL = 1021 -DUP_KEY = 1022 -ERROR_ON_CLOSE = 1023 -ERROR_ON_READ = 1024 -ERROR_ON_RENAME = 1025 -ERROR_ON_WRITE = 1026 -FILE_USED = 1027 -FILSORT_ABORT = 1028 -FORM_NOT_FOUND = 1029 -GET_ERRNO = 1030 -ILLEGAL_HA = 1031 -KEY_NOT_FOUND = 1032 -NOT_FORM_FILE = 1033 -NOT_KEYFILE = 1034 -OLD_KEYFILE = 1035 -OPEN_AS_READONLY = 1036 -OUTOFMEMORY = 1037 -OUT_OF_SORTMEMORY = 1038 -UNEXPECTED_EOF = 1039 -CON_COUNT_ERROR = 1040 -OUT_OF_RESOURCES = 1041 -BAD_HOST_ERROR = 1042 -HANDSHAKE_ERROR = 1043 -DBACCESS_DENIED_ERROR = 1044 -ACCESS_DENIED_ERROR = 1045 -NO_DB_ERROR = 1046 -UNKNOWN_COM_ERROR = 1047 -BAD_NULL_ERROR = 1048 -BAD_DB_ERROR = 1049 -TABLE_EXISTS_ERROR = 1050 -BAD_TABLE_ERROR = 1051 -NON_UNIQ_ERROR = 1052 -SERVER_SHUTDOWN = 1053 -BAD_FIELD_ERROR = 1054 -WRONG_FIELD_WITH_GROUP = 1055 -WRONG_GROUP_FIELD = 1056 -WRONG_SUM_SELECT = 1057 -WRONG_VALUE_COUNT = 1058 -TOO_LONG_IDENT = 1059 -DUP_FIELDNAME = 1060 -DUP_KEYNAME = 1061 -DUP_ENTRY = 1062 -WRONG_FIELD_SPEC = 1063 -PARSE_ERROR = 1064 -EMPTY_QUERY = 1065 -NONUNIQ_TABLE = 1066 -INVALID_DEFAULT = 1067 -MULTIPLE_PRI_KEY = 1068 -TOO_MANY_KEYS = 1069 -TOO_MANY_KEY_PARTS = 1070 -TOO_LONG_KEY = 1071 -KEY_COLUMN_DOES_NOT_EXITS = 1072 -BLOB_USED_AS_KEY = 1073 -TOO_BIG_FIELDLENGTH = 1074 -WRONG_AUTO_KEY = 1075 -READY = 1076 -NORMAL_SHUTDOWN = 1077 -GOT_SIGNAL = 1078 -SHUTDOWN_COMPLETE = 1079 -FORCING_CLOSE = 1080 -IPSOCK_ERROR = 1081 -NO_SUCH_INDEX = 1082 -WRONG_FIELD_TERMINATORS = 1083 -BLOBS_AND_NO_TERMINATED = 1084 -TEXTFILE_NOT_READABLE = 1085 -FILE_EXISTS_ERROR = 1086 -LOAD_INFO = 1087 -ALTER_INFO = 1088 -WRONG_SUB_KEY = 1089 -CANT_REMOVE_ALL_FIELDS = 1090 -CANT_DROP_FIELD_OR_KEY = 1091 -INSERT_INFO = 1092 -INSERT_TABLE_USED = 1093 -NO_SUCH_THREAD = 1094 -KILL_DENIED_ERROR = 1095 -NO_TABLES_USED = 1096 -TOO_BIG_SET = 1097 -NO_UNIQUE_LOGFILE = 1098 -TABLE_NOT_LOCKED_FOR_WRITE = 1099 -TABLE_NOT_LOCKED = 1100 -BLOB_CANT_HAVE_DEFAULT = 1101 -WRONG_DB_NAME = 1102 -WRONG_TABLE_NAME = 1103 -TOO_BIG_SELECT = 1104 -UNKNOWN_ERROR = 1105 -UNKNOWN_PROCEDURE = 1106 -WRONG_PARAMCOUNT_TO_PROCEDURE = 1107 -WRONG_PARAMETERS_TO_PROCEDURE = 1108 -UNKNOWN_TABLE = 1109 -FIELD_SPECIFIED_TWICE = 1110 -INVALID_GROUP_FUNC_USE = 1111 -UNSUPPORTED_EXTENSION = 1112 -TABLE_MUST_HAVE_COLUMNS = 1113 -RECORD_FILE_FULL = 1114 -UNKNOWN_CHARACTER_SET = 1115 -TOO_MANY_TABLES = 1116 -TOO_MANY_FIELDS = 1117 -TOO_BIG_ROWSIZE = 1118 -STACK_OVERRUN = 1119 -WRONG_OUTER_JOIN = 1120 -NULL_COLUMN_IN_INDEX = 1121 -CANT_FIND_UDF = 1122 -CANT_INITIALIZE_UDF = 1123 -UDF_NO_PATHS = 1124 -UDF_EXISTS = 1125 -CANT_OPEN_LIBRARY = 1126 -CANT_FIND_DL_ENTRY = 1127 -FUNCTION_NOT_DEFINED = 1128 -HOST_IS_BLOCKED = 1129 -HOST_NOT_PRIVILEGED = 1130 -PASSWORD_ANONYMOUS_USER = 1131 -PASSWORD_NOT_ALLOWED = 1132 -PASSWORD_NO_MATCH = 1133 -UPDATE_INFO = 1134 -CANT_CREATE_THREAD = 1135 -WRONG_VALUE_COUNT_ON_ROW = 1136 -CANT_REOPEN_TABLE = 1137 -INVALID_USE_OF_NULL = 1138 -REGEXP_ERROR = 1139 -MIX_OF_GROUP_FUNC_AND_FIELDS = 1140 -NONEXISTING_GRANT = 1141 -TABLEACCESS_DENIED_ERROR = 1142 -COLUMNACCESS_DENIED_ERROR = 1143 -ILLEGAL_GRANT_FOR_TABLE = 1144 -GRANT_WRONG_HOST_OR_USER = 1145 -NO_SUCH_TABLE = 1146 -NONEXISTING_TABLE_GRANT = 1147 -NOT_ALLOWED_COMMAND = 1148 -SYNTAX_ERROR = 1149 -DELAYED_CANT_CHANGE_LOCK = 1150 -TOO_MANY_DELAYED_THREADS = 1151 -ABORTING_CONNECTION = 1152 -NET_PACKET_TOO_LARGE = 1153 -NET_READ_ERROR_FROM_PIPE = 1154 -NET_FCNTL_ERROR = 1155 -NET_PACKETS_OUT_OF_ORDER = 1156 -NET_UNCOMPRESS_ERROR = 1157 -NET_READ_ERROR = 1158 -NET_READ_INTERRUPTED = 1159 -NET_ERROR_ON_WRITE = 1160 -NET_WRITE_INTERRUPTED = 1161 -TOO_LONG_STRING = 1162 -TABLE_CANT_HANDLE_BLOB = 1163 -TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164 -DELAYED_INSERT_TABLE_LOCKED = 1165 -WRONG_COLUMN_NAME = 1166 -WRONG_KEY_COLUMN = 1167 -WRONG_MRG_TABLE = 1168 -DUP_UNIQUE = 1169 -BLOB_KEY_WITHOUT_LENGTH = 1170 -PRIMARY_CANT_HAVE_NULL = 1171 -TOO_MANY_ROWS = 1172 -REQUIRES_PRIMARY_KEY = 1173 -NO_RAID_COMPILED = 1174 -UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175 -KEY_DOES_NOT_EXITS = 1176 -CHECK_NO_SUCH_TABLE = 1177 -CHECK_NOT_IMPLEMENTED = 1178 -CANT_DO_THIS_DURING_AN_TRANSACTION = 1179 -ERROR_DURING_COMMIT = 1180 -ERROR_DURING_ROLLBACK = 1181 -ERROR_DURING_FLUSH_LOGS = 1182 -ERROR_DURING_CHECKPOINT = 1183 -NEW_ABORTING_CONNECTION = 1184 -DUMP_NOT_IMPLEMENTED = 1185 -FLUSH_MASTER_BINLOG_CLOSED = 1186 -INDEX_REBUILD = 1187 -MASTER = 1188 -MASTER_NET_READ = 1189 -MASTER_NET_WRITE = 1190 -FT_MATCHING_KEY_NOT_FOUND = 1191 -LOCK_OR_ACTIVE_TRANSACTION = 1192 -UNKNOWN_SYSTEM_VARIABLE = 1193 -CRASHED_ON_USAGE = 1194 -CRASHED_ON_REPAIR = 1195 -WARNING_NOT_COMPLETE_ROLLBACK = 1196 -TRANS_CACHE_FULL = 1197 -SLAVE_MUST_STOP = 1198 -SLAVE_NOT_RUNNING = 1199 -BAD_SLAVE = 1200 -MASTER_INFO = 1201 -SLAVE_THREAD = 1202 -TOO_MANY_USER_CONNECTIONS = 1203 -SET_CONSTANTS_ONLY = 1204 -LOCK_WAIT_TIMEOUT = 1205 -LOCK_TABLE_FULL = 1206 -READ_ONLY_TRANSACTION = 1207 -DROP_DB_WITH_READ_LOCK = 1208 -CREATE_DB_WITH_READ_LOCK = 1209 -WRONG_ARGUMENTS = 1210 -NO_PERMISSION_TO_CREATE_USER = 1211 -UNION_TABLES_IN_DIFFERENT_DIR = 1212 -LOCK_DEADLOCK = 1213 -TABLE_CANT_HANDLE_FT = 1214 -CANNOT_ADD_FOREIGN = 1215 -NO_REFERENCED_ROW = 1216 -ROW_IS_REFERENCED = 1217 -CONNECT_TO_MASTER = 1218 -QUERY_ON_MASTER = 1219 -ERROR_WHEN_EXECUTING_COMMAND = 1220 -WRONG_USAGE = 1221 -WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222 -CANT_UPDATE_WITH_READLOCK = 1223 -MIXING_NOT_ALLOWED = 1224 -DUP_ARGUMENT = 1225 -USER_LIMIT_REACHED = 1226 -SPECIFIC_ACCESS_DENIED_ERROR = 1227 -LOCAL_VARIABLE = 1228 -GLOBAL_VARIABLE = 1229 -NO_DEFAULT = 1230 -WRONG_VALUE_FOR_VAR = 1231 -WRONG_TYPE_FOR_VAR = 1232 -VAR_CANT_BE_READ = 1233 -CANT_USE_OPTION_HERE = 1234 -NOT_SUPPORTED_YET = 1235 -MASTER_FATAL_ERROR_READING_BINLOG = 1236 -SLAVE_IGNORED_TABLE = 1237 -INCORRECT_GLOBAL_LOCAL_VAR = 1238 -WRONG_FK_DEF = 1239 -KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240 -OPERAND_COLUMNS = 1241 -SUBQUERY_NO_1_ROW = 1242 -UNKNOWN_STMT_HANDLER = 1243 -CORRUPT_HELP_DB = 1244 -CYCLIC_REFERENCE = 1245 -AUTO_CONVERT = 1246 -ILLEGAL_REFERENCE = 1247 -DERIVED_MUST_HAVE_ALIAS = 1248 -SELECT_REDUCED = 1249 -TABLENAME_NOT_ALLOWED_HERE = 1250 -NOT_SUPPORTED_AUTH_MODE = 1251 -SPATIAL_CANT_HAVE_NULL = 1252 -COLLATION_CHARSET_MISMATCH = 1253 -SLAVE_WAS_RUNNING = 1254 -SLAVE_WAS_NOT_RUNNING = 1255 -TOO_BIG_FOR_UNCOMPRESS = 1256 -ZLIB_Z_MEM_ERROR = 1257 -ZLIB_Z_BUF_ERROR = 1258 -ZLIB_Z_DATA_ERROR = 1259 -CUT_VALUE_GROUP_CONCAT = 1260 -WARN_TOO_FEW_RECORDS = 1261 -WARN_TOO_MANY_RECORDS = 1262 -WARN_NULL_TO_NOTNULL = 1263 -WARN_DATA_OUT_OF_RANGE = 1264 -WARN_DATA_TRUNCATED = 1265 -WARN_USING_OTHER_HANDLER = 1266 -CANT_AGGREGATE_2COLLATIONS = 1267 -DROP_USER = 1268 -REVOKE_GRANTS = 1269 -CANT_AGGREGATE_3COLLATIONS = 1270 -CANT_AGGREGATE_NCOLLATIONS = 1271 -VARIABLE_IS_NOT_STRUCT = 1272 -UNKNOWN_COLLATION = 1273 -SLAVE_IGNORED_SSL_PARAMS = 1274 -SERVER_IS_IN_SECURE_AUTH_MODE = 1275 -WARN_FIELD_RESOLVED = 1276 -BAD_SLAVE_UNTIL_COND = 1277 -MISSING_SKIP_SLAVE = 1278 -UNTIL_COND_IGNORED = 1279 -WRONG_NAME_FOR_INDEX = 1280 -WRONG_NAME_FOR_CATALOG = 1281 -WARN_QC_RESIZE = 1282 -BAD_FT_COLUMN = 1283 -UNKNOWN_KEY_CACHE = 1284 -WARN_HOSTNAME_WONT_WORK = 1285 -UNKNOWN_STORAGE_ENGINE = 1286 -WARN_DEPRECATED_SYNTAX = 1287 -NON_UPDATABLE_TABLE = 1288 -FEATURE_DISABLED = 1289 -OPTION_PREVENTS_STATEMENT = 1290 -DUPLICATED_VALUE_IN_TYPE = 1291 -TRUNCATED_WRONG_VALUE = 1292 -TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293 -INVALID_ON_UPDATE = 1294 -UNSUPPORTED_PS = 1295 -GET_ERRMSG = 1296 -GET_TEMPORARY_ERRMSG = 1297 -UNKNOWN_TIME_ZONE = 1298 -WARN_INVALID_TIMESTAMP = 1299 -INVALID_CHARACTER_STRING = 1300 -WARN_ALLOWED_PACKET_OVERFLOWED = 1301 -CONFLICTING_DECLARATIONS = 1302 -SP_NO_RECURSIVE_CREATE = 1303 -SP_ALREADY_EXISTS = 1304 -SP_DOES_NOT_EXIST = 1305 -SP_DROP_FAILED = 1306 -SP_STORE_FAILED = 1307 -SP_LILABEL_MISMATCH = 1308 -SP_LABEL_REDEFINE = 1309 -SP_LABEL_MISMATCH = 1310 -SP_UNINIT_VAR = 1311 -SP_BADSELECT = 1312 -SP_BADRETURN = 1313 -SP_BADSTATEMENT = 1314 -UPDATE_LOG_DEPRECATED_IGNORED = 1315 -UPDATE_LOG_DEPRECATED_TRANSLATED = 1316 -QUERY_INTERRUPTED = 1317 -SP_WRONG_NO_OF_ARGS = 1318 -SP_COND_MISMATCH = 1319 -SP_NORETURN = 1320 -SP_NORETURNEND = 1321 -SP_BAD_CURSOR_QUERY = 1322 -SP_BAD_CURSOR_SELECT = 1323 -SP_CURSOR_MISMATCH = 1324 -SP_CURSOR_ALREADY_OPEN = 1325 -SP_CURSOR_NOT_OPEN = 1326 -SP_UNDECLARED_VAR = 1327 -SP_WRONG_NO_OF_FETCH_ARGS = 1328 -SP_FETCH_NO_DATA = 1329 -SP_DUP_PARAM = 1330 -SP_DUP_VAR = 1331 -SP_DUP_COND = 1332 -SP_DUP_CURS = 1333 -SP_CANT_ALTER = 1334 -SP_SUBSELECT_NYI = 1335 -STMT_NOT_ALLOWED_IN_SF_OR_TRG = 1336 -SP_VARCOND_AFTER_CURSHNDLR = 1337 -SP_CURSOR_AFTER_HANDLER = 1338 -SP_CASE_NOT_FOUND = 1339 -FPARSER_TOO_BIG_FILE = 1340 -FPARSER_BAD_HEADER = 1341 -FPARSER_EOF_IN_COMMENT = 1342 -FPARSER_ERROR_IN_PARAMETER = 1343 -FPARSER_EOF_IN_UNKNOWN_PARAMETER = 1344 -VIEW_NO_EXPLAIN = 1345 -FRM_UNKNOWN_TYPE = 1346 -WRONG_OBJECT = 1347 -NONUPDATEABLE_COLUMN = 1348 -VIEW_SELECT_DERIVED = 1349 -VIEW_SELECT_CLAUSE = 1350 -VIEW_SELECT_VARIABLE = 1351 -VIEW_SELECT_TMPTABLE = 1352 -VIEW_WRONG_LIST = 1353 -WARN_VIEW_MERGE = 1354 -WARN_VIEW_WITHOUT_KEY = 1355 -VIEW_INVALID = 1356 -SP_NO_DROP_SP = 1357 -SP_GOTO_IN_HNDLR = 1358 -TRG_ALREADY_EXISTS = 1359 -TRG_DOES_NOT_EXIST = 1360 -TRG_ON_VIEW_OR_TEMP_TABLE = 1361 -TRG_CANT_CHANGE_ROW = 1362 -TRG_NO_SUCH_ROW_IN_TRG = 1363 -NO_DEFAULT_FOR_FIELD = 1364 -DIVISION_BY_ZERO = 1365 -TRUNCATED_WRONG_VALUE_FOR_FIELD = 1366 -ILLEGAL_VALUE_FOR_TYPE = 1367 -VIEW_NONUPD_CHECK = 1368 -VIEW_CHECK_FAILED = 1369 -PROCACCESS_DENIED_ERROR = 1370 -RELAY_LOG_FAIL = 1371 -PASSWD_LENGTH = 1372 -UNKNOWN_TARGET_BINLOG = 1373 -IO_ERR_LOG_INDEX_READ = 1374 -BINLOG_PURGE_PROHIBITED = 1375 -FSEEK_FAIL = 1376 -BINLOG_PURGE_FATAL_ERR = 1377 -LOG_IN_USE = 1378 -LOG_PURGE_UNKNOWN_ERR = 1379 -RELAY_LOG_INIT = 1380 -NO_BINARY_LOGGING = 1381 -RESERVED_SYNTAX = 1382 -WSAS_FAILED = 1383 -DIFF_GROUPS_PROC = 1384 -NO_GROUP_FOR_PROC = 1385 -ORDER_WITH_PROC = 1386 -LOGGING_PROHIBIT_CHANGING_OF = 1387 -NO_FILE_MAPPING = 1388 -WRONG_MAGIC = 1389 -PS_MANY_PARAM = 1390 -KEY_PART_0 = 1391 -VIEW_CHECKSUM = 1392 -VIEW_MULTIUPDATE = 1393 -VIEW_NO_INSERT_FIELD_LIST = 1394 -VIEW_DELETE_MERGE_VIEW = 1395 -CANNOT_USER = 1396 -XAER_NOTA = 1397 -XAER_INVAL = 1398 -XAER_RMFAIL = 1399 -XAER_OUTSIDE = 1400 -XAER_RMERR = 1401 -XA_RBROLLBACK = 1402 -NONEXISTING_PROC_GRANT = 1403 -PROC_AUTO_GRANT_FAIL = 1404 -PROC_AUTO_REVOKE_FAIL = 1405 -DATA_TOO_LONG = 1406 -SP_BAD_SQLSTATE = 1407 -STARTUP = 1408 -LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR = 1409 -CANT_CREATE_USER_WITH_GRANT = 1410 -WRONG_VALUE_FOR_TYPE = 1411 -TABLE_DEF_CHANGED = 1412 -SP_DUP_HANDLER = 1413 -SP_NOT_VAR_ARG = 1414 -SP_NO_RETSET = 1415 -CANT_CREATE_GEOMETRY_OBJECT = 1416 -FAILED_ROUTINE_BREAK_BINLOG = 1417 -BINLOG_UNSAFE_ROUTINE = 1418 -BINLOG_CREATE_ROUTINE_NEED_SUPER = 1419 -EXEC_STMT_WITH_OPEN_CURSOR = 1420 -STMT_HAS_NO_OPEN_CURSOR = 1421 -COMMIT_NOT_ALLOWED_IN_SF_OR_TRG = 1422 -NO_DEFAULT_FOR_VIEW_FIELD = 1423 -SP_NO_RECURSION = 1424 -TOO_BIG_SCALE = 1425 -TOO_BIG_PRECISION = 1426 -M_BIGGER_THAN_D = 1427 -WRONG_LOCK_OF_SYSTEM_TABLE = 1428 -CONNECT_TO_FOREIGN_DATA_SOURCE = 1429 -QUERY_ON_FOREIGN_DATA_SOURCE = 1430 -FOREIGN_DATA_SOURCE_DOESNT_EXIST = 1431 -FOREIGN_DATA_STRING_INVALID_CANT_CREATE = 1432 -FOREIGN_DATA_STRING_INVALID = 1433 -CANT_CREATE_FEDERATED_TABLE = 1434 -TRG_IN_WRONG_SCHEMA = 1435 -STACK_OVERRUN_NEED_MORE = 1436 -TOO_LONG_BODY = 1437 -WARN_CANT_DROP_DEFAULT_KEYCACHE = 1438 -TOO_BIG_DISPLAYWIDTH = 1439 -XAER_DUPID = 1440 -DATETIME_FUNCTION_OVERFLOW = 1441 -CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG = 1442 -VIEW_PREVENT_UPDATE = 1443 -PS_NO_RECURSION = 1444 -SP_CANT_SET_AUTOCOMMIT = 1445 -MALFORMED_DEFINER = 1446 -VIEW_FRM_NO_USER = 1447 -VIEW_OTHER_USER = 1448 -NO_SUCH_USER = 1449 -FORBID_SCHEMA_CHANGE = 1450 -ROW_IS_REFERENCED_2 = 1451 -NO_REFERENCED_ROW_2 = 1452 -SP_BAD_VAR_SHADOW = 1453 -TRG_NO_DEFINER = 1454 -OLD_FILE_FORMAT = 1455 -SP_RECURSION_LIMIT = 1456 -SP_PROC_TABLE_CORRUPT = 1457 -ERROR_LAST = 1457 - diff --git a/MySQLdb/MySQLdb/constants/FIELD_TYPE.py b/MySQLdb/MySQLdb/constants/FIELD_TYPE.py deleted file mode 100644 index 8a57b17..0000000 --- a/MySQLdb/MySQLdb/constants/FIELD_TYPE.py +++ /dev/null @@ -1,37 +0,0 @@ -"""MySQL FIELD_TYPE Constants - -These constants represent the various column (field) types that are -supported by MySQL. - -""" - -DECIMAL = 0 -TINY = 1 -SHORT = 2 -LONG = 3 -FLOAT = 4 -DOUBLE = 5 -NULL = 6 -TIMESTAMP = 7 -LONGLONG = 8 -INT24 = 9 -DATE = 10 -TIME = 11 -DATETIME = 12 -YEAR = 13 -NEWDATE = 14 -VARCHAR = 15 -BIT = 16 -NEWDECIMAL = 246 -ENUM = 247 -SET = 248 -TINY_BLOB = 249 -MEDIUM_BLOB = 250 -LONG_BLOB = 251 -BLOB = 252 -VAR_STRING = 253 -STRING = 254 -GEOMETRY = 255 - -CHAR = TINY -INTERVAL = ENUM diff --git a/MySQLdb/MySQLdb/constants/FLAG.py b/MySQLdb/MySQLdb/constants/FLAG.py deleted file mode 100644 index 00e6c7c..0000000 --- a/MySQLdb/MySQLdb/constants/FLAG.py +++ /dev/null @@ -1,23 +0,0 @@ -"""MySQL FLAG Constants - -These flags are used along with the FIELD_TYPE to indicate various -properties of columns in a result set. - -""" - -NOT_NULL = 1 -PRI_KEY = 2 -UNIQUE_KEY = 4 -MULTIPLE_KEY = 8 -BLOB = 16 -UNSIGNED = 32 -ZEROFILL = 64 -BINARY = 128 -ENUM = 256 -AUTO_INCREMENT = 512 -TIMESTAMP = 1024 -SET = 2048 -NUM = 32768 -PART_KEY = 16384 -GROUP = 32768 -UNIQUE = 65536 diff --git a/MySQLdb/MySQLdb/constants/REFRESH.py b/MySQLdb/MySQLdb/constants/REFRESH.py deleted file mode 100644 index 4a08b94..0000000 --- a/MySQLdb/MySQLdb/constants/REFRESH.py +++ /dev/null @@ -1,17 +0,0 @@ -"""MySQL REFRESH Constants - -These constants seem to mostly deal with things internal to the -MySQL server. Forget you saw this. - -""" - -GRANT = 1 -LOG = 2 -TABLES = 4 -HOSTS = 8 -STATUS = 16 -THREADS = 32 -SLAVE = 64 -MASTER = 128 -READ_LOCK = 16384 -FAST = 32768 diff --git a/MySQLdb/MySQLdb/constants/__init__.py b/MySQLdb/MySQLdb/constants/__init__.py deleted file mode 100644 index 3da4a0e..0000000 --- a/MySQLdb/MySQLdb/constants/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__all__ = ['CR', 'FIELD_TYPE','CLIENT','REFRESH','ER','FLAG'] diff --git a/MySQLdb/MySQLdb/converters.py b/MySQLdb/MySQLdb/converters.py deleted file mode 100644 index 14b1f52..0000000 --- a/MySQLdb/MySQLdb/converters.py +++ /dev/null @@ -1,181 +0,0 @@ -"""MySQLdb type conversion module - -This module handles all the type conversions for MySQL. If the default -type conversions aren't what you need, you can make your own. The -dictionary conversions maps some kind of type to a conversion function -which returns the corresponding value: - -Key: FIELD_TYPE.* (from MySQLdb.constants) - -Conversion function: - - Arguments: string - - Returns: Python object - -Key: Python type object (from types) or class - -Conversion function: - - Arguments: Python object of indicated type or class AND - conversion dictionary - - Returns: SQL literal value - - Notes: Most conversion functions can ignore the dictionary, but - it is a required parameter. It is necessary for converting - things like sequences and instances. - -Don't modify conversions if you can avoid it. Instead, make copies -(with the copy() method), modify the copies, and then pass them to -MySQL.connect(). - -""" - -from _mysql import string_literal, escape_sequence, escape_dict, escape, NULL -from MySQLdb.constants import FIELD_TYPE, FLAG -from MySQLdb.times import * - -try: - from types import IntType, LongType, FloatType, NoneType, TupleType, ListType, DictType, InstanceType, \ - StringType, UnicodeType, ObjectType, BooleanType, ClassType, TypeType -except ImportError: - # Python 3 - long = int - IntType, LongType, FloatType, NoneType = int, long, float, type(None) - TupleType, ListType, DictType, InstanceType = tuple, list, dict, None - StringType, UnicodeType, ObjectType, BooleanType = bytes, str, object, bool - -import array - -try: - set -except NameError: - from sets import Set as set - -def Bool2Str(s, d): return str(int(s)) - -def Str2Set(s): - return set([ i for i in s.split(',') if i ]) - -def Set2Str(s, d): - return string_literal(','.join(s), d) - -def Thing2Str(s, d): - """Convert something into a string via str().""" - return str(s) - -def Unicode2Str(s, d): - """Convert a unicode object to a string using the default encoding. - This is only used as a placeholder for the real function, which - is connection-dependent.""" - return s.encode() - -Long2Int = Thing2Str - -def Float2Str(o, d): - return '%.15g' % o - -def None2NULL(o, d): - """Convert None to NULL.""" - return NULL # duh - -def Thing2Literal(o, d): - - """Convert something into a SQL string literal. If using - MySQL-3.23 or newer, string_literal() is a method of the - _mysql.MYSQL object, and this function will be overridden with - that method when the connection is created.""" - - return string_literal(o, d) - - -def Instance2Str(o, d): - - """ - - Convert an Instance to a string representation. If the __str__() - method produces acceptable output, then you don't need to add the - class to conversions; it will be handled by the default - converter. If the exact class is not found in d, it will use the - first class it can find for which o is an instance. - - """ - - if o.__class__ in d: - return d[o.__class__](o, d) - cl = filter(lambda x,o=o: - type(x) is ClassType - and isinstance(o, x), d.keys()) - if not cl and hasattr(types, 'ObjectType'): - cl = filter(lambda x,o=o: - type(x) is TypeType - and isinstance(o, x) - and d[x] is not Instance2Str, - d.keys()) - if not cl: - return d[types.StringType](o,d) - d[o.__class__] = d[cl[0]] - return d[cl[0]](o, d) - -def char_array(s): - return array.array('c', s) - -def array2Str(o, d): - return Thing2Literal(o.tostring(), d) - -conversions = { - IntType: Thing2Str, - LongType: Long2Int, - FloatType: Float2Str, - NoneType: None2NULL, - TupleType: escape_sequence, - ListType: escape_sequence, - DictType: escape_dict, - InstanceType: Instance2Str, - array.ArrayType: array2Str, - StringType: Thing2Literal, # default - UnicodeType: Unicode2Str, - ObjectType: Instance2Str, - BooleanType: Bool2Str, - DateTimeType: DateTime2literal, - DateTimeDeltaType: DateTimeDelta2literal, - set: Set2Str, - FIELD_TYPE.TINY: int, - FIELD_TYPE.SHORT: int, - FIELD_TYPE.LONG: long, - FIELD_TYPE.FLOAT: float, - FIELD_TYPE.DOUBLE: float, - FIELD_TYPE.DECIMAL: float, - FIELD_TYPE.NEWDECIMAL: float, - FIELD_TYPE.LONGLONG: long, - FIELD_TYPE.INT24: int, - FIELD_TYPE.YEAR: int, - FIELD_TYPE.SET: Str2Set, - FIELD_TYPE.TIMESTAMP: mysql_timestamp_converter, - FIELD_TYPE.DATETIME: DateTime_or_None, - FIELD_TYPE.TIME: TimeDelta_or_None, - FIELD_TYPE.DATE: Date_or_None, - FIELD_TYPE.BLOB: [ - (FLAG.BINARY, str), - ], - FIELD_TYPE.STRING: [ - (FLAG.BINARY, str), - ], - FIELD_TYPE.VAR_STRING: [ - (FLAG.BINARY, str), - ], - FIELD_TYPE.VARCHAR: [ - (FLAG.BINARY, str), - ], - } - -try: - from decimal import Decimal - conversions[FIELD_TYPE.DECIMAL] = Decimal - conversions[FIELD_TYPE.NEWDECIMAL] = Decimal -except ImportError: - pass - - - diff --git a/MySQLdb/MySQLdb/cursors.py b/MySQLdb/MySQLdb/cursors.py deleted file mode 100644 index a8cfa3e..0000000 --- a/MySQLdb/MySQLdb/cursors.py +++ /dev/null @@ -1,533 +0,0 @@ -"""MySQLdb Cursors - -This module implements Cursors of various types for MySQLdb. By -default, MySQLdb uses the Cursor class. - -""" - -import re -import sys -try: - from types import ListType, TupleType, UnicodeType -except ImportError: - # Python 3 - ListType = list - TupleType = tuple - UnicodeType = str - -restr = r""" - \s - values - \s* - ( - \( - [^()']* - (?: - (?: - (?:\( - # ( - editor hightlighting helper - [^)]* - \)) - | - ' - [^\\']* - (?:\\.[^\\']*)* - ' - ) - [^()']* - )* - \) - ) -""" - -insert_values = re.compile(restr, re.S | re.I | re.X) - -from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ - DatabaseError, OperationalError, IntegrityError, InternalError, \ - NotSupportedError, ProgrammingError - - -class BaseCursor(object): - - """A base for Cursor classes. Useful attributes: - - description - A tuple of DB API 7-tuples describing the columns in - the last executed query; see PEP-249 for details. - - description_flags - Tuple of column flags for last query, one entry per column - in the result set. Values correspond to those in - MySQLdb.constants.FLAG. See MySQL documentation (C API) - for more information. Non-standard extension. - - arraysize - default number of rows fetchmany() will fetch - - """ - - from _mysql_exceptions import MySQLError, Warning, Error, InterfaceError, \ - DatabaseError, DataError, OperationalError, IntegrityError, \ - InternalError, ProgrammingError, NotSupportedError - - _defer_warnings = False - - def __init__(self, connection): - from weakref import proxy - - self.connection = proxy(connection) - self.description = None - self.description_flags = None - self.rowcount = -1 - self.arraysize = 1 - self._executed = None - self.lastrowid = None - self.messages = [] - self.errorhandler = connection.errorhandler - self._result = None - self._warnings = 0 - self._info = None - self.rownumber = None - - def __del__(self): - self.close() - self.errorhandler = None - self._result = None - - def close(self): - """Close the cursor. No further queries will be possible.""" - if not self.connection: return - while self.nextset(): pass - self.connection = None - - def _check_executed(self): - if not self._executed: - self.errorhandler(self, ProgrammingError, "execute() first") - - def _warning_check(self): - from warnings import warn - if self._warnings: - warnings = self._get_db().show_warnings() - if warnings: - # This is done in two loops in case - # Warnings are set to raise exceptions. - for w in warnings: - self.messages.append((self.Warning, w)) - for w in warnings: - warn(w[-1], self.Warning, 3) - elif self._info: - self.messages.append((self.Warning, self._info)) - warn(self._info, self.Warning, 3) - - def nextset(self): - """Advance to the next result set. - - Returns None if there are no more result sets. - """ - if self._executed: - self.fetchall() - del self.messages[:] - - db = self._get_db() - nr = db.next_result() - if nr == -1: - return None - self._do_get_result() - self._post_get_result() - self._warning_check() - return 1 - - def _post_get_result(self): pass - - def _do_get_result(self): - db = self._get_db() - self._result = self._get_result() - self.rowcount = db.affected_rows() - self.rownumber = 0 - self.description = self._result and self._result.describe() or None - self.description_flags = self._result and self._result.field_flags() or None - self.lastrowid = db.insert_id() - self._warnings = db.warning_count() - self._info = db.info() - - def setinputsizes(self, *args): - """Does nothing, required by DB API.""" - - def setoutputsizes(self, *args): - """Does nothing, required by DB API.""" - - def _get_db(self): - if not self.connection: - self.errorhandler(self, ProgrammingError, "cursor closed") - return self.connection - - def execute(self, query, args=None): - - """Execute a query. - - query -- string, query to execute on server - args -- optional sequence or mapping, parameters to use with query. - - Note: If args is a sequence, then %s must be used as the - parameter placeholder in the query. If a mapping is used, - %(key)s must be used as the placeholder. - - Returns long integer rows affected, if any - - """ - del self.messages[:] - db = self._get_db() - charset = db.character_set_name() - if isinstance(query, unicode): - query = query.encode(charset) - if args is not None: - query = query % db.literal(args) - try: - r = None - r = self._query(query) - except TypeError, m: - if m.args[0] in ("not enough arguments for format string", - "not all arguments converted"): - self.messages.append((ProgrammingError, m.args[0])) - self.errorhandler(self, ProgrammingError, m.args[0]) - else: - self.messages.append((TypeError, m)) - self.errorhandler(self, TypeError, m) - except (SystemExit, KeyboardInterrupt): - raise - except: - exc, value, tb = sys.exc_info() - del tb - self.messages.append((exc, value)) - self.errorhandler(self, exc, value) - self._executed = query - if not self._defer_warnings: self._warning_check() - return r - - def executemany(self, query, args): - - """Execute a multi-row query. - - query -- string, query to execute on server - - args - - Sequence of sequences or mappings, parameters to use with - query. - - Returns long integer rows affected, if any. - - This method improves performance on multiple-row INSERT and - REPLACE. Otherwise it is equivalent to looping over args with - execute(). - - """ - del self.messages[:] - db = self._get_db() - if not args: return - charset = db.character_set_name() - if isinstance(query, unicode): query = query.encode(charset) - m = insert_values.search(query) - if not m: - r = 0 - for a in args: - r = r + self.execute(query, a) - return r - p = m.start(1) - e = m.end(1) - qv = m.group(1) - try: - q = [ qv % db.literal(a) for a in args ] - except TypeError, msg: - if msg.args[0] in ("not enough arguments for format string", - "not all arguments converted"): - self.errorhandler(self, ProgrammingError, msg.args[0]) - else: - self.errorhandler(self, TypeError, msg) - except (SystemExit, KeyboardInterrupt): - raise - except: - exc, value, tb = sys.exc_info() - del tb - self.errorhandler(self, exc, value) - r = self._query('\n'.join([query[:p], ',\n'.join(q), query[e:]])) - if not self._defer_warnings: self._warning_check() - return r - - def callproc(self, procname, args=()): - - """Execute stored procedure procname with args - - procname -- string, name of procedure to execute on server - - args -- Sequence of parameters to use with procedure - - Returns the original args. - - 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 .execute() to get any OUT or INOUT values. - - 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 nextset() - to advance through all result sets; otherwise you may get - disconnected. - """ - - db = self._get_db() - charset = db.character_set_name() - for index, arg in enumerate(args): - q = "SET @_%s_%d=%s" % (procname, index, - db.literal(arg)) - if isinstance(q, unicode): - q = q.encode(charset) - self._query(q) - self.nextset() - - q = "CALL %s(%s)" % (procname, - ','.join(['@_%s_%d' % (procname, i) - for i in range(len(args))])) - if type(q) is UnicodeType: - q = q.encode(charset) - self._query(q) - self._executed = q - if not self._defer_warnings: self._warning_check() - return args - - def _do_query(self, q): - db = self._get_db() - self._last_executed = q - db.query(q) - self._do_get_result() - return self.rowcount - - def _query(self, q): return self._do_query(q) - - def _fetch_row(self, size=1): - if not self._result: - return () - return self._result.fetch_row(size, self._fetch_type) - - def __iter__(self): - return iter(self.fetchone, None) - - Warning = Warning - Error = Error - InterfaceError = InterfaceError - DatabaseError = DatabaseError - DataError = DataError - OperationalError = OperationalError - IntegrityError = IntegrityError - InternalError = InternalError - ProgrammingError = ProgrammingError - NotSupportedError = NotSupportedError - - -class CursorStoreResultMixIn(object): - - """This is a MixIn class which causes the entire result set to be - stored on the client side, i.e. it uses mysql_store_result(). If the - result set can be very large, consider adding a LIMIT clause to your - query, or using CursorUseResultMixIn instead.""" - - def _get_result(self): return self._get_db().store_result() - - def _query(self, q): - rowcount = self._do_query(q) - self._post_get_result() - return rowcount - - def _post_get_result(self): - self._rows = self._fetch_row(0) - self._result = None - - def fetchone(self): - """Fetches a single row from the cursor. None indicates that - no more rows are available.""" - self._check_executed() - if self.rownumber >= len(self._rows): return None - result = self._rows[self.rownumber] - self.rownumber = self.rownumber+1 - return result - - def fetchmany(self, size=None): - """Fetch up to size rows from the cursor. Result set may be smaller - than size. If size is not defined, cursor.arraysize is used.""" - self._check_executed() - end = self.rownumber + (size or self.arraysize) - result = self._rows[self.rownumber:end] - self.rownumber = min(end, len(self._rows)) - return result - - def fetchall(self): - """Fetchs all available rows from the cursor.""" - self._check_executed() - if self.rownumber: - result = self._rows[self.rownumber:] - else: - result = self._rows - self.rownumber = len(self._rows) - return result - - def scroll(self, value, mode='relative'): - """Scroll the cursor in the result set to a new position according - to mode. - - 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.""" - self._check_executed() - if mode == 'relative': - r = self.rownumber + value - elif mode == 'absolute': - r = value - else: - self.errorhandler(self, ProgrammingError, - "unknown scroll mode %s" % repr(mode)) - if r < 0 or r >= len(self._rows): - self.errorhandler(self, IndexError, "out of range") - self.rownumber = r - - def __iter__(self): - self._check_executed() - result = self.rownumber and self._rows[self.rownumber:] or self._rows - return iter(result) - - -class CursorUseResultMixIn(object): - - """This is a MixIn class which causes the result set to be stored - in the server and sent row-by-row to client side, i.e. it uses - mysql_use_result(). You MUST retrieve the entire result set and - close() the cursor before additional queries can be peformed on - the connection.""" - - _defer_warnings = True - - def _get_result(self): return self._get_db().use_result() - - def fetchone(self): - """Fetches a single row from the cursor.""" - self._check_executed() - r = self._fetch_row(1) - if not r: - self._warning_check() - return None - self.rownumber = self.rownumber + 1 - return r[0] - - def fetchmany(self, size=None): - """Fetch up to size rows from the cursor. Result set may be smaller - than size. If size is not defined, cursor.arraysize is used.""" - self._check_executed() - r = self._fetch_row(size or self.arraysize) - self.rownumber = self.rownumber + len(r) - if not r: - self._warning_check() - return r - - def fetchall(self): - """Fetchs all available rows from the cursor.""" - self._check_executed() - r = self._fetch_row(0) - self.rownumber = self.rownumber + len(r) - self._warning_check() - return r - - def __iter__(self): - return self - - def next(self): - row = self.fetchone() - if row is None: - raise StopIteration - return row - - -class CursorTupleRowsMixIn(object): - - """This is a MixIn class that causes all rows to be returned as tuples, - which is the standard form required by DB API.""" - - _fetch_type = 0 - - -class CursorDictRowsMixIn(object): - - """This is a MixIn class that causes all rows to be returned as - dictionaries. This is a non-standard feature.""" - - _fetch_type = 1 - - def fetchoneDict(self): - """Fetch a single row as a dictionary. Deprecated: - Use fetchone() instead. Will be removed in 1.3.""" - from warnings import warn - warn("fetchoneDict() is non-standard and will be removed in 1.3", - DeprecationWarning, 2) - return self.fetchone() - - def fetchmanyDict(self, size=None): - """Fetch several rows as a list of dictionaries. Deprecated: - Use fetchmany() instead. Will be removed in 1.3.""" - from warnings import warn - warn("fetchmanyDict() is non-standard and will be removed in 1.3", - DeprecationWarning, 2) - return self.fetchmany(size) - - def fetchallDict(self): - """Fetch all available rows as a list of dictionaries. Deprecated: - Use fetchall() instead. Will be removed in 1.3.""" - from warnings import warn - warn("fetchallDict() is non-standard and will be removed in 1.3", - DeprecationWarning, 2) - return self.fetchall() - - -class CursorOldDictRowsMixIn(CursorDictRowsMixIn): - - """This is a MixIn class that returns rows as dictionaries with - the same key convention as the old Mysqldb (MySQLmodule). Don't - use this.""" - - _fetch_type = 2 - - -class Cursor(CursorStoreResultMixIn, CursorTupleRowsMixIn, - BaseCursor): - - """This is the standard Cursor class that returns rows as tuples - and stores the result set in the client.""" - - -class DictCursor(CursorStoreResultMixIn, CursorDictRowsMixIn, - BaseCursor): - - """This is a Cursor class that returns rows as dictionaries and - stores the result set in the client.""" - - -class SSCursor(CursorUseResultMixIn, CursorTupleRowsMixIn, - BaseCursor): - - """This is a Cursor class that returns rows as tuples and stores - the result set in the server.""" - - -class SSDictCursor(CursorUseResultMixIn, CursorDictRowsMixIn, - BaseCursor): - - """This is a Cursor class that returns rows as dictionaries and - stores the result set in the server.""" - - diff --git a/MySQLdb/MySQLdb/release.py b/MySQLdb/MySQLdb/release.py deleted file mode 100644 index d0767e1..0000000 --- a/MySQLdb/MySQLdb/release.py +++ /dev/null @@ -1,4 +0,0 @@ - -__author__ = "Andy Dustman " -version_info = (1,2,4,'beta',3) -__version__ = "1.2.4b3" diff --git a/MySQLdb/MySQLdb/times.py b/MySQLdb/MySQLdb/times.py deleted file mode 100644 index bc92eb4..0000000 --- a/MySQLdb/MySQLdb/times.py +++ /dev/null @@ -1,111 +0,0 @@ -"""times module - -This module provides some Date and Time classes for dealing with MySQL data. - -Use Python datetime module to handle date and time columns.""" - -import math -from time import localtime -from datetime import date, datetime, time, timedelta -from _mysql import string_literal - -Date = date -Time = time -TimeDelta = timedelta -Timestamp = datetime - -DateTimeDeltaType = timedelta -DateTimeType = datetime - -def DateFromTicks(ticks): - """Convert UNIX ticks into a date instance.""" - return date(*localtime(ticks)[:3]) - -def TimeFromTicks(ticks): - """Convert UNIX ticks into a time instance.""" - return time(*localtime(ticks)[3:6]) - -def TimestampFromTicks(ticks): - """Convert UNIX ticks into a datetime instance.""" - return datetime(*localtime(ticks)[:6]) - -format_TIME = format_DATE = str - -def format_TIMEDELTA(v): - seconds = int(v.seconds) % 60 - minutes = int(v.seconds / 60) % 60 - hours = int(v.seconds / 3600) % 24 - return '%d %d:%d:%d' % (v.days, hours, minutes, seconds) - -def format_TIMESTAMP(d): - return d.isoformat(" ") - - -def DateTime_or_None(s): - if ' ' in s: - sep = ' ' - elif 'T' in s: - sep = 'T' - else: - return Date_or_None(s) - - try: - d, t = s.split(sep, 1) - return datetime(*[ int(x) for x in d.split('-')+t.split(':') ]) - except (SystemExit, KeyboardInterrupt): - raise - except: - return Date_or_None(s) - -def TimeDelta_or_None(s): - try: - h, m, s = s.split(':') - h, m, s = int(h), int(m), float(s) - td = timedelta(hours=abs(h), minutes=m, seconds=int(s), - microseconds=int(math.modf(s)[0] * 1000000)) - if h < 0: - return -td - else: - return td - except ValueError: - # unpacking or int/float conversion failed - return None - -def Time_or_None(s): - try: - h, m, s = s.split(':') - h, m, s = int(h), int(m), float(s) - return time(hour=h, minute=m, second=int(s), - microsecond=int(math.modf(s)[0] * 1000000)) - except ValueError: - return None - -def Date_or_None(s): - try: - return date(*[ int(x) for x in s.split('-',2)]) - except (SystemExit, KeyboardInterrupt): - raise - except: - return None - -def DateTime2literal(d, c): - """Format a DateTime object as an ISO timestamp.""" - return string_literal(format_TIMESTAMP(d),c) - -def DateTimeDelta2literal(d, c): - """Format a DateTimeDelta object as a time.""" - return string_literal(format_TIMEDELTA(d),c) - -def mysql_timestamp_converter(s): - """Convert a MySQL TIMESTAMP to a Timestamp object.""" - # MySQL>4.1 returns TIMESTAMP in the same format as DATETIME - if s[4] == '-': return DateTime_or_None(s) - s = s + "0"*(14-len(s)) # padding - parts = map(int, filter(None, (s[:4],s[4:6],s[6:8], - s[8:10],s[10:12],s[12:14]))) - try: - return Timestamp(*parts) - except (SystemExit, KeyboardInterrupt): - raise - except: - return None diff --git a/MySQLdb/README b/MySQLdb/README deleted file mode 100644 index f44b410..0000000 --- a/MySQLdb/README +++ /dev/null @@ -1,253 +0,0 @@ -==================== -MySQLdb Installation -==================== - -.. contents:: -.. - -Prerequisites -------------- - -+ Python 2.3.4 or higher - - * http://www.python.org/ - - * Versions lower than 2.3 WON'T WORK. - - * 2.4 is the primary test environment. - - * Red Hat Linux: - - - Make sure you have the Python development headers and libraries - (python-devel). - -+ setuptools - - * http://pypi.python.org/pypi/setuptools - -+ MySQL 3.23.32 or higher - - * http://www.mysql.com/downloads/ - - * Versions lower than 3.22 definitely WON'T WORK. - - * Versions lower than 3.22.19 might not work. - - * MySQL-3.22 might work but isn't supported anymore. It's very old. - - * MySQL-3.23 ought to work, but it's pretty elderly. - - * MySQL-4.0 is supported, but not tested and slightly discouraged. - - * MySQL-4.1 is supported. The prepared statements API is not - supported, and won't be until MySQLdb-1.3 or 2.0, if ever. - - * MySQL-5.0 is supported and tested, including stored procedures. - - * MySQL-5.1 is supported (currently a release candidate) but untested. - It should work. - - * MySQL-6.0 is sorta-kinda-supported (currently alpha) but untested. - It should work. - - * Drizzle is a fork of MySQL. So far - the C API looks really similar except everything is renamed. - Drizzle support probably won't happen in 1.2. There may be have to - be an entirely different module, but still using DB-API. - - * MaxDB, formerly known as SAP DB (and maybe Adabas D?), is a - completely different animal. Use the sapdb.sql module that comes - with MaxDB. - - * Red Hat Linux packages: - - - mysql-devel to compile - - - mysql and/or mysql-devel to run - - * MySQL.com RPM packages: - - - MySQL-devel to compile - - - MySQL-shared if you want to use their shared - library. Otherwise you'll get a statically-linked module, - which may or may not be what you want. - - - MySQL-shared to run if you compiled with MySQL-shared installed - - * Transactions (particularly InnoDB tables) are supported for - MySQL-3.23 and up. You may need a special package from your vendor - with this support turned on. - -+ zlib - - * Required for MySQL-3.23 and newer. - - * Red Hat Linux - - - zlib-devel to compile - - - zlib to run - -+ openssl - - * May be needed for MySQL-4.0 or newer, depending on compilation - options. If you need it, you probably already have it. - - - you may need openssl-devel on some platforms - -+ C compiler - - * Most free software-based systems already have this, usually gcc. - - * Most commercial UNIX platforms also come with a C compiler, or - you can also use gcc. - - * If you have some Windows flavor, you usually have to pay extra - for this, or you can use Cygwin_. - -.. _Cygwin: http://www.cygwin.com/ - - -Building and installing ------------------------ - -The setup.py script uses mysql_config to find all compiler and linker -options, and should work as is on any POSIX-like platform, so long as -mysql_config is in your path. - -Depending on which version of MySQL you have, you may have the option -of using three different client libraries. To select the client library, -edit the [options] section of site.cfg: - - embedded - use embedded server library (libmysqld) if True; otherwise use - one of the client libraries (default). - - threadsafe - thread-safe client library (libmysqlclient_r) if True (default); - otherwise use non-thread-safe (libmysqlclient). You should - always use the thread-safe library if you have the option; - otherwise you *may* have problems. - - static - if True, try to link against a static library; otherwise link - against dynamic libraries (default). You may need static linking - to use the embedded server. - - -Finally, putting it together:: - - $ tar xfz MySQL-python-1.2.1.tar.gz - $ cd MySQL-python-1.2.1 - $ # edit site.cfg if necessary - $ python setup.py build - $ sudo python setup.py install # or su first - - -Windows -....... - -I don't do Windows. However if someone provides me with a package for -Windows, I'll make it available. Don't ask me for help with Windows -because I can't help you. - -Generally, though, running setup.py is similar to above:: - - C:\...> python setup.py install - C:\...> python setup.py bdist_wininst - -The latter example should build a Windows installer package, if you -have the correct tools. In any event, you *must* have a C compiler. -Additionally, you have to set an environment variable (mysqlroot) -which is the path to your MySQL installation. In theory, it would be -possible to get this information out of the registry, but like I said, -I don't do Windows, but I'll accept a patch that does this. - -On Windows, you will definitely have to edit site.cfg since there is -no mysql_config in the MySQL package. - - -Zope -.... - -If you are using a binary package of Zope, you need run setup.py with -the python executable that came with Zope. Otherwise, you'll install -into the wrong Python tree and Zope (ZMySQLDA) will not be able to -find _mysql. - - -Binary Packages ---------------- - -I don't plan to make binary packages any more. However, if someone -contributes one, I will make it available. Several OS vendors have -their own packages available. - - -RPMs -.... - -If you prefer to install RPMs, you can use the bdist_rpm command with -setup.py. This only builds the RPM; it does not install it. You may -want to use the --python=XXX option, where XXX is the name of the -Python executable, i.e. python, python2, python2.4; the default is -python. Using this will incorporate the Python executable name into -the package name for the RPM so you have install the package multiple -times if you need to support more than one version of Python. You can -also set this in setup.cfg. - - -Red Hat Linux -............. - -MySQL-python is pre-packaged in Red Hat Linux 7.x and newer. This -includes Fedora Core and Red Hat Enterprise Linux. You can also -build your own RPM packages as described above. - - -Debian GNU/Linux -................ - -Packaged as `python-mysqldb`_:: - - # apt-get install python-mysqldb - -Or use Synaptic. - -.. _`python-mysqldb`: http://packages.debian.org/python-mysqldb - - -Ubuntu -...... - -Same as with Debian. - - -Gentoo Linux -............ - -Packaged as `mysql-python`_. :: - - # emerge sync - # emerge mysql-python - # emerge zmysqlda # if you use Zope - -.. _`mysql-python`: http://packages.gentoo.org/search/?sstring=mysql-python - - -BSD -... - -MySQL-python is a ported package in FreeBSD, NetBSD, and OpenBSD, -although the name may vary to match OS conventions. - - -License -------- - -GPL or the original license based on Python 1.5.2's license. - - -:Author: Andy Dustman -:Revision: $Id$ diff --git a/MySQLdb/__init__.py b/MySQLdb/__init__.py new file mode 100644 index 0000000..8761671 --- /dev/null +++ b/MySQLdb/__init__.py @@ -0,0 +1,98 @@ +"""MySQLdb - A DB API v2.0 compatible interface to MySQL. + +This package is a wrapper around _mysql, which mostly implements the +MySQL C API. + +connect() -- connects to server + +See the C API specification and the MySQL documentation for more info +on other items. + +For information on how MySQLdb handles type conversion, see the +MySQLdb.converters module. + +""" + +__revision__ = """$Revision$"""[11:-2] +from MySQLdb.release import __version__, version_info, __author__ + +import _mysql + +if version_info != _mysql.version_info: + raise ImportError("this is MySQLdb version %s, but _mysql is version %r" % + (version_info, _mysql.version_info)) + +threadsafety = 1 +apilevel = "2.0" +paramstyle = "format" + +from _mysql import * +from MySQLdb.constants import FIELD_TYPE +from MySQLdb.times import Date, Time, Timestamp, \ + DateFromTicks, TimeFromTicks, TimestampFromTicks + +try: + frozenset +except NameError: + from sets import ImmutableSet as frozenset + +class DBAPISet(frozenset): + + """A special type of set for which A == x is true if A is a + DBAPISet and x is a member of that set.""" + + def __eq__(self, other): + if isinstance(other, DBAPISet): + return not self.difference(other) + return other in self + + +STRING = DBAPISet([FIELD_TYPE.ENUM, FIELD_TYPE.STRING, + FIELD_TYPE.VAR_STRING]) +BINARY = DBAPISet([FIELD_TYPE.BLOB, FIELD_TYPE.LONG_BLOB, + FIELD_TYPE.MEDIUM_BLOB, FIELD_TYPE.TINY_BLOB]) +NUMBER = DBAPISet([FIELD_TYPE.DECIMAL, FIELD_TYPE.DOUBLE, FIELD_TYPE.FLOAT, + FIELD_TYPE.INT24, FIELD_TYPE.LONG, FIELD_TYPE.LONGLONG, + FIELD_TYPE.TINY, FIELD_TYPE.YEAR]) +DATE = DBAPISet([FIELD_TYPE.DATE, FIELD_TYPE.NEWDATE]) +TIME = DBAPISet([FIELD_TYPE.TIME]) +TIMESTAMP = DBAPISet([FIELD_TYPE.TIMESTAMP, FIELD_TYPE.DATETIME]) +DATETIME = TIMESTAMP +ROWID = DBAPISet() + +def test_DBAPISet_set_equality(): + assert STRING == STRING + +def test_DBAPISet_set_inequality(): + assert STRING != NUMBER + +def test_DBAPISet_set_equality_membership(): + assert FIELD_TYPE.VAR_STRING == STRING + +def test_DBAPISet_set_inequality_membership(): + assert FIELD_TYPE.DATE != STRING + +def Binary(x): + return str(x) + +def Connect(*args, **kwargs): + """Factory function for connections.Connection.""" + from MySQLdb.connections import Connection + return Connection(*args, **kwargs) + +connect = Connection = Connect + +__all__ = [ 'BINARY', 'Binary', 'Connect', 'Connection', 'DATE', + 'Date', 'Time', 'Timestamp', 'DateFromTicks', 'TimeFromTicks', + 'TimestampFromTicks', 'DataError', 'DatabaseError', 'Error', + 'FIELD_TYPE', 'IntegrityError', 'InterfaceError', 'InternalError', + 'MySQLError', 'NULL', 'NUMBER', 'NotSupportedError', 'DBAPISet', + 'OperationalError', 'ProgrammingError', 'ROWID', 'STRING', 'TIME', + 'TIMESTAMP', 'Warning', 'apilevel', 'connect', 'connections', + 'constants', 'converters', 'cursors', 'debug', 'escape', 'escape_dict', + 'escape_sequence', 'escape_string', 'get_client_info', + 'paramstyle', 'string_literal', 'threadsafety', 'version_info'] + + + + diff --git a/MySQLdb/_mysql.c b/MySQLdb/_mysql.c deleted file mode 100644 index b721a66..0000000 --- a/MySQLdb/_mysql.c +++ /dev/null @@ -1,3105 +0,0 @@ -/* -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. Alternatively, you may use the original license -reproduced below. - -Copyright 1999 by Comstar.net, Inc., Atlanta, GA, US. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Comstar.net, Inc. -or COMSTAR not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior permission. - -COMSTAR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -EVENT SHALL COMSTAR BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "Python.h" -#if PY_MAJOR_VERSION >= 3 -#define IS_PY3K -#define PyInt_FromLong(n) PyLong_FromLong(n) -#define PyInt_Check(n) PyLong_Check(n) -#define PyInt_AS_LONG(n) PyLong_AS_LONG(n) -#endif -#if PY_VERSION_HEX > 0x02060000 -#include "bytesobject.h" -#endif -#include "pymemcompat.h" -#include "structmember.h" -#if defined(MS_WINDOWS) -#include -#else -#include "my_config.h" -#endif -#include "mysql.h" -#include "mysqld_error.h" -#include "errmsg.h" - -#if PY_VERSION_HEX < 0x02020000 -# define MyTuple_Resize(t,n,d) _PyTuple_Resize(t, n, d) -# define MyMember(a,b,c,d,e) {a,b,c,d} -# define MyMemberlist(x) struct memberlist x -# define MyAlloc(s,t) PyObject_New(s,&t) -# define MyFree(o) PyObject_Del(o) -#else -# define MyTuple_Resize(t,n,d) _PyTuple_Resize(t, n) -# define MyMember(a,b,c,d,e) {a,b,c,d,e} -# define MyMemberlist(x) struct PyMemberDef x -# define MyAlloc(s,t) (s *) t.tp_alloc(&t,0) -#ifdef IS_PY3K -# define MyFree(o) PyObject_Del(o) -#else -# define MyFree(ob) ob->ob_type->tp_free((PyObject *)ob) -#endif -#endif - -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -#define PY_SSIZE_T_MAX INT_MAX -#define PY_SSIZE_T_MIN INT_MIN -#endif - -static PyObject *_mysql_MySQLError; -static PyObject *_mysql_Warning; -static PyObject *_mysql_Error; -static PyObject *_mysql_DatabaseError; -static PyObject *_mysql_InterfaceError; -static PyObject *_mysql_DataError; -static PyObject *_mysql_OperationalError; -static PyObject *_mysql_IntegrityError; -static PyObject *_mysql_InternalError; -static PyObject *_mysql_ProgrammingError; -static PyObject *_mysql_NotSupportedError; - -typedef struct { - PyObject_HEAD - MYSQL connection; - int open; - PyObject *converter; -} _mysql_ConnectionObject; - -#define check_connection(c) if (!(c->open)) return _mysql_Exception(c) -#define result_connection(r) ((_mysql_ConnectionObject *)r->conn) -#define check_result_connection(r) check_connection(result_connection(r)) - -extern PyTypeObject _mysql_ConnectionObject_Type; - -typedef struct { - PyObject_HEAD - PyObject *conn; - MYSQL_RES *result; - int nfields; - int use; - PyObject *converter; -} _mysql_ResultObject; - -extern PyTypeObject _mysql_ResultObject_Type; - -static int _mysql_server_init_done = 0; -#if MYSQL_VERSION_ID >= 40000 -#define check_server_init(x) if (!_mysql_server_init_done) { if (mysql_server_init(0, NULL, NULL)) { _mysql_Exception(NULL); return x; } else { _mysql_server_init_done = 1;} } -#else -#define check_server_init(x) if (!_mysql_server_init_done) _mysql_server_init_done = 1 -#endif - -#if MYSQL_VERSION_ID >= 50500 -#define HAVE_OPENSSL 1 -#endif - -PyObject * -_mysql_Exception(_mysql_ConnectionObject *c) -{ - PyObject *t, *e; - int merr; - - if (!(t = PyTuple_New(2))) return NULL; - if (!_mysql_server_init_done) { - e = _mysql_InternalError; - PyTuple_SET_ITEM(t, 0, PyInt_FromLong(-1L)); -#ifdef IS_PY3K - PyTuple_SET_ITEM(t, 1, PyUnicode_FromString("server not initialized")); -#else - PyTuple_SET_ITEM(t, 1, PyString_FromString("server not initialized")); -#endif - PyErr_SetObject(e, t); - Py_DECREF(t); - return NULL; - } - merr = mysql_errno(&(c->connection)); - if (!merr) - e = _mysql_InterfaceError; - else if (merr > CR_MAX_ERROR) { - PyTuple_SET_ITEM(t, 0, PyInt_FromLong(-1L)); -#ifdef IS_PY3K - PyTuple_SET_ITEM(t, 1, PyUnicode_FromString("error totally whack")); -#else - PyTuple_SET_ITEM(t, 1, PyString_FromString("error totally whack")); -#endif - PyErr_SetObject(_mysql_InterfaceError, t); - Py_DECREF(t); - return NULL; - } - else switch (merr) { - case CR_COMMANDS_OUT_OF_SYNC: - case ER_DB_CREATE_EXISTS: - case ER_SYNTAX_ERROR: - case ER_PARSE_ERROR: - case ER_NO_SUCH_TABLE: - case ER_WRONG_DB_NAME: - case ER_WRONG_TABLE_NAME: - case ER_FIELD_SPECIFIED_TWICE: - case ER_INVALID_GROUP_FUNC_USE: - case ER_UNSUPPORTED_EXTENSION: - case ER_TABLE_MUST_HAVE_COLUMNS: -#ifdef ER_CANT_DO_THIS_DURING_AN_TRANSACTION - case ER_CANT_DO_THIS_DURING_AN_TRANSACTION: -#endif - e = _mysql_ProgrammingError; - break; -#ifdef WARN_DATA_TRUNCATED - case WARN_DATA_TRUNCATED: -#ifdef WARN_NULL_TO_NOTNULL - case WARN_NULL_TO_NOTNULL: -#endif -#ifdef ER_WARN_DATA_OUT_OF_RANGE - case ER_WARN_DATA_OUT_OF_RANGE: -#endif -#ifdef ER_NO_DEFAULT - case ER_NO_DEFAULT: -#endif -#ifdef ER_PRIMARY_CANT_HAVE_NULL - case ER_PRIMARY_CANT_HAVE_NULL: -#endif -#ifdef ER_DATA_TOO_LONG - case ER_DATA_TOO_LONG: -#endif -#ifdef ER_DATETIME_FUNCTION_OVERFLOW - case ER_DATETIME_FUNCTION_OVERFLOW: -#endif - e = _mysql_DataError; - break; -#endif - case ER_DUP_ENTRY: -#ifdef ER_DUP_UNIQUE - case ER_DUP_UNIQUE: -#endif -#ifdef ER_NO_REFERENCED_ROW - case ER_NO_REFERENCED_ROW: -#endif -#ifdef ER_NO_REFERENCED_ROW_2 - case ER_NO_REFERENCED_ROW_2: -#endif -#ifdef ER_ROW_IS_REFERENCED - case ER_ROW_IS_REFERENCED: -#endif -#ifdef ER_ROW_IS_REFERENCED_2 - case ER_ROW_IS_REFERENCED_2: -#endif -#ifdef ER_CANNOT_ADD_FOREIGN - case ER_CANNOT_ADD_FOREIGN: -#endif - e = _mysql_IntegrityError; - break; -#ifdef ER_WARNING_NOT_COMPLETE_ROLLBACK - case ER_WARNING_NOT_COMPLETE_ROLLBACK: -#endif -#ifdef ER_NOT_SUPPORTED_YET - case ER_NOT_SUPPORTED_YET: -#endif -#ifdef ER_FEATURE_DISABLED - case ER_FEATURE_DISABLED: -#endif -#ifdef ER_UNKNOWN_STORAGE_ENGINE - case ER_UNKNOWN_STORAGE_ENGINE: -#endif - e = _mysql_NotSupportedError; - break; - default: - if (merr < 1000) - e = _mysql_InternalError; - else - e = _mysql_OperationalError; - break; - } - PyTuple_SET_ITEM(t, 0, PyInt_FromLong((long)merr)); -#ifdef IS_PY3K - PyTuple_SET_ITEM(t, 1, PyUnicode_FromString(mysql_error(&(c->connection)))); -#else - PyTuple_SET_ITEM(t, 1, PyString_FromString(mysql_error(&(c->connection)))); -#endif - PyErr_SetObject(e, t); - Py_DECREF(t); - return NULL; -} - -static char _mysql_server_init__doc__[] = -"Initialize embedded server. If this client is not linked against\n\ -the embedded server library, this function does nothing.\n\ -\n\ -args -- sequence of command-line arguments\n\ -groups -- sequence of groups to use in defaults files\n\ -"; - -static PyObject *_mysql_server_init( - PyObject *self, - PyObject *args, - PyObject *kwargs) { - static char *kwlist[] = {"args", "groups", NULL}; - char **cmd_args_c=NULL, **groups_c=NULL, *s; - int cmd_argc=0, i, groupc; - PyObject *cmd_args=NULL, *groups=NULL, *ret=NULL, *item; - - if (_mysql_server_init_done) { - PyErr_SetString(_mysql_ProgrammingError, - "already initialized"); - return NULL; - } - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", kwlist, - &cmd_args, &groups)) - return NULL; - -#if MYSQL_VERSION_ID >= 40000 - if (cmd_args) { - if (!PySequence_Check(cmd_args)) { - PyErr_SetString(PyExc_TypeError, - "args must be a sequence"); - goto finish; - } - cmd_argc = PySequence_Size(cmd_args); - if (cmd_argc == -1) { - PyErr_SetString(PyExc_TypeError, - "args could not be sized"); - goto finish; - } - cmd_args_c = (char **) PyMem_Malloc(cmd_argc*sizeof(char *)); - for (i=0; i< cmd_argc; i++) { - item = PySequence_GetItem(cmd_args, i); -#ifdef IS_PY3K - s = PyUnicode_AS_DATA(item); -#else - s = PyString_AsString(item); -#endif - - Py_DECREF(item); - if (!s) { - PyErr_SetString(PyExc_TypeError, - "args must contain strings"); - goto finish; - } - cmd_args_c[i] = s; - } - } - if (groups) { - if (!PySequence_Check(groups)) { - PyErr_SetString(PyExc_TypeError, - "groups must be a sequence"); - goto finish; - } - groupc = PySequence_Size(groups); - if (groupc == -1) { - PyErr_SetString(PyExc_TypeError, - "groups could not be sized"); - goto finish; - } - groups_c = (char **) PyMem_Malloc((1+groupc)*sizeof(char *)); - for (i=0; i< groupc; i++) { - item = PySequence_GetItem(groups, i); -#ifdef IS_PY3K - s = PyUnicode_AS_DATA(item); -#else - s = PyString_AsString(item); -#endif - Py_DECREF(item); - if (!s) { - PyErr_SetString(PyExc_TypeError, - "groups must contain strings"); - goto finish; - } - groups_c[i] = s; - } - groups_c[groupc] = (char *)NULL; - } - /* even though this may block, don't give up the interpreter lock - so that the server can't be initialized multiple times. */ - if (mysql_server_init(cmd_argc, cmd_args_c, groups_c)) { - _mysql_Exception(NULL); - goto finish; - } -#endif - ret = Py_None; - Py_INCREF(Py_None); - _mysql_server_init_done = 1; - finish: - PyMem_Free(groups_c); - PyMem_Free(cmd_args_c); - return ret; -} - -static char _mysql_server_end__doc__[] = -"Shut down embedded server. If not using an embedded server, this\n\ -does nothing."; - -static PyObject *_mysql_server_end( - PyObject *self, - PyObject *args) { - if (_mysql_server_init_done) { -#if MYSQL_VERSION_ID >= 40000 - mysql_server_end(); -#endif - _mysql_server_init_done = 0; - Py_INCREF(Py_None); - return Py_None; - } - return _mysql_Exception(NULL); -} - -#if MYSQL_VERSION_ID >= 32314 -static char _mysql_thread_safe__doc__[] = -"Indicates whether the client is compiled as thread-safe."; - -static PyObject *_mysql_thread_safe( - PyObject *self, - PyObject *args) { - PyObject *flag; - if (!PyArg_ParseTuple(args, "")) return NULL; - check_server_init(NULL); - if (!(flag=PyInt_FromLong((long)mysql_thread_safe()))) return NULL; - return flag; -} -#endif - -static char _mysql_ResultObject__doc__[] = -"result(connection, use=0, converter={}) -- Result set from a query.\n\ -\n\ -Creating instances of this class directly is an excellent way to\n\ -shoot yourself in the foot. If using _mysql.connection directly,\n\ -use connection.store_result() or connection.use_result() instead.\n\ -If using MySQLdb.Connection, this is done by the cursor class.\n\ -Just forget you ever saw this. Forget... FOR-GET..."; - -static int -_mysql_ResultObject_Initialize( - _mysql_ResultObject *self, - PyObject *args, - PyObject *kwargs) -{ - static char *kwlist[] = {"connection", "use", "converter", NULL}; - MYSQL_RES *result; - _mysql_ConnectionObject *conn=NULL; - int use=0; - PyObject *conv=NULL; - int n, i; - MYSQL_FIELD *fields; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iO", kwlist, - &conn, &use, &conv)) - return -1; - if (!conv) { - if (!(conv = PyDict_New())) - return -1; - } - else - Py_INCREF(conv); - - self->conn = (PyObject *) conn; - Py_INCREF(conn); - self->use = use; - Py_BEGIN_ALLOW_THREADS ; - if (use) - result = mysql_use_result(&(conn->connection)); - else - result = mysql_store_result(&(conn->connection)); - self->result = result; - Py_END_ALLOW_THREADS ; - if (!result) { - if (mysql_field_count(&(conn->connection)) > 0) { - _mysql_Exception(conn); - return -1; - } - self->converter = PyTuple_New(0); - Py_DECREF(conv); - return 0; - } - n = mysql_num_fields(result); - self->nfields = n; - if (!(self->converter = PyTuple_New(n))) { - Py_DECREF(conv); - return -1; - } - fields = mysql_fetch_fields(result); - for (i=0; iconverter, i, fun); - } - - Py_DECREF(conv); - return 0; -} - -#if PY_VERSION_HEX >= 0x02020000 -static int _mysql_ResultObject_traverse( - _mysql_ResultObject *self, - visitproc visit, - void *arg) -{ - int r; - if (self->converter) { - if (!(r = visit(self->converter, arg))) return r; - } - if (self->conn) - return visit(self->conn, arg); - return 0; -} -#endif - -static int _mysql_ResultObject_clear( - _mysql_ResultObject *self) -{ - Py_XDECREF(self->converter); - self->converter = NULL; - Py_XDECREF(self->conn); - self->conn = NULL; - return 0; -} - -static int -_mysql_ConnectionObject_Initialize( - _mysql_ConnectionObject *self, - PyObject *args, - PyObject *kwargs) -{ - MYSQL *conn = NULL; - PyObject *conv = NULL; - PyObject *ssl = NULL; -#if HAVE_OPENSSL - char *key = NULL, *cert = NULL, *ca = NULL, - *capath = NULL, *cipher = NULL; -#endif - char *host = NULL, *user = NULL, *passwd = NULL, - *db = NULL, *unix_socket = NULL; - unsigned int port = 0; - unsigned int client_flag = 0; - static char *kwlist[] = { "host", "user", "passwd", "db", "port", - "unix_socket", "conv", - "connect_timeout", "compress", - "named_pipe", "init_command", - "read_default_file", "read_default_group", - "client_flag", "ssl", - "local_infile", - NULL } ; - int connect_timeout = 0; - int compress = -1, named_pipe = -1, local_infile = -1; - char *init_command=NULL, - *read_default_file=NULL, - *read_default_group=NULL; - - self->converter = NULL; - self->open = 0; - check_server_init(-1); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssisOiiisssiOi:connect", - kwlist, - &host, &user, &passwd, &db, - &port, &unix_socket, &conv, - &connect_timeout, - &compress, &named_pipe, - &init_command, &read_default_file, - &read_default_group, - &client_flag, &ssl, - &local_infile /* DO NOT PATCH FOR RECONNECT, IDIOTS - IF YOU DO THIS, I WILL NOT SUPPORT YOUR PACKAGES. */ - )) - return -1; - -#ifdef IS_PY3K -#define _stringsuck(d,t,s) {t=PyMapping_GetItemString(s,#d);\ - if(t){d=PyUnicode_AS_DATA(t);Py_DECREF(t);}\ - PyErr_Clear();} -#else -#define _stringsuck(d,t,s) {t=PyMapping_GetItemString(s,#d);\ - if(t){d=PyString_AsString(t);Py_DECREF(t);}\ - PyErr_Clear();} -#endif - - if (ssl) { -#if HAVE_OPENSSL - PyObject *value = NULL; - _stringsuck(ca, value, ssl); - _stringsuck(capath, value, ssl); - _stringsuck(cert, value, ssl); - _stringsuck(key, value, ssl); - _stringsuck(cipher, value, ssl); -#else - PyErr_SetString(_mysql_NotSupportedError, - "client library does not have SSL support"); - return -1; -#endif - } - - Py_BEGIN_ALLOW_THREADS ; - conn = mysql_init(&(self->connection)); - if (connect_timeout) { - unsigned int timeout = connect_timeout; - mysql_options(&(self->connection), MYSQL_OPT_CONNECT_TIMEOUT, - (char *)&timeout); - } - if (compress != -1) { - mysql_options(&(self->connection), MYSQL_OPT_COMPRESS, 0); - client_flag |= CLIENT_COMPRESS; - } - if (named_pipe != -1) - mysql_options(&(self->connection), MYSQL_OPT_NAMED_PIPE, 0); - if (init_command != NULL) - mysql_options(&(self->connection), MYSQL_INIT_COMMAND, init_command); - if (read_default_file != NULL) - mysql_options(&(self->connection), MYSQL_READ_DEFAULT_FILE, read_default_file); - if (read_default_group != NULL) - mysql_options(&(self->connection), MYSQL_READ_DEFAULT_GROUP, read_default_group); - - if (local_infile != -1) - mysql_options(&(self->connection), MYSQL_OPT_LOCAL_INFILE, (char *) &local_infile); - -#if HAVE_OPENSSL - if (ssl) - mysql_ssl_set(&(self->connection), - key, cert, ca, capath, cipher); -#endif - - conn = mysql_real_connect(&(self->connection), host, user, passwd, db, - port, unix_socket, client_flag); - - Py_END_ALLOW_THREADS ; - - if (!conn) { - _mysql_Exception(self); - return -1; - } - - /* Internal references to python-land objects */ - if (!conv) - conv = PyDict_New(); - else - Py_INCREF(conv); - - if (!conv) - return -1; - self->converter = conv; - - /* - PyType_GenericAlloc() automatically sets up GC allocation and - tracking for GC objects, at least in 2.2.1, so it does not need to - be done here. tp_dealloc still needs to call PyObject_GC_UnTrack(), - however. - */ - self->open = 1; - return 0; -} - -static char _mysql_connect__doc__[] = -"Returns a MYSQL connection object. Exclusive use of\n\ -keyword parameters strongly recommended. Consult the\n\ -MySQL C API documentation for more details.\n\ -\n\ -host\n\ - string, host to connect\n\ -\n\ -user\n\ - string, user to connect as\n\ -\n\ -passwd\n\ - string, password to use\n\ -\n\ -db\n\ - string, database to use\n\ -\n\ -port\n\ - integer, TCP/IP port to connect to\n\ -\n\ -unix_socket\n\ - string, location of unix_socket (UNIX-ish only)\n\ -\n\ -conv\n\ - mapping, maps MySQL FIELD_TYPE.* to Python functions which\n\ - convert a string to the appropriate Python type\n\ -\n\ -connect_timeout\n\ - number of seconds to wait before the connection\n\ - attempt fails.\n\ -\n\ -compress\n\ - if set, gzip compression is enabled\n\ -\n\ -named_pipe\n\ - if set, connect to server via named pipe (Windows only)\n\ -\n\ -init_command\n\ - command which is run once the connection is created\n\ -\n\ -read_default_file\n\ - see the MySQL documentation for mysql_options()\n\ -\n\ -read_default_group\n\ - see the MySQL documentation for mysql_options()\n\ -\n\ -client_flag\n\ - client flags from MySQLdb.constants.CLIENT\n\ -\n\ -load_infile\n\ - int, non-zero enables LOAD LOCAL INFILE, zero disables\n\ -\n\ -"; - -static PyObject * -_mysql_connect( - PyObject *self, - PyObject *args, - PyObject *kwargs) -{ - _mysql_ConnectionObject *c=NULL; - - c = MyAlloc(_mysql_ConnectionObject, _mysql_ConnectionObject_Type); - if (c == NULL) return NULL; - if (_mysql_ConnectionObject_Initialize(c, args, kwargs)) { - Py_DECREF(c); - c = NULL; - } - return (PyObject *) c; -} - -#if PY_VERSION_HEX >= 0x02020000 -static int _mysql_ConnectionObject_traverse( - _mysql_ConnectionObject *self, - visitproc visit, - void *arg) -{ - if (self->converter) - return visit(self->converter, arg); - return 0; -} -#endif - -static int _mysql_ConnectionObject_clear( - _mysql_ConnectionObject *self) -{ - Py_XDECREF(self->converter); - self->converter = NULL; - return 0; -} - -static char _mysql_ConnectionObject_close__doc__[] = -"Close the connection. No further activity possible."; - -static PyObject * -_mysql_ConnectionObject_close( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (args) { - if (!PyArg_ParseTuple(args, "")) return NULL; - } - if (self->open) { - Py_BEGIN_ALLOW_THREADS - mysql_close(&(self->connection)); - Py_END_ALLOW_THREADS - self->open = 0; - } else { - PyErr_SetString(_mysql_ProgrammingError, - "closing a closed connection"); - return NULL; - } - _mysql_ConnectionObject_clear(self); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_affected_rows__doc__ [] = -"Return number of rows affected by the last query.\n\ -Non-standard. Use Cursor.rowcount.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_affected_rows( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - return PyLong_FromUnsignedLongLong(mysql_affected_rows(&(self->connection))); -} - -static char _mysql_debug__doc__[] = -"Does a DBUG_PUSH with the given string.\n\ -mysql_debug() uses the Fred Fish debug library.\n\ -To use this function, you must compile the client library to\n\ -support debugging.\n\ -"; -static PyObject * -_mysql_debug( - PyObject *self, - PyObject *args) -{ - char *debug; - if (!PyArg_ParseTuple(args, "s", &debug)) return NULL; - mysql_debug(debug); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_dump_debug_info__doc__[] = -"Instructs the server to write some debug information to the\n\ -log. The connected user must have the process privilege for\n\ -this to work. Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_dump_debug_info( - _mysql_ConnectionObject *self, - PyObject *args) -{ - int err; - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - err = mysql_dump_debug_info(&(self->connection)); - Py_END_ALLOW_THREADS - if (err) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_autocommit__doc__[] = -"Set the autocommit mode. True values enable; False value disable.\n\ -"; -static PyObject * -_mysql_ConnectionObject_autocommit( - _mysql_ConnectionObject *self, - PyObject *args) -{ - int flag, err; - if (!PyArg_ParseTuple(args, "i", &flag)) return NULL; - Py_BEGIN_ALLOW_THREADS -#if MYSQL_VERSION_ID >= 40100 - err = mysql_autocommit(&(self->connection), flag); -#else - { - char query[256]; - snprintf(query, 256, "SET AUTOCOMMIT=%d", flag); - err = mysql_query(&(self->connection), query); - } -#endif - Py_END_ALLOW_THREADS - if (err) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_commit__doc__[] = -"Commits the current transaction\n\ -"; -static PyObject * -_mysql_ConnectionObject_commit( - _mysql_ConnectionObject *self, - PyObject *args) -{ - int err; - if (!PyArg_ParseTuple(args, "")) return NULL; - Py_BEGIN_ALLOW_THREADS -#if MYSQL_VERSION_ID >= 40100 - err = mysql_commit(&(self->connection)); -#else - err = mysql_query(&(self->connection), "COMMIT"); -#endif - Py_END_ALLOW_THREADS - if (err) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_rollback__doc__[] = -"Rolls backs the current transaction\n\ -"; -static PyObject * -_mysql_ConnectionObject_rollback( - _mysql_ConnectionObject *self, - PyObject *args) -{ - int err; - if (!PyArg_ParseTuple(args, "")) return NULL; - Py_BEGIN_ALLOW_THREADS -#if MYSQL_VERSION_ID >= 40100 - err = mysql_rollback(&(self->connection)); -#else - err = mysql_query(&(self->connection), "ROLLBACK"); -#endif - Py_END_ALLOW_THREADS - if (err) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_next_result__doc__[] = -"If more query results exist, next_result() reads the next query\n\ -results and returns the status back to application.\n\ -\n\ -After calling next_result() the state of the connection is as if\n\ -you had called query() for the next query. This means that you can\n\ -now call store_result(), warning_count(), affected_rows()\n\ -, and so forth. \n\ -\n\ -Returns 0 if there are more results; -1 if there are no more results\n\ -\n\ -Non-standard.\n\ -"; -static PyObject * -_mysql_ConnectionObject_next_result( - _mysql_ConnectionObject *self, - PyObject *args) -{ - int err; - if (!PyArg_ParseTuple(args, "")) return NULL; - Py_BEGIN_ALLOW_THREADS -#if MYSQL_VERSION_ID >= 40100 - err = mysql_next_result(&(self->connection)); -#else - err = -1; -#endif - Py_END_ALLOW_THREADS - if (err > 0) return _mysql_Exception(self); - return PyInt_FromLong(err); -} - -#if MYSQL_VERSION_ID >= 40100 - -static char _mysql_ConnectionObject_set_server_option__doc__[] = -"set_server_option(option) -- Enables or disables an option\n\ -for the connection.\n\ -\n\ -Non-standard.\n\ -"; -static PyObject * -_mysql_ConnectionObject_set_server_option( - _mysql_ConnectionObject *self, - PyObject *args) -{ - int err, flags=0; - if (!PyArg_ParseTuple(args, "i", &flags)) - return NULL; - Py_BEGIN_ALLOW_THREADS - err = mysql_set_server_option(&(self->connection), flags); - Py_END_ALLOW_THREADS - if (err) return _mysql_Exception(self); - return PyInt_FromLong(err); -} - -static char _mysql_ConnectionObject_sqlstate__doc__[] = -"Returns a string containing the SQLSTATE error code\n\ -for the last error. The error code consists of five characters.\n\ -'00000' means \"no error.\" The values are specified by ANSI SQL\n\ -and ODBC. For a list of possible values, see section 23\n\ -Error Handling in MySQL in the MySQL Manual.\n\ -\n\ -Note that not all MySQL errors are yet mapped to SQLSTATE's.\n\ -The value 'HY000' (general error) is used for unmapped errors.\n\ -\n\ -Non-standard.\n\ -"; -static PyObject * -_mysql_ConnectionObject_sqlstate( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; -#ifdef IS_PY3K - return PyUnicode_FromString(mysql_sqlstate(&(self->connection))); -#else - return PyString_FromString(mysql_sqlstate(&(self->connection))); -#endif -} - -static char _mysql_ConnectionObject_warning_count__doc__[] = -"Returns the number of warnings generated during execution\n\ -of the previous SQL statement.\n\ -\n\ -Non-standard.\n\ -"; -static PyObject * -_mysql_ConnectionObject_warning_count( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - return PyInt_FromLong(mysql_warning_count(&(self->connection))); -} - -#endif - -static char _mysql_ConnectionObject_errno__doc__[] = -"Returns the error code for the most recently invoked API function\n\ -that can succeed or fail. A return value of zero means that no error\n\ -occurred.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_errno( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - return PyInt_FromLong((long)mysql_errno(&(self->connection))); -} - -static char _mysql_ConnectionObject_error__doc__[] = -"Returns the error message for the most recently invoked API function\n\ -that can succeed or fail. An empty string ("") is returned if no error\n\ -occurred.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_error( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); -#ifdef IS_PY3K - return PyUnicode_FromString(mysql_error(&(self->connection))); -#else - return PyString_FromString(mysql_error(&(self->connection))); -#endif -} - -static char _mysql_escape_string__doc__[] = -"escape_string(s) -- quote any SQL-interpreted characters in string s.\n\ -\n\ -Use connection.escape_string(s), if you use it at all.\n\ -_mysql.escape_string(s) cannot handle character sets. You are\n\ -probably better off using connection.escape(o) instead, since\n\ -it will escape entire sequences as well as strings."; - -static PyObject * -_mysql_escape_string( - _mysql_ConnectionObject *self, - PyObject *args) -{ - PyObject *str; - char *in, *out; - int len, size; - if (!PyArg_ParseTuple(args, "s#:escape_string", &in, &size)) return NULL; -#ifdef IS_PY3K - str = PyUnicode_FromStringAndSize((char *) NULL, size*2+1); -#else - str = PyString_FromStringAndSize((char *) NULL, size*2+1); -#endif - if (!str) return PyErr_NoMemory(); -#ifdef IS_PY3K - out = PyUnicode_AS_DATA(str); -#else - out = PyString_AS_STRING(str); -#endif -#if MYSQL_VERSION_ID < 32321 - len = mysql_escape_string(out, in, size); -#else - check_server_init(NULL); - if (self && self->open) - len = mysql_real_escape_string(&(self->connection), out, in, size); - else - len = mysql_escape_string(out, in, size); -#endif -#ifdef IS_PY3K - if (PyUnicode_Resize(&str, len) < 0) return NULL; -#else - if (_PyString_Resize(&str, len) < 0) return NULL; -#endif - return (str); -} - -static char _mysql_string_literal__doc__[] = -"string_literal(obj) -- converts object obj into a SQL string literal.\n\ -This means, any special SQL characters are escaped, and it is enclosed\n\ -within single quotes. In other words, it performs:\n\ -\n\ -\"'%s'\" % escape_string(str(obj))\n\ -\n\ -Use connection.string_literal(obj), if you use it at all.\n\ -_mysql.string_literal(obj) cannot handle character sets."; - -static PyObject * -_mysql_string_literal( - _mysql_ConnectionObject *self, - PyObject *args) -{ - PyObject *str, *s, *o, *d; - char *in, *out; - int len, size; - if (!PyArg_ParseTuple(args, "O|O:string_literal", &o, &d)) return NULL; - s = PyObject_Str(o); - if (!s) return NULL; -#ifdef IS_PY3K - in = PyUnicode_AS_DATA(s); - size = PyUnicode_GetSize(s); - str = PyUnicode_FromStringAndSize((char *) NULL, size*2+3); - if (!str) return PyErr_NoMemory(); - out = PyUnicode_AS_DATA(str); -#else - in = PyString_AsString(s); - size = PyString_GET_SIZE(s); - str = PyString_FromStringAndSize((char *) NULL, size*2+3); - if (!str) return PyErr_NoMemory(); - out = PyString_AS_STRING(str); -#endif -#if MYSQL_VERSION_ID < 32321 - len = mysql_escape_string(out+1, in, size); -#else - check_server_init(NULL); - if (self && self->open) - len = mysql_real_escape_string(&(self->connection), out+1, in, size); - else - len = mysql_escape_string(out+1, in, size); -#endif - *out = *(out+len+1) = '\''; -#ifdef IS_PY3K - if (PyUnicode_Resize(&str, len+2) < 0) return NULL; -#else - if (_PyString_Resize(&str, len+2) < 0) return NULL; -#endif - Py_DECREF(s); - return (str); -} - -static PyObject *_mysql_NULL; - -static PyObject * -_escape_item( - PyObject *item, - PyObject *d) -{ - PyObject *quoted=NULL, *itemtype, *itemconv; - if (!(itemtype = PyObject_Type(item))) - goto error; - itemconv = PyObject_GetItem(d, itemtype); - Py_DECREF(itemtype); - if (!itemconv) { - PyErr_Clear(); - itemconv = PyObject_GetItem(d, -#ifdef IS_PY3K - (PyObject *) &PyUnicode_Type); -#else - (PyObject *) &PyString_Type); -#endif - } - if (!itemconv) { - PyErr_SetString(PyExc_TypeError, - "no default type converter defined"); - goto error; - } - quoted = PyObject_CallFunction(itemconv, "OO", item, d); - Py_DECREF(itemconv); -error: - return quoted; -} - -static char _mysql_escape__doc__[] = -"escape(obj, dict) -- escape any special characters in object obj\n\ -using mapping dict to provide quoting functions for each type.\n\ -Returns a SQL literal string."; -static PyObject * -_mysql_escape( - PyObject *self, - PyObject *args) -{ - PyObject *o=NULL, *d=NULL; - if (!PyArg_ParseTuple(args, "O|O:escape", &o, &d)) - return NULL; - if (d) { - if (!PyMapping_Check(d)) { - PyErr_SetString(PyExc_TypeError, - "argument 2 must be a mapping"); - return NULL; - } - return _escape_item(o, d); - } else { - if (!self) { - PyErr_SetString(PyExc_TypeError, - "argument 2 must be a mapping"); - return NULL; - } - return _escape_item(o, - ((_mysql_ConnectionObject *) self)->converter); - } -} - -static char _mysql_escape_sequence__doc__[] = -"escape_sequence(seq, dict) -- escape any special characters in sequence\n\ -seq using mapping dict to provide quoting functions for each type.\n\ -Returns a tuple of escaped items."; -static PyObject * -_mysql_escape_sequence( - PyObject *self, - PyObject *args) -{ - PyObject *o=NULL, *d=NULL, *r=NULL, *item, *quoted; - int i, n; - if (!PyArg_ParseTuple(args, "OO:escape_sequence", &o, &d)) - goto error; - if (!PyMapping_Check(d)) { - PyErr_SetString(PyExc_TypeError, - "argument 2 must be a mapping"); - return NULL; - } - if ((n = PyObject_Length(o)) == -1) goto error; - if (!(r = PyTuple_New(n))) goto error; - for (i=0; iresult); - fields = mysql_fetch_fields(self->result); - if (!(d = PyTuple_New(n))) return NULL; - for (i=0; iresult); - fields = mysql_fetch_fields(self->result); - if (!(d = PyTuple_New(n))) return NULL; - for (i=0; iresult); - if (!(r = PyTuple_New(n))) return NULL; - length = mysql_fetch_lengths(self->result); - for (i=0; iconverter, i); - v = _mysql_field_to_python(c, row[i], length[i]); - if (!v) goto error; - PyTuple_SET_ITEM(r, i, v); - } - return r; - error: - Py_XDECREF(r); - return NULL; -} - -static PyObject * -_mysql_row_to_dict( - _mysql_ResultObject *self, - MYSQL_ROW row) -{ - unsigned int n, i; - unsigned long *length; - PyObject *r, *c; - MYSQL_FIELD *fields; - - n = mysql_num_fields(self->result); - if (!(r = PyDict_New())) return NULL; - length = mysql_fetch_lengths(self->result); - fields = mysql_fetch_fields(self->result); - for (i=0; iconverter, i); - v = _mysql_field_to_python(c, row[i], length[i]); - if (!v) goto error; - if (!PyMapping_HasKeyString(r, fields[i].name)) { - PyMapping_SetItemString(r, fields[i].name, v); - } else { - int len; - char buf[256]; - strncpy(buf, fields[i].table, 256); - len = strlen(buf); - strncat(buf, ".", 256-len); - len = strlen(buf); - strncat(buf, fields[i].name, 256-len); - PyMapping_SetItemString(r, buf, v); - } - Py_DECREF(v); - } - return r; - error: - Py_XDECREF(r); - return NULL; -} - -static PyObject * -_mysql_row_to_dict_old( - _mysql_ResultObject *self, - MYSQL_ROW row) -{ - unsigned int n, i; - unsigned long *length; - PyObject *r, *c; - MYSQL_FIELD *fields; - - n = mysql_num_fields(self->result); - if (!(r = PyDict_New())) return NULL; - length = mysql_fetch_lengths(self->result); - fields = mysql_fetch_fields(self->result); - for (i=0; iconverter, i); - v = _mysql_field_to_python(c, row[i], length[i]); - if (!v) goto error; - { - int len=0; - char buf[256]=""; - if (strlen(fields[i].table)) { - strncpy(buf, fields[i].table, 256); - len = strlen(buf); - strncat(buf, ".", 256-len); - len = strlen(buf); - } - strncat(buf, fields[i].name, 256-len); - PyMapping_SetItemString(r, buf, v); - } - Py_DECREF(v); - } - return r; - error: - Py_XDECREF(r); - return NULL; -} - -typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW); - -int -_mysql__fetch_row( - _mysql_ResultObject *self, - PyObject **r, - int skiprows, - int maxrows, - _PYFUNC *convert_row) -{ - unsigned int i; - MYSQL_ROW row; - - for (i = skiprows; i<(skiprows+maxrows); i++) { - PyObject *v; - if (!self->use) - row = mysql_fetch_row(self->result); - else { - Py_BEGIN_ALLOW_THREADS; - row = mysql_fetch_row(self->result); - Py_END_ALLOW_THREADS; - } - if (!row && mysql_errno(&(((_mysql_ConnectionObject *)(self->conn))->connection))) { - _mysql_Exception((_mysql_ConnectionObject *)self->conn); - goto error; - } - if (!row) { - if (MyTuple_Resize(r, i, 0) == -1) goto error; - break; - } - v = convert_row(self, row); - if (!v) goto error; - PyTuple_SET_ITEM(*r, i, v); - } - return i-skiprows; - error: - return -1; -} - -static char _mysql_ResultObject_fetch_row__doc__[] = -"fetch_row([maxrows, how]) -- Fetches up to maxrows as a tuple.\n\ -The rows are formatted according to how:\n\ -\n\ - 0 -- tuples (default)\n\ - 1 -- dictionaries, key=column or table.column if duplicated\n\ - 2 -- dictionaries, key=table.column\n\ -"; - -static PyObject * -_mysql_ResultObject_fetch_row( - _mysql_ResultObject *self, - PyObject *args, - PyObject *kwargs) -{ - typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW); - static char *kwlist[] = { "maxrows", "how", NULL }; - static _PYFUNC *row_converters[] = - { - _mysql_row_to_tuple, - _mysql_row_to_dict, - _mysql_row_to_dict_old - }; - _PYFUNC *convert_row; - unsigned int maxrows=1, how=0, skiprows=0, rowsadded; - PyObject *r=NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:fetch_row", kwlist, - &maxrows, &how)) - return NULL; - check_result_connection(self); - if (how < 0 || how >= sizeof(row_converters)) { - PyErr_SetString(PyExc_ValueError, "how out of range"); - return NULL; - } - convert_row = row_converters[how]; - if (maxrows) { - if (!(r = PyTuple_New(maxrows))) goto error; - rowsadded = _mysql__fetch_row(self, &r, skiprows, maxrows, - convert_row); - if (rowsadded == -1) goto error; - } else { - if (self->use) { - maxrows = 1000; - if (!(r = PyTuple_New(maxrows))) goto error; - while (1) { - rowsadded = _mysql__fetch_row(self, &r, skiprows, - maxrows, convert_row); - if (rowsadded == -1) goto error; - skiprows += rowsadded; - if (rowsadded < maxrows) break; - if (MyTuple_Resize(&r, skiprows+maxrows, 0) == -1) - goto error; - } - } else { - /* XXX if overflow, maxrows<0? */ - maxrows = (int) mysql_num_rows(self->result); - if (!(r = PyTuple_New(maxrows))) goto error; - rowsadded = _mysql__fetch_row(self, &r, 0, - maxrows, convert_row); - if (rowsadded == -1) goto error; - } - } - return r; - error: - Py_XDECREF(r); - return NULL; -} - -#if MYSQL_VERSION_ID >= 32303 - -static char _mysql_ConnectionObject_change_user__doc__[] = -"Changes the user and causes the database specified by db to\n\ -become the default (current) database on the connection\n\ -specified by mysql. In subsequent queries, this database is\n\ -the default for table references that do not include an\n\ -explicit database specifier.\n\ -\n\ -This function was introduced in MySQL Version 3.23.3.\n\ -\n\ -Fails unless the connected user can be authenticated or if he\n\ -doesn't have permission to use the database. In this case the\n\ -user and database are not changed.\n\ -\n\ -The db parameter may be set to None if you don't want to have\n\ -a default database.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_change_user( - _mysql_ConnectionObject *self, - PyObject *args, - PyObject *kwargs) -{ - char *user, *pwd=NULL, *db=NULL; - int r; - static char *kwlist[] = { "user", "passwd", "db", NULL } ; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ss:change_user", - kwlist, &user, &pwd, &db)) - return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - r = mysql_change_user(&(self->connection), user, pwd, db); - Py_END_ALLOW_THREADS - if (r) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} -#endif - -static char _mysql_ConnectionObject_character_set_name__doc__[] = -"Returns the default character set for the current connection.\n\ -Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_character_set_name( - _mysql_ConnectionObject *self, - PyObject *args) -{ - const char *s; - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); -#if MYSQL_VERSION_ID >= 32321 - s = mysql_character_set_name(&(self->connection)); -#else - s = "latin1"; -#endif -#ifdef IS_PY3K - return PyUnicode_FromString(s); -#else - return PyString_FromString(s); -#endif -} - -#if MYSQL_VERSION_ID >= 50007 -static char _mysql_ConnectionObject_set_character_set__doc__[] = -"Sets the default character set for the current connection.\n\ -Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_set_character_set( - _mysql_ConnectionObject *self, - PyObject *args) -{ - const char *s; - int err; - if (!PyArg_ParseTuple(args, "s", &s)) return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - err = mysql_set_character_set(&(self->connection), s); - Py_END_ALLOW_THREADS - if (err) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} -#endif - -#if MYSQL_VERSION_ID >= 50010 -static char _mysql_ConnectionObject_get_character_set_info__doc__[] = -"Returns a dict with information about the current character set:\n\ -\n\ -collation\n\ - collation name\n\ -name\n\ - character set name\n\ -comment\n\ - comment or descriptive name\n\ -dir\n\ - character set directory\n\ -mbminlen\n\ - min. length for multibyte string\n\ -mbmaxlen\n\ - max. length for multibyte string\n\ -\n\ -Not all keys may be present, particularly dir.\n\ -\n\ -Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_get_character_set_info( - _mysql_ConnectionObject *self, - PyObject *args) -{ - PyObject *result; - MY_CHARSET_INFO cs; - - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - mysql_get_character_set_info(&(self->connection), &cs); - if (!(result = PyDict_New())) return NULL; -#ifdef IS_PY3K - if (cs.csname) - PyDict_SetItemString(result, "name", PyUnicode_FromString(cs.csname)); - if (cs.name) - PyDict_SetItemString(result, "collation", PyUnicode_FromString(cs.name)); - if (cs.comment) - PyDict_SetItemString(result, "comment", PyUnicode_FromString(cs.comment)); - if (cs.dir) - PyDict_SetItemString(result, "dir", PyUnicode_FromString(cs.dir)); - PyDict_SetItemString(result, "mbminlen", PyInt_FromLong(cs.mbminlen)); - PyDict_SetItemString(result, "mbmaxlen", PyInt_FromLong(cs.mbmaxlen)); -#else - if (cs.csname) - PyDict_SetItemString(result, "name", PyString_FromString(cs.csname)); - if (cs.name) - PyDict_SetItemString(result, "collation", PyString_FromString(cs.name)); - if (cs.comment) - PyDict_SetItemString(result, "comment", PyString_FromString(cs.comment)); - if (cs.dir) - PyDict_SetItemString(result, "dir", PyString_FromString(cs.dir)); - PyDict_SetItemString(result, "mbminlen", PyInt_FromLong(cs.mbminlen)); - PyDict_SetItemString(result, "mbmaxlen", PyInt_FromLong(cs.mbmaxlen)); -#endif - return result; -} -#endif - -static char _mysql_get_client_info__doc__[] = -"get_client_info() -- Returns a string that represents\n\ -the client library version."; -static PyObject * -_mysql_get_client_info( - PyObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_server_init(NULL); -#ifdef IS_PY3K - return PyUnicode_FromString(mysql_get_client_info()); -#else - return PyString_FromString(mysql_get_client_info()); -#endif -} - -static char _mysql_ConnectionObject_get_host_info__doc__[] = -"Returns a string that represents the MySQL client library\n\ -version. Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_get_host_info( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); -#ifdef IS_PY3K - return PyUnicode_FromString(mysql_get_host_info(&(self->connection))); -#else - return PyString_FromString(mysql_get_host_info(&(self->connection))); -#endif -} - -static char _mysql_ConnectionObject_get_proto_info__doc__[] = -"Returns an unsigned integer representing the protocol version\n\ -used by the current connection. Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_get_proto_info( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - return PyInt_FromLong((long)mysql_get_proto_info(&(self->connection))); -} - -static char _mysql_ConnectionObject_get_server_info__doc__[] = -"Returns a string that represents the server version number.\n\ -Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_get_server_info( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); -#ifdef IS_PY3K - return PyUnicode_FromString(mysql_get_server_info(&(self->connection))); -#else - return PyString_FromString(mysql_get_server_info(&(self->connection))); -#endif -} - -static char _mysql_ConnectionObject_info__doc__[] = -"Retrieves a string providing information about the most\n\ -recently executed query. Non-standard. Use messages or\n\ -Cursor.messages.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_info( - _mysql_ConnectionObject *self, - PyObject *args) -{ - const char *s; - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - s = mysql_info(&(self->connection)); -#ifdef IS_PY3K - if (s) return PyUnicode_FromString(s); -#else - if (s) return PyString_FromString(s); -#endif - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_insert_id__doc__[] = -"Returns the ID generated for an AUTO_INCREMENT column by the previous\n\ -query. Use this function after you have performed an INSERT query into a\n\ -table that contains an AUTO_INCREMENT field.\n\ -\n\ -Note that this returns 0 if the previous query does not\n\ -generate an AUTO_INCREMENT value. If you need to save the value for\n\ -later, be sure to call this immediately after the query\n\ -that generates the value.\n\ -\n\ -The ID is updated after INSERT and UPDATE statements that generate\n\ -an AUTO_INCREMENT value or that set a column value to\n\ -LAST_INSERT_ID(expr). See section 6.3.5.2 Miscellaneous Functions\n\ -in the MySQL documentation.\n\ -\n\ -Also note that the value of the SQL LAST_INSERT_ID() function always\n\ -contains the most recently generated AUTO_INCREMENT value, and is not\n\ -reset between queries because the value of that function is maintained\n\ -in the server.\n\ -" ; - -static PyObject * -_mysql_ConnectionObject_insert_id( - _mysql_ConnectionObject *self, - PyObject *args) -{ - my_ulonglong r; - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - r = mysql_insert_id(&(self->connection)); - Py_END_ALLOW_THREADS - return PyLong_FromUnsignedLongLong(r); -} - -static char _mysql_ConnectionObject_kill__doc__[] = -"Asks the server to kill the thread specified by pid.\n\ -Non-standard."; - -static PyObject * -_mysql_ConnectionObject_kill( - _mysql_ConnectionObject *self, - PyObject *args) -{ - unsigned long pid; - int r; - if (!PyArg_ParseTuple(args, "k:kill", &pid)) return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - r = mysql_kill(&(self->connection), pid); - Py_END_ALLOW_THREADS - if (r) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_field_count__doc__[] = -"Returns the number of columns for the most recent query on the\n\ -connection. Non-standard. Will probably give you bogus results\n\ -on most cursor classes. Use Cursor.rowcount.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_field_count( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); -#if MYSQL_VERSION_ID < 32224 - return PyInt_FromLong((long)mysql_num_fields(&(self->connection))); -#else - return PyInt_FromLong((long)mysql_field_count(&(self->connection))); -#endif -} - -static char _mysql_ResultObject_num_fields__doc__[] = -"Returns the number of fields (column) in the result." ; - -static PyObject * -_mysql_ResultObject_num_fields( - _mysql_ResultObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_result_connection(self); - return PyInt_FromLong((long)mysql_num_fields(self->result)); -} - -static char _mysql_ResultObject_num_rows__doc__[] = -"Returns the number of rows in the result set. Note that if\n\ -use=1, this will not return a valid value until the entire result\n\ -set has been read.\n\ -"; - -static PyObject * -_mysql_ResultObject_num_rows( - _mysql_ResultObject *self, - PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) return NULL; - check_result_connection(self); - return PyLong_FromUnsignedLongLong(mysql_num_rows(self->result)); -} - -static char _mysql_ConnectionObject_ping__doc__[] = -"Checks whether or not the connection to the server is\n\ -working. If it has gone down, an automatic reconnection is\n\ -attempted.\n\ -\n\ -This function can be used by clients that remain idle for a\n\ -long while, to check whether or not the server has closed the\n\ -connection and reconnect if necessary.\n\ -\n\ -New in 1.2.2: Accepts an optional reconnect parameter. If True,\n\ -then the client will attempt reconnection. Note that this setting\n\ -is persistent. By default, this is on in MySQL<5.0.3, and off\n\ -thereafter.\n\ -\n\ -Non-standard. You should assume that ping() performs an\n\ -implicit rollback; use only when starting a new transaction.\n\ -You have been warned.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_ping( - _mysql_ConnectionObject *self, - PyObject *args) -{ - int r, reconnect = -1; - if (!PyArg_ParseTuple(args, "|I", &reconnect)) return NULL; - check_connection(self); - if ( reconnect != -1 ) self->connection.reconnect = reconnect; - Py_BEGIN_ALLOW_THREADS - r = mysql_ping(&(self->connection)); - Py_END_ALLOW_THREADS - if (r) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_query__doc__[] = -"Execute a query. store_result() or use_result() will get the\n\ -result set, if any. Non-standard. Use cursor() to create a cursor,\n\ -then cursor.execute().\n\ -" ; - -static PyObject * -_mysql_ConnectionObject_query( - _mysql_ConnectionObject *self, - PyObject *args) -{ - char *query; - int len, r; - if (!PyArg_ParseTuple(args, "s#:query", &query, &len)) return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - r = mysql_real_query(&(self->connection), query, len); - Py_END_ALLOW_THREADS - if (r) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} - - -static char _mysql_ConnectionObject_select_db__doc__[] = -"Causes the database specified by db to become the default\n\ -(current) database on the connection specified by mysql. In subsequent\n\ -queries, this database is the default for table references that do not\n\ -include an explicit database specifier.\n\ -\n\ -Fails unless the connected user can be authenticated as having\n\ -permission to use the database.\n\ -\n\ -Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_select_db( - _mysql_ConnectionObject *self, - PyObject *args) -{ - char *db; - int r; - if (!PyArg_ParseTuple(args, "s:select_db", &db)) return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - r = mysql_select_db(&(self->connection), db); - Py_END_ALLOW_THREADS - if (r) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_shutdown__doc__[] = -"Asks the database server to shut down. The connected user must\n\ -have shutdown privileges. Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_shutdown( - _mysql_ConnectionObject *self, - PyObject *args) -{ - int r; - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - r = mysql_shutdown(&(self->connection) -#if MYSQL_VERSION_ID >= 40103 - , SHUTDOWN_DEFAULT -#endif - ); - Py_END_ALLOW_THREADS - if (r) return _mysql_Exception(self); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ConnectionObject_stat__doc__[] = -"Returns a character string containing information similar to\n\ -that provided by the mysqladmin status command. This includes\n\ -uptime in seconds and the number of running threads,\n\ -questions, reloads, and open tables. Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_stat( - _mysql_ConnectionObject *self, - PyObject *args) -{ - const char *s; - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - s = mysql_stat(&(self->connection)); - Py_END_ALLOW_THREADS - if (!s) return _mysql_Exception(self); -#ifdef IS_PY3K - return PyUnicode_FromString(s); -#else - return PyString_FromString(s); -#endif - -} - -static char _mysql_ConnectionObject_store_result__doc__[] = -"Returns a result object acquired by mysql_store_result\n\ -(results stored in the client). If no results are available,\n\ -None is returned. Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_store_result( - _mysql_ConnectionObject *self, - PyObject *args) -{ - PyObject *arglist=NULL, *kwarglist=NULL, *result=NULL; - _mysql_ResultObject *r=NULL; - - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - arglist = Py_BuildValue("(OiO)", self, 0, self->converter); - if (!arglist) goto error; - kwarglist = PyDict_New(); - if (!kwarglist) goto error; - r = MyAlloc(_mysql_ResultObject, _mysql_ResultObject_Type); - if (!r) goto error; - if (_mysql_ResultObject_Initialize(r, arglist, kwarglist)) - goto error; - result = (PyObject *) r; - if (!(r->result)) { - Py_DECREF(result); - Py_INCREF(Py_None); - result = Py_None; - } - error: - Py_XDECREF(arglist); - Py_XDECREF(kwarglist); - return result; -} - -static char _mysql_ConnectionObject_thread_id__doc__[] = -"Returns the thread ID of the current connection. This value\n\ -can be used as an argument to kill() to kill the thread.\n\ -\n\ -If the connection is lost and you reconnect with ping(), the\n\ -thread ID will change. This means you should not get the\n\ -thread ID and store it for later. You should get it when you\n\ -need it.\n\ -\n\ -Non-standard."; - -static PyObject * -_mysql_ConnectionObject_thread_id( - _mysql_ConnectionObject *self, - PyObject *args) -{ - unsigned long pid; - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - Py_BEGIN_ALLOW_THREADS - pid = mysql_thread_id(&(self->connection)); - Py_END_ALLOW_THREADS - return PyInt_FromLong((long)pid); -} - -static char _mysql_ConnectionObject_use_result__doc__[] = -"Returns a result object acquired by mysql_use_result\n\ -(results stored in the server). If no results are available,\n\ -None is returned. Non-standard.\n\ -"; - -static PyObject * -_mysql_ConnectionObject_use_result( - _mysql_ConnectionObject *self, - PyObject *args) -{ - PyObject *arglist=NULL, *kwarglist=NULL, *result=NULL; - _mysql_ResultObject *r=NULL; - - if (!PyArg_ParseTuple(args, "")) return NULL; - check_connection(self); - arglist = Py_BuildValue("(OiO)", self, 1, self->converter); - if (!arglist) return NULL; - kwarglist = PyDict_New(); - if (!kwarglist) goto error; - r = MyAlloc(_mysql_ResultObject, _mysql_ResultObject_Type); - if (!r) goto error; - result = (PyObject *) r; - if (_mysql_ResultObject_Initialize(r, arglist, kwarglist)) - goto error; - if (!(r->result)) { - Py_DECREF(result); - Py_INCREF(Py_None); - result = Py_None; - } - error: - Py_DECREF(arglist); - Py_XDECREF(kwarglist); - return result; -} - -static void -_mysql_ConnectionObject_dealloc( - _mysql_ConnectionObject *self) -{ - PyObject *o; - - PyObject_GC_UnTrack(self); - if (self->open) { - o = _mysql_ConnectionObject_close(self, NULL); - Py_XDECREF(o); - } - MyFree(self); -} - -static PyObject * -_mysql_ConnectionObject_repr( - _mysql_ConnectionObject *self) -{ - char buf[300]; - if (self->open) - sprintf(buf, "<_mysql.connection open to '%.256s' at %lx>", - self->connection.host, - (long)self); - else - sprintf(buf, "<_mysql.connection closed at %lx>", - (long)self); -#ifdef IS_PY3K - return PyUnicode_FromString(buf); -#else - return PyString_FromString(buf); -#endif -} - -static char _mysql_ResultObject_data_seek__doc__[] = -"data_seek(n) -- seek to row n of result set"; -static PyObject * -_mysql_ResultObject_data_seek( - _mysql_ResultObject *self, - PyObject *args) -{ - unsigned int row; - if (!PyArg_ParseTuple(args, "i:data_seek", &row)) return NULL; - check_result_connection(self); - mysql_data_seek(self->result, row); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ResultObject_row_seek__doc__[] = -"row_seek(n) -- seek by offset n rows of result set"; -static PyObject * -_mysql_ResultObject_row_seek( - _mysql_ResultObject *self, - PyObject *args) -{ - int offset; - MYSQL_ROW_OFFSET r; - if (!PyArg_ParseTuple(args, "i:row_seek", &offset)) return NULL; - check_result_connection(self); - if (self->use) { - PyErr_SetString(_mysql_ProgrammingError, - "cannot be used with connection.use_result()"); - return NULL; - } - r = mysql_row_tell(self->result); - mysql_row_seek(self->result, r+offset); - Py_INCREF(Py_None); - return Py_None; -} - -static char _mysql_ResultObject_row_tell__doc__[] = -"row_tell() -- return the current row number of the result set."; -static PyObject * -_mysql_ResultObject_row_tell( - _mysql_ResultObject *self, - PyObject *args) -{ - MYSQL_ROW_OFFSET r; - if (!PyArg_ParseTuple(args, "")) return NULL; - check_result_connection(self); - if (self->use) { - PyErr_SetString(_mysql_ProgrammingError, - "cannot be used with connection.use_result()"); - return NULL; - } - r = mysql_row_tell(self->result); - return PyInt_FromLong(r-self->result->data->data); -} - -static void -_mysql_ResultObject_dealloc( - _mysql_ResultObject *self) -{ - PyObject_GC_UnTrack((PyObject *)self); - mysql_free_result(self->result); - _mysql_ResultObject_clear(self); - MyFree(self); -} - -static PyObject * -_mysql_ResultObject_repr( - _mysql_ResultObject *self) -{ - char buf[300]; - sprintf(buf, "<_mysql.result object at %lx>", - (long)self); -#ifdef IS_PY3K - return PyUnicode_FromString(buf); -#else - return PyString_FromString(buf); -#endif -} - -static PyMethodDef _mysql_ConnectionObject_methods[] = { - { - "affected_rows", - (PyCFunction)_mysql_ConnectionObject_affected_rows, - METH_VARARGS, - _mysql_ConnectionObject_affected_rows__doc__ - }, - { - "autocommit", - (PyCFunction)_mysql_ConnectionObject_autocommit, - METH_VARARGS, - _mysql_ConnectionObject_autocommit__doc__ - }, - { - "commit", - (PyCFunction)_mysql_ConnectionObject_commit, - METH_VARARGS, - _mysql_ConnectionObject_commit__doc__ - }, - { - "rollback", - (PyCFunction)_mysql_ConnectionObject_rollback, - METH_VARARGS, - _mysql_ConnectionObject_rollback__doc__ - }, - { - "next_result", - (PyCFunction)_mysql_ConnectionObject_next_result, - METH_VARARGS, - _mysql_ConnectionObject_next_result__doc__ - }, -#if MYSQL_VERSION_ID >= 40100 - { - "set_server_option", - (PyCFunction)_mysql_ConnectionObject_set_server_option, - METH_VARARGS, - _mysql_ConnectionObject_set_server_option__doc__ - }, - { - "sqlstate", - (PyCFunction)_mysql_ConnectionObject_sqlstate, - METH_VARARGS, - _mysql_ConnectionObject_sqlstate__doc__ - }, - { - "warning_count", - (PyCFunction)_mysql_ConnectionObject_warning_count, - METH_VARARGS, - _mysql_ConnectionObject_warning_count__doc__ - }, -#endif -#if MYSQL_VERSION_ID >= 32303 - { - "change_user", - (PyCFunction)_mysql_ConnectionObject_change_user, - METH_VARARGS | METH_KEYWORDS, - _mysql_ConnectionObject_change_user__doc__ - }, -#endif - { - "character_set_name", - (PyCFunction)_mysql_ConnectionObject_character_set_name, - METH_VARARGS, - _mysql_ConnectionObject_character_set_name__doc__ - }, -#if MYSQL_VERSION_ID >= 50007 - { - "set_character_set", - (PyCFunction)_mysql_ConnectionObject_set_character_set, - METH_VARARGS, - _mysql_ConnectionObject_set_character_set__doc__ - }, -#endif -#if MYSQL_VERSION_ID >= 50010 - { - "get_character_set_info", - (PyCFunction)_mysql_ConnectionObject_get_character_set_info, - METH_VARARGS, - _mysql_ConnectionObject_get_character_set_info__doc__ - }, -#endif - { - "close", - (PyCFunction)_mysql_ConnectionObject_close, - METH_VARARGS, - _mysql_ConnectionObject_close__doc__ - }, - { - "dump_debug_info", - (PyCFunction)_mysql_ConnectionObject_dump_debug_info, - METH_VARARGS, - _mysql_ConnectionObject_dump_debug_info__doc__ - }, - { - "escape", - (PyCFunction)_mysql_escape, - METH_VARARGS, - _mysql_escape__doc__ - }, - { - "escape_string", - (PyCFunction)_mysql_escape_string, - METH_VARARGS, - _mysql_escape_string__doc__ - }, - { - "error", - (PyCFunction)_mysql_ConnectionObject_error, - METH_VARARGS, - _mysql_ConnectionObject_error__doc__ - }, - { - "errno", - (PyCFunction)_mysql_ConnectionObject_errno, - METH_VARARGS, - _mysql_ConnectionObject_errno__doc__ - }, - { - "field_count", - (PyCFunction)_mysql_ConnectionObject_field_count, - METH_VARARGS, - _mysql_ConnectionObject_field_count__doc__ - }, - { - "get_host_info", - (PyCFunction)_mysql_ConnectionObject_get_host_info, - METH_VARARGS, - _mysql_ConnectionObject_get_host_info__doc__ - }, - { - "get_proto_info", - (PyCFunction)_mysql_ConnectionObject_get_proto_info, - METH_VARARGS, - _mysql_ConnectionObject_get_proto_info__doc__ - }, - { - "get_server_info", - (PyCFunction)_mysql_ConnectionObject_get_server_info, - METH_VARARGS, - _mysql_ConnectionObject_get_server_info__doc__ - }, - { - "info", - (PyCFunction)_mysql_ConnectionObject_info, - METH_VARARGS, - _mysql_ConnectionObject_info__doc__ - }, - { - "insert_id", - (PyCFunction)_mysql_ConnectionObject_insert_id, - METH_VARARGS, - _mysql_ConnectionObject_insert_id__doc__ - }, - { - "kill", - (PyCFunction)_mysql_ConnectionObject_kill, - METH_VARARGS, - _mysql_ConnectionObject_kill__doc__ - }, - { - "ping", - (PyCFunction)_mysql_ConnectionObject_ping, - METH_VARARGS, - _mysql_ConnectionObject_ping__doc__ - }, - { - "query", - (PyCFunction)_mysql_ConnectionObject_query, - METH_VARARGS, - _mysql_ConnectionObject_query__doc__ - }, - { - "select_db", - (PyCFunction)_mysql_ConnectionObject_select_db, - METH_VARARGS, - _mysql_ConnectionObject_select_db__doc__ - }, - { - "shutdown", - (PyCFunction)_mysql_ConnectionObject_shutdown, - METH_VARARGS, - _mysql_ConnectionObject_shutdown__doc__ - }, - { - "stat", - (PyCFunction)_mysql_ConnectionObject_stat, - METH_VARARGS, - _mysql_ConnectionObject_stat__doc__ - }, - { - "store_result", - (PyCFunction)_mysql_ConnectionObject_store_result, - METH_VARARGS, - _mysql_ConnectionObject_store_result__doc__ - }, - { - "string_literal", - (PyCFunction)_mysql_string_literal, - METH_VARARGS, - _mysql_string_literal__doc__}, - { - "thread_id", - (PyCFunction)_mysql_ConnectionObject_thread_id, - METH_VARARGS, - _mysql_ConnectionObject_thread_id__doc__ - }, - { - "use_result", - (PyCFunction)_mysql_ConnectionObject_use_result, - METH_VARARGS, - _mysql_ConnectionObject_use_result__doc__ - }, - {NULL, NULL} /* sentinel */ -}; - -static MyMemberlist(_mysql_ConnectionObject_memberlist)[] = { - MyMember( - "open", - T_INT, - offsetof(_mysql_ConnectionObject,open), - READONLY, - "True if connection is open" - ), - MyMember( - "converter", - T_OBJECT, - offsetof(_mysql_ConnectionObject,converter), - 0, - "Type conversion mapping" - ), - MyMember( - "server_capabilities", - T_UINT, - offsetof(_mysql_ConnectionObject,connection.server_capabilities), - READONLY, - "Capabilites of server; consult MySQLdb.constants.CLIENT" - ), - MyMember( - "port", - T_UINT, - offsetof(_mysql_ConnectionObject,connection.port), - READONLY, - "TCP/IP port of the server connection" - ), - MyMember( - "client_flag", - T_UINT, - READONLY, - offsetof(_mysql_ConnectionObject,connection.client_flag), - "Client flags; refer to MySQLdb.constants.CLIENT" - ), - {NULL} /* Sentinel */ -}; - -static PyMethodDef _mysql_ResultObject_methods[] = { - { - "data_seek", - (PyCFunction)_mysql_ResultObject_data_seek, - METH_VARARGS, - _mysql_ResultObject_data_seek__doc__ - }, - { - "row_seek", - (PyCFunction)_mysql_ResultObject_row_seek, - METH_VARARGS, - _mysql_ResultObject_row_seek__doc__ - }, - { - "row_tell", - (PyCFunction)_mysql_ResultObject_row_tell, - METH_VARARGS, - _mysql_ResultObject_row_tell__doc__ - }, - { - "describe", - (PyCFunction)_mysql_ResultObject_describe, - METH_VARARGS, - _mysql_ResultObject_describe__doc__ - }, - { - "fetch_row", - (PyCFunction)_mysql_ResultObject_fetch_row, - METH_VARARGS | METH_KEYWORDS, - _mysql_ResultObject_fetch_row__doc__ - }, - { - "field_flags", - (PyCFunction)_mysql_ResultObject_field_flags, - METH_VARARGS, - _mysql_ResultObject_field_flags__doc__ - }, - { - "num_fields", - (PyCFunction)_mysql_ResultObject_num_fields, - METH_VARARGS, - _mysql_ResultObject_num_fields__doc__ - }, - { - "num_rows", - (PyCFunction)_mysql_ResultObject_num_rows, - METH_VARARGS, - _mysql_ResultObject_num_rows__doc__ - }, - {NULL, NULL} /* sentinel */ -}; - -static MyMemberlist(_mysql_ResultObject_memberlist)[] = { - MyMember( - "converter", - T_OBJECT, - offsetof(_mysql_ResultObject,converter), - READONLY, - "Type conversion mapping" - ), - {NULL} /* Sentinel */ -}; - -static PyObject * -_mysql_ConnectionObject_getattr( - _mysql_ConnectionObject *self, - char *name) -{ -#ifndef IS_PY3K - PyObject *res; - - res = Py_FindMethod(_mysql_ConnectionObject_methods, (PyObject *)self, name); - if (res != NULL) - return res; - PyErr_Clear(); -#endif - if (strcmp(name, "closed") == 0) - return PyInt_FromLong((long)!(self->open)); -#if PY_VERSION_HEX < 0x02020000 - return PyMember_Get((char *)self, _mysql_ConnectionObject_memberlist, name); -#else - { - MyMemberlist(*l); - for (l = _mysql_ConnectionObject_memberlist; l->name != NULL; l++) { - if (strcmp(l->name, name) == 0) - return PyMember_GetOne((char *)self, l); - } - PyErr_SetString(PyExc_AttributeError, name); - return NULL; - } -#endif -} - -static PyObject * -_mysql_ResultObject_getattr( - _mysql_ResultObject *self, - char *name) -{ -#ifndef IS_PY3K - PyObject *res; - - res = Py_FindMethod(_mysql_ResultObject_methods, (PyObject *)self, name); - if (res != NULL) - return res; - PyErr_Clear(); -#endif -#if PY_VERSION_HEX < 0x02020000 - return PyMember_Get((char *)self, _mysql_ResultObject_memberlist, name); -#else - { - MyMemberlist(*l); - for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++) { - if (strcmp(l->name, name) == 0) - return PyMember_GetOne((char *)self, l); - } - PyErr_SetString(PyExc_AttributeError, name); - return NULL; - } -#endif -} - -static int -_mysql_ConnectionObject_setattr( - _mysql_ConnectionObject *self, - char *name, - PyObject *v) -{ - if (v == NULL) { - PyErr_SetString(PyExc_AttributeError, - "can't delete connection attributes"); - return -1; - } -#if PY_VERSION_HEX < 0x02020000 - return PyMember_Set((char *)self, _mysql_ConnectionObject_memberlist, name, v); -#else - { - MyMemberlist(*l); - for (l = _mysql_ConnectionObject_memberlist; l->name != NULL; l++) - if (strcmp(l->name, name) == 0) - return PyMember_SetOne((char *)self, l, v); - } - PyErr_SetString(PyExc_AttributeError, name); - return -1; -#endif -} - -static int -_mysql_ResultObject_setattr( - _mysql_ResultObject *self, - char *name, - PyObject *v) -{ - if (v == NULL) { - PyErr_SetString(PyExc_AttributeError, - "can't delete connection attributes"); - return -1; - } -#if PY_VERSION_HEX < 0x02020000 - return PyMember_Set((char *)self, _mysql_ResultObject_memberlist, name, v); -#else - { - MyMemberlist(*l); - for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++) - if (strcmp(l->name, name) == 0) - return PyMember_SetOne((char *)self, l, v); - } - PyErr_SetString(PyExc_AttributeError, name); - return -1; -#endif -} - -PyTypeObject _mysql_ConnectionObject_Type = { -#ifdef IS_PY3K - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, -#endif - "_mysql.connection", /* (char *)tp_name For printing */ - sizeof(_mysql_ConnectionObject), - 0, - (destructor)_mysql_ConnectionObject_dealloc, /* tp_dealloc */ - 0, /*tp_print*/ - (getattrfunc)_mysql_ConnectionObject_getattr, /* tp_getattr */ - (setattrfunc)_mysql_ConnectionObject_setattr, /* tp_setattr */ - 0, /*tp_compare*/ - (reprfunc)_mysql_ConnectionObject_repr, /* tp_repr */ - - /* Method suites for standard classes */ - - 0, /* (PyNumberMethods *) tp_as_number */ - 0, /* (PySequenceMethods *) tp_as_sequence */ - 0, /* (PyMappingMethods *) tp_as_mapping */ - - /* More standard operations (here for binary compatibility) */ - - 0, /* (hashfunc) tp_hash */ - 0, /* (ternaryfunc) tp_call */ - 0, /* (reprfunc) tp_str */ - 0, /* (getattrofunc) tp_getattro */ - 0, /* (setattrofunc) tp_setattro */ - - /* Functions to access object as input/output buffer */ - 0, /* (PyBufferProcs *) tp_as_buffer */ - - /* Flags to define presence of optional/expanded features */ -#if PY_VERSION_HEX < 0x02020000 - Py_TPFLAGS_DEFAULT, /* (long) tp_flags */ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, -#endif - _mysql_connect__doc__, /* (char *) tp_doc Documentation string */ -#if PY_VERSION_HEX >= 0x02000000 - /* Assigned meaning in release 2.0 */ -#if PY_VERSION_HEX >= 0x02020000 - /* call function for all accessible objects */ - (traverseproc) _mysql_ConnectionObject_traverse, /* tp_traverse */ - - /* delete references to contained objects */ - (inquiry) _mysql_ConnectionObject_clear, /* tp_clear */ -#else - /* not supporting pre-2.2 GC */ - 0, - 0, -#endif -#if PY_VERSION_HEX >= 0x02010000 - /* Assigned meaning in release 2.1 */ - /* rich comparisons */ - 0, /* (richcmpfunc) tp_richcompare */ - - /* weak reference enabler */ - 0, /* (long) tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - /* Added in release 2.2 */ - /* Iterators */ - 0, /* (getiterfunc) tp_iter */ - 0, /* (iternextfunc) tp_iternext */ - - /* Attribute descriptor and subclassing stuff */ - (struct PyMethodDef *)_mysql_ConnectionObject_methods, /* tp_methods */ - (MyMemberlist(*))_mysql_ConnectionObject_memberlist, /* tp_members */ - 0, /* (struct getsetlist *) tp_getset; */ - 0, /* (struct _typeobject *) tp_base; */ - 0, /* (PyObject *) tp_dict */ - 0, /* (descrgetfunc) tp_descr_get */ - 0, /* (descrsetfunc) tp_descr_set */ - 0, /* (long) tp_dictoffset */ - (initproc)_mysql_ConnectionObject_Initialize, /* tp_init */ - NULL, /* tp_alloc */ - NULL, /* tp_new */ - NULL, /* tp_free Low-level free-memory routine */ - 0, /* (PyObject *) tp_bases */ - 0, /* (PyObject *) tp_mro method resolution order */ - 0, /* (PyObject *) tp_defined */ -#endif /* python 2.2 */ -#endif /* python 2.1 */ -#endif /* python 2.0 */ -} ; - -PyTypeObject _mysql_ResultObject_Type = { -#ifdef IS_PY3K - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, -#endif - "_mysql.result", - sizeof(_mysql_ResultObject), - 0, - (destructor)_mysql_ResultObject_dealloc, /* tp_dealloc */ - 0, /*tp_print*/ - (getattrfunc)_mysql_ResultObject_getattr, /* tp_getattr */ - (setattrfunc)_mysql_ResultObject_setattr, /* tp_setattr */ - 0, /*tp_compare*/ - (reprfunc)_mysql_ResultObject_repr, /* tp_repr */ - - /* Method suites for standard classes */ - - 0, /* (PyNumberMethods *) tp_as_number */ - 0, /* (PySequenceMethods *) tp_as_sequence */ - 0, /* (PyMappingMethods *) tp_as_mapping */ - - /* More standard operations (here for binary compatibility) */ - - 0, /* (hashfunc) tp_hash */ - 0, /* (ternaryfunc) tp_call */ - 0, /* (reprfunc) tp_str */ - 0, /* (getattrofunc) tp_getattro */ - 0, /* (setattrofunc) tp_setattro */ - - /* Functions to access object as input/output buffer */ - 0, /* (PyBufferProcs *) tp_as_buffer */ - - /* Flags to define presence of optional/expanded features */ -#if PY_VERSION_HEX < 0x02020000 - Py_TPFLAGS_DEFAULT, /* (long) tp_flags */ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, -#endif - - _mysql_ResultObject__doc__, /* (char *) tp_doc Documentation string */ -#if PY_VERSION_HEX >= 0x02000000 - /* Assigned meaning in release 2.0 */ -#if PY_VERSION_HEX >= 0x02020000 - /* call function for all accessible objects */ - (traverseproc) _mysql_ResultObject_traverse, /* tp_traverse */ - - /* delete references to contained objects */ - (inquiry) _mysql_ResultObject_clear, /* tp_clear */ -#else - /* not supporting pre-2.2 GC */ - 0, - 0, -#endif -#if PY_VERSION_HEX >= 0x02010000 - /* Assigned meaning in release 2.1 */ - /* rich comparisons */ - 0, /* (richcmpfunc) tp_richcompare */ - - /* weak reference enabler */ - 0, /* (long) tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - /* Added in release 2.2 */ - /* Iterators */ - 0, /* (getiterfunc) tp_iter */ - 0, /* (iternextfunc) tp_iternext */ - - /* Attribute descriptor and subclassing stuff */ - (struct PyMethodDef *) _mysql_ResultObject_methods, /* tp_methods */ - (MyMemberlist(*)) _mysql_ResultObject_memberlist, /*tp_members */ - 0, /* (struct getsetlist *) tp_getset; */ - 0, /* (struct _typeobject *) tp_base; */ - 0, /* (PyObject *) tp_dict */ - 0, /* (descrgetfunc) tp_descr_get */ - 0, /* (descrsetfunc) tp_descr_set */ - 0, /* (long) tp_dictoffset */ - (initproc)_mysql_ResultObject_Initialize, /* tp_init */ - NULL, /* tp_alloc */ - NULL, /* tp_new */ - NULL, /* tp_free Low-level free-memory routine */ - 0, /* (PyObject *) tp_bases */ - 0, /* (PyObject *) tp_mro method resolution order */ - 0, /* (PyObject *) tp_defined */ -#endif /* python 2.2 */ -#endif /* python 2.1 */ -#endif /* python 2.0 */ -}; - -static PyMethodDef -_mysql_methods[] = { - { - "connect", - (PyCFunction)_mysql_connect, - METH_VARARGS | METH_KEYWORDS, - _mysql_connect__doc__ - }, - { - "debug", - (PyCFunction)_mysql_debug, - METH_VARARGS, - _mysql_debug__doc__ - }, - { - "escape", - (PyCFunction)_mysql_escape, - METH_VARARGS, - _mysql_escape__doc__ - }, - { - "escape_sequence", - (PyCFunction)_mysql_escape_sequence, - METH_VARARGS, - _mysql_escape_sequence__doc__ - }, - { - "escape_dict", - (PyCFunction)_mysql_escape_dict, - METH_VARARGS, - _mysql_escape_dict__doc__ - }, - { - "escape_string", - (PyCFunction)_mysql_escape_string, - METH_VARARGS, - _mysql_escape_string__doc__ - }, - { - "string_literal", - (PyCFunction)_mysql_string_literal, - METH_VARARGS, - _mysql_string_literal__doc__ - }, - { - "get_client_info", - (PyCFunction)_mysql_get_client_info, - METH_VARARGS, - _mysql_get_client_info__doc__ - }, -#if MYSQL_VERSION_ID >= 32314 - { - "thread_safe", - (PyCFunction)_mysql_thread_safe, - METH_VARARGS, - _mysql_thread_safe__doc__ - }, -#endif - { - "server_init", - (PyCFunction)_mysql_server_init, - METH_VARARGS | METH_KEYWORDS, - _mysql_server_init__doc__ - }, - { - "server_end", - (PyCFunction)_mysql_server_end, - METH_VARARGS, - _mysql_server_end__doc__ - }, - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -_mysql_NewException( - PyObject *dict, - PyObject *edict, - char *name) -{ - PyObject *e; - - if (!(e = PyDict_GetItemString(edict, name))) - return NULL; - if (PyDict_SetItemString(dict, name, e)) return NULL; - return e; -} - -#define QUOTE(X) _QUOTE(X) -#define _QUOTE(X) #X - -static char _mysql___doc__[] = -"an adaptation of the MySQL C API (mostly)\n\ -\n\ -You probably are better off using MySQLdb instead of using this\n\ -module directly.\n\ -\n\ -In general, renaming goes from mysql_* to _mysql.*. _mysql.connect()\n\ -returns a connection object (MYSQL). Functions which expect MYSQL * as\n\ -an argument are now methods of the connection object. A number of things\n\ -return result objects (MYSQL_RES). Functions which expect MYSQL_RES * as\n\ -an argument are now methods of the result object. Deprecated functions\n\ -(as of 3.23) are NOT implemented.\n\ -"; - -#ifdef IS_PY3K -static struct PyModuleDef _mysqlmodule = { - PyModuleDef_HEAD_INIT, - "_mysql", /* name of module */ - _mysql___doc__, /* module documentation, may be NULL */ - -1, /* size of per-interpreter state of the module, - or -1 if the module keeps state in global variables. */ - _mysql_methods -}; - -PyMODINIT_FUNC -PyInit__mysql(void) -#else -DL_EXPORT(void) -init_mysql(void) -#endif -{ - PyObject *dict, *module, *emod, *edict; -#ifdef IS_PY3K - module = PyModule_Create(&_mysqlmodule); - if (!module) return module; /* this really should never happen */ -#else - module = Py_InitModule4("_mysql", _mysql_methods, _mysql___doc__, - (PyObject *)NULL, PYTHON_API_VERSION); - if (!module) return; /* this really should never happen */ -#endif -#ifdef IS_PY3K - Py_TYPE(&_mysql_ConnectionObject_Type) = &PyType_Type; - Py_TYPE(&_mysql_ResultObject_Type) = &PyType_Type; -#else - _mysql_ConnectionObject_Type.ob_type = &PyType_Type; - _mysql_ResultObject_Type.ob_type = &PyType_Type; -#endif -#if PY_VERSION_HEX >= 0x02020000 - _mysql_ConnectionObject_Type.tp_alloc = PyType_GenericAlloc; - _mysql_ConnectionObject_Type.tp_new = PyType_GenericNew; -#ifndef IS_PY3K - _mysql_ConnectionObject_Type.tp_free = _PyObject_GC_Del; -#endif - _mysql_ResultObject_Type.tp_alloc = PyType_GenericAlloc; - _mysql_ResultObject_Type.tp_new = PyType_GenericNew; -#ifndef IS_PY3K - _mysql_ResultObject_Type.tp_free = _PyObject_GC_Del; -#endif -#endif - - if (!(dict = PyModule_GetDict(module))) goto error; - if (PyDict_SetItemString(dict, "version_info", - PyRun_String(QUOTE(version_info), Py_eval_input, - dict, dict))) - goto error; - if (PyDict_SetItemString(dict, "__version__", -#ifdef IS_PY3K - PyUnicode_FromString(QUOTE(__version__)))) -#else - PyString_FromString(QUOTE(__version__)))) -#endif - goto error; - if (PyDict_SetItemString(dict, "connection", - (PyObject *)&_mysql_ConnectionObject_Type)) - goto error; - Py_INCREF(&_mysql_ConnectionObject_Type); - if (PyDict_SetItemString(dict, "result", - (PyObject *)&_mysql_ResultObject_Type)) - goto error; - Py_INCREF(&_mysql_ResultObject_Type); - if (!(emod = PyImport_ImportModule("_mysql_exceptions"))) { - PyErr_Print(); - goto error; - } - if (!(edict = PyModule_GetDict(emod))) goto error; - if (!(_mysql_MySQLError = - _mysql_NewException(dict, edict, "MySQLError"))) - goto error; - if (!(_mysql_Warning = - _mysql_NewException(dict, edict, "Warning"))) - goto error; - if (!(_mysql_Error = - _mysql_NewException(dict, edict, "Error"))) - goto error; - if (!(_mysql_InterfaceError = - _mysql_NewException(dict, edict, "InterfaceError"))) - goto error; - if (!(_mysql_DatabaseError = - _mysql_NewException(dict, edict, "DatabaseError"))) - goto error; - if (!(_mysql_DataError = - _mysql_NewException(dict, edict, "DataError"))) - goto error; - if (!(_mysql_OperationalError = - _mysql_NewException(dict, edict, "OperationalError"))) - goto error; - if (!(_mysql_IntegrityError = - _mysql_NewException(dict, edict, "IntegrityError"))) - goto error; - if (!(_mysql_InternalError = - _mysql_NewException(dict, edict, "InternalError"))) - goto error; - if (!(_mysql_ProgrammingError = - _mysql_NewException(dict, edict, "ProgrammingError"))) - goto error; - if (!(_mysql_NotSupportedError = - _mysql_NewException(dict, edict, "NotSupportedError"))) - goto error; - Py_DECREF(emod); -#ifdef IS_PY3K - if (!(_mysql_NULL = PyUnicode_FromString("NULL"))) - goto error; -#else - if (!(_mysql_NULL = PyString_FromString("NULL"))) - goto error; -#endif - if (PyDict_SetItemString(dict, "NULL", _mysql_NULL)) goto error; - error: - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_ImportError, - "_mysql: init failed"); - module = NULL; - } -#ifdef IS_PY3K - return module; -#endif -} - - diff --git a/MySQLdb/_mysql_exceptions.py b/MySQLdb/_mysql_exceptions.py deleted file mode 100644 index 3241e74..0000000 --- a/MySQLdb/_mysql_exceptions.py +++ /dev/null @@ -1,87 +0,0 @@ -"""_mysql_exceptions: Exception classes for _mysql and MySQLdb. - -These classes are dictated by the DB API v2.0: - - http://www.python.org/topics/database/DatabaseAPI-2.0.html -""" - -try: - from exceptions import Exception, StandardError, Warning -except ImportError: - # Python 3 - StandardError = Exception - - -class MySQLError(StandardError): - - """Exception related to operation with MySQL.""" - - -class Warning(Warning, MySQLError): - - """Exception raised for important warnings like data truncations - while inserting, etc.""" - -class Error(MySQLError): - - """Exception that is the base class of all other error exceptions - (not Warning).""" - - -class InterfaceError(Error): - - """Exception raised for errors that are related to the database - interface rather than the database itself.""" - - -class DatabaseError(Error): - - """Exception raised for errors that are related to the - database.""" - - -class DataError(DatabaseError): - - """Exception raised for errors that are due to problems with the - processed data like division by zero, numeric value out of range, - etc.""" - - -class OperationalError(DatabaseError): - - """Exception raised for errors that are related to the database's - operation and not necessarily under the control of the programmer, - e.g. an unexpected disconnect occurs, the data source name is not - found, a transaction could not be processed, a memory allocation - error occurred during processing, etc.""" - - -class IntegrityError(DatabaseError): - - """Exception raised when the relational integrity of the database - is affected, e.g. a foreign key check fails, duplicate key, - etc.""" - - -class InternalError(DatabaseError): - - """Exception raised when the database encounters an internal - error, e.g. the cursor is not valid anymore, the transaction is - out of sync, etc.""" - - -class ProgrammingError(DatabaseError): - - """Exception raised for programming errors, e.g. table not found - or already exists, syntax error in the SQL statement, wrong number - of parameters specified, etc.""" - - -class NotSupportedError(DatabaseError): - - """Exception raised in case a method or database API was used - which is not supported by the database, e.g. requesting a - .rollback() on a connection that does not support transaction or - has transactions turned off.""" - - diff --git a/MySQLdb/connections.py b/MySQLdb/connections.py new file mode 100644 index 0000000..1d6fa82 --- /dev/null +++ b/MySQLdb/connections.py @@ -0,0 +1,333 @@ +""" + +This module implements connections for MySQLdb. Presently there is +only one class: Connection. Others are unlikely. However, you might +want to make your own subclasses. In most cases, you will probably +override Connection.default_cursor with a non-standard Cursor class. + +""" +from MySQLdb import cursors +from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ + DatabaseError, OperationalError, IntegrityError, InternalError, \ + NotSupportedError, ProgrammingError +import types, _mysql +import re + + +def defaulterrorhandler(connection, cursor, errorclass, errorvalue): + """ + + If cursor is not None, (errorclass, errorvalue) is appended to + cursor.messages; otherwise it is appended to + connection.messages. Then errorclass is raised with errorvalue as + the value. + + You can override this with your own error handler by assigning it + to the instance. + + """ + error = errorclass, errorvalue + if cursor: + cursor.messages.append(error) + else: + connection.messages.append(error) + del cursor + del connection + raise errorclass, errorvalue + +re_numeric_part = re.compile(r"^(\d+)") + +def numeric_part(s): + """Returns the leading numeric part of a string. + + >>> numeric_part("20-alpha") + 20 + >>> numeric_part("foo") + >>> numeric_part("16b") + 16 + """ + + m = re_numeric_part.match(s) + if m: + return int(m.group(1)) + return None + + +class Connection(_mysql.connection): + + """MySQL Database Connection Object""" + + default_cursor = cursors.Cursor + + def __init__(self, *args, **kwargs): + """ + + Create a connection to the database. It is strongly recommended + that you only use keyword parameters. Consult the MySQL C API + documentation for more information. + + host + string, host to connect + + user + string, user to connect as + + passwd + string, password to use + + db + string, database to use + + port + integer, TCP/IP port to connect to + + unix_socket + string, location of unix_socket to use + + conv + conversion dictionary, see MySQLdb.converters + + connect_timeout + number of seconds to wait before the connection attempt + fails. + + compress + if set, compression is enabled + + named_pipe + if set, a named pipe is used to connect (Windows only) + + init_command + command which is run once the connection is created + + read_default_file + file from which default client values are read + + read_default_group + configuration group to use from the default file + + cursorclass + class object, used to create cursors (keyword only) + + use_unicode + If True, text-like columns are returned as unicode objects + using the connection's character set. Otherwise, text-like + columns are returned as strings. columns are returned as + normal strings. Unicode objects will always be encoded to + the connection's character set regardless of this setting. + + charset + If supplied, the connection character set will be changed + to this character set (MySQL-4.1 and newer). This implies + use_unicode=True. + + sql_mode + If supplied, the session SQL mode will be changed to this + setting (MySQL-4.1 and newer). For more details and legal + values, see the MySQL documentation. + + client_flag + integer, flags to use or 0 + (see MySQL docs or constants/CLIENTS.py) + + ssl + dictionary or mapping, contains SSL connection parameters; + see the MySQL documentation for more details + (mysql_ssl_set()). If this is set, and the client does not + support SSL, NotSupportedError will be raised. + + local_infile + integer, non-zero enables LOAD LOCAL INFILE; zero disables + + There are a number of undocumented, non-standard methods. See the + documentation for the MySQL C API for some hints on what they do. + + """ + from MySQLdb.constants import CLIENT, FIELD_TYPE + from MySQLdb.converters import conversions + from weakref import proxy, WeakValueDictionary + + import types + + kwargs2 = kwargs.copy() + + if 'conv' in kwargs: + conv = kwargs['conv'] + else: + conv = conversions + + conv2 = {} + for k, v in conv.items(): + if isinstance(k, int) and isinstance(v, list): + conv2[k] = v[:] + else: + conv2[k] = v + kwargs2['conv'] = conv2 + + cursorclass = kwargs2.pop('cursorclass', self.default_cursor) + charset = kwargs2.pop('charset', '') + + if charset: + use_unicode = True + else: + use_unicode = False + + use_unicode = kwargs2.pop('use_unicode', use_unicode) + sql_mode = kwargs2.pop('sql_mode', '') + + client_flag = kwargs.get('client_flag', 0) + client_version = tuple([ numeric_part(n) for n in _mysql.get_client_info().split('.')[:2] ]) + if client_version >= (4, 1): + client_flag |= CLIENT.MULTI_STATEMENTS + if client_version >= (5, 0): + client_flag |= CLIENT.MULTI_RESULTS + + kwargs2['client_flag'] = client_flag + + super(Connection, self).__init__(*args, **kwargs2) + self.cursorclass = cursorclass + self.encoders = dict([ (k, v) for k, v in conv.items() + if type(k) is not int ]) + + self._server_version = tuple([ numeric_part(n) for n in self.get_server_info().split('.')[:2] ]) + + db = proxy(self) + def _get_string_literal(): + def string_literal(obj, dummy=None): + return db.string_literal(obj) + return string_literal + + def _get_unicode_literal(): + def unicode_literal(u, dummy=None): + return db.literal(u.encode(unicode_literal.charset)) + return unicode_literal + + def _get_string_decoder(): + def string_decoder(s): + return s.decode(string_decoder.charset) + return string_decoder + + string_literal = _get_string_literal() + self.unicode_literal = unicode_literal = _get_unicode_literal() + self.string_decoder = string_decoder = _get_string_decoder() + if not charset: + charset = self.character_set_name() + self.set_character_set(charset) + + if sql_mode: + self.set_sql_mode(sql_mode) + + if use_unicode: + self.converter[FIELD_TYPE.STRING].append((None, string_decoder)) + self.converter[FIELD_TYPE.VAR_STRING].append((None, string_decoder)) + self.converter[FIELD_TYPE.VARCHAR].append((None, string_decoder)) + self.converter[FIELD_TYPE.BLOB].append((None, string_decoder)) + + self.encoders[types.StringType] = string_literal + self.encoders[types.UnicodeType] = unicode_literal + self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS + if self._transactional: + # PEP-249 requires autocommit to be initially off + self.autocommit(False) + self.messages = [] + + def cursor(self, cursorclass=None): + """ + + Create a cursor on which queries may be performed. The + optional cursorclass parameter is used to create the + Cursor. By default, self.cursorclass=cursors.Cursor is + used. + + """ + return (cursorclass or self.cursorclass)(self) + + def __enter__(self): return self.cursor() + + def __exit__(self, exc, value, tb): + if exc: + self.rollback() + else: + self.commit() + + def literal(self, o): + """ + + If o is a single object, returns an SQL literal as a string. + If o is a non-string sequence, the items of the sequence are + converted and returned as a sequence. + + Non-standard. For internal use; do not use this in your + applications. + + """ + return self.escape(o, self.encoders) + + def begin(self): + """Explicitly begin a connection. Non-standard. + DEPRECATED: Will be removed in 1.3. + Use an SQL BEGIN statement instead.""" + from warnings import warn + warn("begin() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + self.query("BEGIN") + + if not hasattr(_mysql.connection, 'warning_count'): + + def warning_count(self): + """Return the number of warnings generated from the + last query. This is derived from the info() method.""" + from string import atoi + info = self.info() + if info: + return atoi(info.split()[-1]) + else: + return 0 + + def set_character_set(self, charset): + """Set the connection character set to charset. The character + set can only be changed in MySQL-4.1 and newer. If you try + to change the character set from the current value in an + older version, NotSupportedError will be raised.""" + if self.character_set_name() != charset: + try: + super(Connection, self).set_character_set(charset) + except AttributeError: + if self._server_version < (4, 1): + raise NotSupportedError("server is too old to set charset") + self.query('SET NAMES %s' % charset) + self.store_result() + self.string_decoder.charset = charset + self.unicode_literal.charset = charset + + def set_sql_mode(self, sql_mode): + """Set the connection sql_mode. See MySQL documentation for + legal values.""" + if self._server_version < (4, 1): + raise NotSupportedError("server is too old to set sql_mode") + self.query("SET SESSION sql_mode='%s'" % sql_mode) + self.store_result() + + def show_warnings(self): + """Return detailed information about warnings as a + sequence of tuples of (Level, Code, Message). This + is only supported in MySQL-4.1 and up. If your server + is an earlier version, an empty sequence is returned.""" + if self._server_version < (4,1): return () + self.query("SHOW WARNINGS") + r = self.store_result() + warnings = r.fetch_row(0) + return warnings + + Warning = Warning + Error = Error + InterfaceError = InterfaceError + DatabaseError = DatabaseError + DataError = DataError + OperationalError = OperationalError + IntegrityError = IntegrityError + InternalError = InternalError + ProgrammingError = ProgrammingError + NotSupportedError = NotSupportedError + + errorhandler = defaulterrorhandler diff --git a/MySQLdb/constants/CLIENT.py b/MySQLdb/constants/CLIENT.py new file mode 100644 index 0000000..6559917 --- /dev/null +++ b/MySQLdb/constants/CLIENT.py @@ -0,0 +1,29 @@ +"""MySQL CLIENT constants + +These constants are used when creating the connection. Use bitwise-OR +(|) to combine options together, and pass them as the client_flags +parameter to MySQLdb.Connection. For more information on these flags, +see the MySQL C API documentation for mysql_real_connect(). + +""" + +LONG_PASSWORD = 1 +FOUND_ROWS = 2 +LONG_FLAG = 4 +CONNECT_WITH_DB = 8 +NO_SCHEMA = 16 +COMPRESS = 32 +ODBC = 64 +LOCAL_FILES = 128 +IGNORE_SPACE = 256 +CHANGE_USER = 512 +INTERACTIVE = 1024 +SSL = 2048 +IGNORE_SIGPIPE = 4096 +TRANSACTIONS = 8192 # mysql_com.h was WRONG prior to 3.23.35 +RESERVED = 16384 +SECURE_CONNECTION = 32768 +MULTI_STATEMENTS = 65536 +MULTI_RESULTS = 131072 + + diff --git a/MySQLdb/constants/CR.py b/MySQLdb/constants/CR.py new file mode 100644 index 0000000..249dfec --- /dev/null +++ b/MySQLdb/constants/CR.py @@ -0,0 +1,30 @@ +"""MySQL Connection Errors + +Nearly all of these raise OperationalError. COMMANDS_OUT_OF_SYNC +raises ProgrammingError. + +""" + +MIN_ERROR = 2000 +MAX_ERROR = 2999 +UNKNOWN_ERROR = 2000 +SOCKET_CREATE_ERROR = 2001 +CONNECTION_ERROR = 2002 +CONN_HOST_ERROR = 2003 +IPSOCK_ERROR = 2004 +UNKNOWN_HOST = 2005 +SERVER_GONE_ERROR = 2006 +VERSION_ERROR = 2007 +OUT_OF_MEMORY = 2008 +WRONG_HOST_INFO = 2009 +LOCALHOST_CONNECTION = 2010 +TCP_CONNECTION = 2011 +SERVER_HANDSHAKE_ERR = 2012 +SERVER_LOST = 2013 +COMMANDS_OUT_OF_SYNC = 2014 +NAMEDPIPE_CONNECTION = 2015 +NAMEDPIPEWAIT_ERROR = 2016 +NAMEDPIPEOPEN_ERROR = 2017 +NAMEDPIPESETSTATE_ERROR = 2018 +CANT_READ_CHARSET = 2019 +NET_PACKET_TOO_LARGE = 2020 diff --git a/MySQLdb/constants/ER.py b/MySQLdb/constants/ER.py new file mode 100644 index 0000000..ed45f3a --- /dev/null +++ b/MySQLdb/constants/ER.py @@ -0,0 +1,467 @@ +"""MySQL ER Constants + +These constants are error codes for the bulk of the error conditions +that may occur. + +""" + +HASHCHK = 1000 +NISAMCHK = 1001 +NO = 1002 +YES = 1003 +CANT_CREATE_FILE = 1004 +CANT_CREATE_TABLE = 1005 +CANT_CREATE_DB = 1006 +DB_CREATE_EXISTS = 1007 +DB_DROP_EXISTS = 1008 +DB_DROP_DELETE = 1009 +DB_DROP_RMDIR = 1010 +CANT_DELETE_FILE = 1011 +CANT_FIND_SYSTEM_REC = 1012 +CANT_GET_STAT = 1013 +CANT_GET_WD = 1014 +CANT_LOCK = 1015 +CANT_OPEN_FILE = 1016 +FILE_NOT_FOUND = 1017 +CANT_READ_DIR = 1018 +CANT_SET_WD = 1019 +CHECKREAD = 1020 +DISK_FULL = 1021 +DUP_KEY = 1022 +ERROR_ON_CLOSE = 1023 +ERROR_ON_READ = 1024 +ERROR_ON_RENAME = 1025 +ERROR_ON_WRITE = 1026 +FILE_USED = 1027 +FILSORT_ABORT = 1028 +FORM_NOT_FOUND = 1029 +GET_ERRNO = 1030 +ILLEGAL_HA = 1031 +KEY_NOT_FOUND = 1032 +NOT_FORM_FILE = 1033 +NOT_KEYFILE = 1034 +OLD_KEYFILE = 1035 +OPEN_AS_READONLY = 1036 +OUTOFMEMORY = 1037 +OUT_OF_SORTMEMORY = 1038 +UNEXPECTED_EOF = 1039 +CON_COUNT_ERROR = 1040 +OUT_OF_RESOURCES = 1041 +BAD_HOST_ERROR = 1042 +HANDSHAKE_ERROR = 1043 +DBACCESS_DENIED_ERROR = 1044 +ACCESS_DENIED_ERROR = 1045 +NO_DB_ERROR = 1046 +UNKNOWN_COM_ERROR = 1047 +BAD_NULL_ERROR = 1048 +BAD_DB_ERROR = 1049 +TABLE_EXISTS_ERROR = 1050 +BAD_TABLE_ERROR = 1051 +NON_UNIQ_ERROR = 1052 +SERVER_SHUTDOWN = 1053 +BAD_FIELD_ERROR = 1054 +WRONG_FIELD_WITH_GROUP = 1055 +WRONG_GROUP_FIELD = 1056 +WRONG_SUM_SELECT = 1057 +WRONG_VALUE_COUNT = 1058 +TOO_LONG_IDENT = 1059 +DUP_FIELDNAME = 1060 +DUP_KEYNAME = 1061 +DUP_ENTRY = 1062 +WRONG_FIELD_SPEC = 1063 +PARSE_ERROR = 1064 +EMPTY_QUERY = 1065 +NONUNIQ_TABLE = 1066 +INVALID_DEFAULT = 1067 +MULTIPLE_PRI_KEY = 1068 +TOO_MANY_KEYS = 1069 +TOO_MANY_KEY_PARTS = 1070 +TOO_LONG_KEY = 1071 +KEY_COLUMN_DOES_NOT_EXITS = 1072 +BLOB_USED_AS_KEY = 1073 +TOO_BIG_FIELDLENGTH = 1074 +WRONG_AUTO_KEY = 1075 +READY = 1076 +NORMAL_SHUTDOWN = 1077 +GOT_SIGNAL = 1078 +SHUTDOWN_COMPLETE = 1079 +FORCING_CLOSE = 1080 +IPSOCK_ERROR = 1081 +NO_SUCH_INDEX = 1082 +WRONG_FIELD_TERMINATORS = 1083 +BLOBS_AND_NO_TERMINATED = 1084 +TEXTFILE_NOT_READABLE = 1085 +FILE_EXISTS_ERROR = 1086 +LOAD_INFO = 1087 +ALTER_INFO = 1088 +WRONG_SUB_KEY = 1089 +CANT_REMOVE_ALL_FIELDS = 1090 +CANT_DROP_FIELD_OR_KEY = 1091 +INSERT_INFO = 1092 +INSERT_TABLE_USED = 1093 +NO_SUCH_THREAD = 1094 +KILL_DENIED_ERROR = 1095 +NO_TABLES_USED = 1096 +TOO_BIG_SET = 1097 +NO_UNIQUE_LOGFILE = 1098 +TABLE_NOT_LOCKED_FOR_WRITE = 1099 +TABLE_NOT_LOCKED = 1100 +BLOB_CANT_HAVE_DEFAULT = 1101 +WRONG_DB_NAME = 1102 +WRONG_TABLE_NAME = 1103 +TOO_BIG_SELECT = 1104 +UNKNOWN_ERROR = 1105 +UNKNOWN_PROCEDURE = 1106 +WRONG_PARAMCOUNT_TO_PROCEDURE = 1107 +WRONG_PARAMETERS_TO_PROCEDURE = 1108 +UNKNOWN_TABLE = 1109 +FIELD_SPECIFIED_TWICE = 1110 +INVALID_GROUP_FUNC_USE = 1111 +UNSUPPORTED_EXTENSION = 1112 +TABLE_MUST_HAVE_COLUMNS = 1113 +RECORD_FILE_FULL = 1114 +UNKNOWN_CHARACTER_SET = 1115 +TOO_MANY_TABLES = 1116 +TOO_MANY_FIELDS = 1117 +TOO_BIG_ROWSIZE = 1118 +STACK_OVERRUN = 1119 +WRONG_OUTER_JOIN = 1120 +NULL_COLUMN_IN_INDEX = 1121 +CANT_FIND_UDF = 1122 +CANT_INITIALIZE_UDF = 1123 +UDF_NO_PATHS = 1124 +UDF_EXISTS = 1125 +CANT_OPEN_LIBRARY = 1126 +CANT_FIND_DL_ENTRY = 1127 +FUNCTION_NOT_DEFINED = 1128 +HOST_IS_BLOCKED = 1129 +HOST_NOT_PRIVILEGED = 1130 +PASSWORD_ANONYMOUS_USER = 1131 +PASSWORD_NOT_ALLOWED = 1132 +PASSWORD_NO_MATCH = 1133 +UPDATE_INFO = 1134 +CANT_CREATE_THREAD = 1135 +WRONG_VALUE_COUNT_ON_ROW = 1136 +CANT_REOPEN_TABLE = 1137 +INVALID_USE_OF_NULL = 1138 +REGEXP_ERROR = 1139 +MIX_OF_GROUP_FUNC_AND_FIELDS = 1140 +NONEXISTING_GRANT = 1141 +TABLEACCESS_DENIED_ERROR = 1142 +COLUMNACCESS_DENIED_ERROR = 1143 +ILLEGAL_GRANT_FOR_TABLE = 1144 +GRANT_WRONG_HOST_OR_USER = 1145 +NO_SUCH_TABLE = 1146 +NONEXISTING_TABLE_GRANT = 1147 +NOT_ALLOWED_COMMAND = 1148 +SYNTAX_ERROR = 1149 +DELAYED_CANT_CHANGE_LOCK = 1150 +TOO_MANY_DELAYED_THREADS = 1151 +ABORTING_CONNECTION = 1152 +NET_PACKET_TOO_LARGE = 1153 +NET_READ_ERROR_FROM_PIPE = 1154 +NET_FCNTL_ERROR = 1155 +NET_PACKETS_OUT_OF_ORDER = 1156 +NET_UNCOMPRESS_ERROR = 1157 +NET_READ_ERROR = 1158 +NET_READ_INTERRUPTED = 1159 +NET_ERROR_ON_WRITE = 1160 +NET_WRITE_INTERRUPTED = 1161 +TOO_LONG_STRING = 1162 +TABLE_CANT_HANDLE_BLOB = 1163 +TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164 +DELAYED_INSERT_TABLE_LOCKED = 1165 +WRONG_COLUMN_NAME = 1166 +WRONG_KEY_COLUMN = 1167 +WRONG_MRG_TABLE = 1168 +DUP_UNIQUE = 1169 +BLOB_KEY_WITHOUT_LENGTH = 1170 +PRIMARY_CANT_HAVE_NULL = 1171 +TOO_MANY_ROWS = 1172 +REQUIRES_PRIMARY_KEY = 1173 +NO_RAID_COMPILED = 1174 +UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175 +KEY_DOES_NOT_EXITS = 1176 +CHECK_NO_SUCH_TABLE = 1177 +CHECK_NOT_IMPLEMENTED = 1178 +CANT_DO_THIS_DURING_AN_TRANSACTION = 1179 +ERROR_DURING_COMMIT = 1180 +ERROR_DURING_ROLLBACK = 1181 +ERROR_DURING_FLUSH_LOGS = 1182 +ERROR_DURING_CHECKPOINT = 1183 +NEW_ABORTING_CONNECTION = 1184 +DUMP_NOT_IMPLEMENTED = 1185 +FLUSH_MASTER_BINLOG_CLOSED = 1186 +INDEX_REBUILD = 1187 +MASTER = 1188 +MASTER_NET_READ = 1189 +MASTER_NET_WRITE = 1190 +FT_MATCHING_KEY_NOT_FOUND = 1191 +LOCK_OR_ACTIVE_TRANSACTION = 1192 +UNKNOWN_SYSTEM_VARIABLE = 1193 +CRASHED_ON_USAGE = 1194 +CRASHED_ON_REPAIR = 1195 +WARNING_NOT_COMPLETE_ROLLBACK = 1196 +TRANS_CACHE_FULL = 1197 +SLAVE_MUST_STOP = 1198 +SLAVE_NOT_RUNNING = 1199 +BAD_SLAVE = 1200 +MASTER_INFO = 1201 +SLAVE_THREAD = 1202 +TOO_MANY_USER_CONNECTIONS = 1203 +SET_CONSTANTS_ONLY = 1204 +LOCK_WAIT_TIMEOUT = 1205 +LOCK_TABLE_FULL = 1206 +READ_ONLY_TRANSACTION = 1207 +DROP_DB_WITH_READ_LOCK = 1208 +CREATE_DB_WITH_READ_LOCK = 1209 +WRONG_ARGUMENTS = 1210 +NO_PERMISSION_TO_CREATE_USER = 1211 +UNION_TABLES_IN_DIFFERENT_DIR = 1212 +LOCK_DEADLOCK = 1213 +TABLE_CANT_HANDLE_FT = 1214 +CANNOT_ADD_FOREIGN = 1215 +NO_REFERENCED_ROW = 1216 +ROW_IS_REFERENCED = 1217 +CONNECT_TO_MASTER = 1218 +QUERY_ON_MASTER = 1219 +ERROR_WHEN_EXECUTING_COMMAND = 1220 +WRONG_USAGE = 1221 +WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222 +CANT_UPDATE_WITH_READLOCK = 1223 +MIXING_NOT_ALLOWED = 1224 +DUP_ARGUMENT = 1225 +USER_LIMIT_REACHED = 1226 +SPECIFIC_ACCESS_DENIED_ERROR = 1227 +LOCAL_VARIABLE = 1228 +GLOBAL_VARIABLE = 1229 +NO_DEFAULT = 1230 +WRONG_VALUE_FOR_VAR = 1231 +WRONG_TYPE_FOR_VAR = 1232 +VAR_CANT_BE_READ = 1233 +CANT_USE_OPTION_HERE = 1234 +NOT_SUPPORTED_YET = 1235 +MASTER_FATAL_ERROR_READING_BINLOG = 1236 +SLAVE_IGNORED_TABLE = 1237 +INCORRECT_GLOBAL_LOCAL_VAR = 1238 +WRONG_FK_DEF = 1239 +KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240 +OPERAND_COLUMNS = 1241 +SUBQUERY_NO_1_ROW = 1242 +UNKNOWN_STMT_HANDLER = 1243 +CORRUPT_HELP_DB = 1244 +CYCLIC_REFERENCE = 1245 +AUTO_CONVERT = 1246 +ILLEGAL_REFERENCE = 1247 +DERIVED_MUST_HAVE_ALIAS = 1248 +SELECT_REDUCED = 1249 +TABLENAME_NOT_ALLOWED_HERE = 1250 +NOT_SUPPORTED_AUTH_MODE = 1251 +SPATIAL_CANT_HAVE_NULL = 1252 +COLLATION_CHARSET_MISMATCH = 1253 +SLAVE_WAS_RUNNING = 1254 +SLAVE_WAS_NOT_RUNNING = 1255 +TOO_BIG_FOR_UNCOMPRESS = 1256 +ZLIB_Z_MEM_ERROR = 1257 +ZLIB_Z_BUF_ERROR = 1258 +ZLIB_Z_DATA_ERROR = 1259 +CUT_VALUE_GROUP_CONCAT = 1260 +WARN_TOO_FEW_RECORDS = 1261 +WARN_TOO_MANY_RECORDS = 1262 +WARN_NULL_TO_NOTNULL = 1263 +WARN_DATA_OUT_OF_RANGE = 1264 +WARN_DATA_TRUNCATED = 1265 +WARN_USING_OTHER_HANDLER = 1266 +CANT_AGGREGATE_2COLLATIONS = 1267 +DROP_USER = 1268 +REVOKE_GRANTS = 1269 +CANT_AGGREGATE_3COLLATIONS = 1270 +CANT_AGGREGATE_NCOLLATIONS = 1271 +VARIABLE_IS_NOT_STRUCT = 1272 +UNKNOWN_COLLATION = 1273 +SLAVE_IGNORED_SSL_PARAMS = 1274 +SERVER_IS_IN_SECURE_AUTH_MODE = 1275 +WARN_FIELD_RESOLVED = 1276 +BAD_SLAVE_UNTIL_COND = 1277 +MISSING_SKIP_SLAVE = 1278 +UNTIL_COND_IGNORED = 1279 +WRONG_NAME_FOR_INDEX = 1280 +WRONG_NAME_FOR_CATALOG = 1281 +WARN_QC_RESIZE = 1282 +BAD_FT_COLUMN = 1283 +UNKNOWN_KEY_CACHE = 1284 +WARN_HOSTNAME_WONT_WORK = 1285 +UNKNOWN_STORAGE_ENGINE = 1286 +WARN_DEPRECATED_SYNTAX = 1287 +NON_UPDATABLE_TABLE = 1288 +FEATURE_DISABLED = 1289 +OPTION_PREVENTS_STATEMENT = 1290 +DUPLICATED_VALUE_IN_TYPE = 1291 +TRUNCATED_WRONG_VALUE = 1292 +TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293 +INVALID_ON_UPDATE = 1294 +UNSUPPORTED_PS = 1295 +GET_ERRMSG = 1296 +GET_TEMPORARY_ERRMSG = 1297 +UNKNOWN_TIME_ZONE = 1298 +WARN_INVALID_TIMESTAMP = 1299 +INVALID_CHARACTER_STRING = 1300 +WARN_ALLOWED_PACKET_OVERFLOWED = 1301 +CONFLICTING_DECLARATIONS = 1302 +SP_NO_RECURSIVE_CREATE = 1303 +SP_ALREADY_EXISTS = 1304 +SP_DOES_NOT_EXIST = 1305 +SP_DROP_FAILED = 1306 +SP_STORE_FAILED = 1307 +SP_LILABEL_MISMATCH = 1308 +SP_LABEL_REDEFINE = 1309 +SP_LABEL_MISMATCH = 1310 +SP_UNINIT_VAR = 1311 +SP_BADSELECT = 1312 +SP_BADRETURN = 1313 +SP_BADSTATEMENT = 1314 +UPDATE_LOG_DEPRECATED_IGNORED = 1315 +UPDATE_LOG_DEPRECATED_TRANSLATED = 1316 +QUERY_INTERRUPTED = 1317 +SP_WRONG_NO_OF_ARGS = 1318 +SP_COND_MISMATCH = 1319 +SP_NORETURN = 1320 +SP_NORETURNEND = 1321 +SP_BAD_CURSOR_QUERY = 1322 +SP_BAD_CURSOR_SELECT = 1323 +SP_CURSOR_MISMATCH = 1324 +SP_CURSOR_ALREADY_OPEN = 1325 +SP_CURSOR_NOT_OPEN = 1326 +SP_UNDECLARED_VAR = 1327 +SP_WRONG_NO_OF_FETCH_ARGS = 1328 +SP_FETCH_NO_DATA = 1329 +SP_DUP_PARAM = 1330 +SP_DUP_VAR = 1331 +SP_DUP_COND = 1332 +SP_DUP_CURS = 1333 +SP_CANT_ALTER = 1334 +SP_SUBSELECT_NYI = 1335 +STMT_NOT_ALLOWED_IN_SF_OR_TRG = 1336 +SP_VARCOND_AFTER_CURSHNDLR = 1337 +SP_CURSOR_AFTER_HANDLER = 1338 +SP_CASE_NOT_FOUND = 1339 +FPARSER_TOO_BIG_FILE = 1340 +FPARSER_BAD_HEADER = 1341 +FPARSER_EOF_IN_COMMENT = 1342 +FPARSER_ERROR_IN_PARAMETER = 1343 +FPARSER_EOF_IN_UNKNOWN_PARAMETER = 1344 +VIEW_NO_EXPLAIN = 1345 +FRM_UNKNOWN_TYPE = 1346 +WRONG_OBJECT = 1347 +NONUPDATEABLE_COLUMN = 1348 +VIEW_SELECT_DERIVED = 1349 +VIEW_SELECT_CLAUSE = 1350 +VIEW_SELECT_VARIABLE = 1351 +VIEW_SELECT_TMPTABLE = 1352 +VIEW_WRONG_LIST = 1353 +WARN_VIEW_MERGE = 1354 +WARN_VIEW_WITHOUT_KEY = 1355 +VIEW_INVALID = 1356 +SP_NO_DROP_SP = 1357 +SP_GOTO_IN_HNDLR = 1358 +TRG_ALREADY_EXISTS = 1359 +TRG_DOES_NOT_EXIST = 1360 +TRG_ON_VIEW_OR_TEMP_TABLE = 1361 +TRG_CANT_CHANGE_ROW = 1362 +TRG_NO_SUCH_ROW_IN_TRG = 1363 +NO_DEFAULT_FOR_FIELD = 1364 +DIVISION_BY_ZERO = 1365 +TRUNCATED_WRONG_VALUE_FOR_FIELD = 1366 +ILLEGAL_VALUE_FOR_TYPE = 1367 +VIEW_NONUPD_CHECK = 1368 +VIEW_CHECK_FAILED = 1369 +PROCACCESS_DENIED_ERROR = 1370 +RELAY_LOG_FAIL = 1371 +PASSWD_LENGTH = 1372 +UNKNOWN_TARGET_BINLOG = 1373 +IO_ERR_LOG_INDEX_READ = 1374 +BINLOG_PURGE_PROHIBITED = 1375 +FSEEK_FAIL = 1376 +BINLOG_PURGE_FATAL_ERR = 1377 +LOG_IN_USE = 1378 +LOG_PURGE_UNKNOWN_ERR = 1379 +RELAY_LOG_INIT = 1380 +NO_BINARY_LOGGING = 1381 +RESERVED_SYNTAX = 1382 +WSAS_FAILED = 1383 +DIFF_GROUPS_PROC = 1384 +NO_GROUP_FOR_PROC = 1385 +ORDER_WITH_PROC = 1386 +LOGGING_PROHIBIT_CHANGING_OF = 1387 +NO_FILE_MAPPING = 1388 +WRONG_MAGIC = 1389 +PS_MANY_PARAM = 1390 +KEY_PART_0 = 1391 +VIEW_CHECKSUM = 1392 +VIEW_MULTIUPDATE = 1393 +VIEW_NO_INSERT_FIELD_LIST = 1394 +VIEW_DELETE_MERGE_VIEW = 1395 +CANNOT_USER = 1396 +XAER_NOTA = 1397 +XAER_INVAL = 1398 +XAER_RMFAIL = 1399 +XAER_OUTSIDE = 1400 +XAER_RMERR = 1401 +XA_RBROLLBACK = 1402 +NONEXISTING_PROC_GRANT = 1403 +PROC_AUTO_GRANT_FAIL = 1404 +PROC_AUTO_REVOKE_FAIL = 1405 +DATA_TOO_LONG = 1406 +SP_BAD_SQLSTATE = 1407 +STARTUP = 1408 +LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR = 1409 +CANT_CREATE_USER_WITH_GRANT = 1410 +WRONG_VALUE_FOR_TYPE = 1411 +TABLE_DEF_CHANGED = 1412 +SP_DUP_HANDLER = 1413 +SP_NOT_VAR_ARG = 1414 +SP_NO_RETSET = 1415 +CANT_CREATE_GEOMETRY_OBJECT = 1416 +FAILED_ROUTINE_BREAK_BINLOG = 1417 +BINLOG_UNSAFE_ROUTINE = 1418 +BINLOG_CREATE_ROUTINE_NEED_SUPER = 1419 +EXEC_STMT_WITH_OPEN_CURSOR = 1420 +STMT_HAS_NO_OPEN_CURSOR = 1421 +COMMIT_NOT_ALLOWED_IN_SF_OR_TRG = 1422 +NO_DEFAULT_FOR_VIEW_FIELD = 1423 +SP_NO_RECURSION = 1424 +TOO_BIG_SCALE = 1425 +TOO_BIG_PRECISION = 1426 +M_BIGGER_THAN_D = 1427 +WRONG_LOCK_OF_SYSTEM_TABLE = 1428 +CONNECT_TO_FOREIGN_DATA_SOURCE = 1429 +QUERY_ON_FOREIGN_DATA_SOURCE = 1430 +FOREIGN_DATA_SOURCE_DOESNT_EXIST = 1431 +FOREIGN_DATA_STRING_INVALID_CANT_CREATE = 1432 +FOREIGN_DATA_STRING_INVALID = 1433 +CANT_CREATE_FEDERATED_TABLE = 1434 +TRG_IN_WRONG_SCHEMA = 1435 +STACK_OVERRUN_NEED_MORE = 1436 +TOO_LONG_BODY = 1437 +WARN_CANT_DROP_DEFAULT_KEYCACHE = 1438 +TOO_BIG_DISPLAYWIDTH = 1439 +XAER_DUPID = 1440 +DATETIME_FUNCTION_OVERFLOW = 1441 +CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG = 1442 +VIEW_PREVENT_UPDATE = 1443 +PS_NO_RECURSION = 1444 +SP_CANT_SET_AUTOCOMMIT = 1445 +MALFORMED_DEFINER = 1446 +VIEW_FRM_NO_USER = 1447 +VIEW_OTHER_USER = 1448 +NO_SUCH_USER = 1449 +FORBID_SCHEMA_CHANGE = 1450 +ROW_IS_REFERENCED_2 = 1451 +NO_REFERENCED_ROW_2 = 1452 +SP_BAD_VAR_SHADOW = 1453 +TRG_NO_DEFINER = 1454 +OLD_FILE_FORMAT = 1455 +SP_RECURSION_LIMIT = 1456 +SP_PROC_TABLE_CORRUPT = 1457 +ERROR_LAST = 1457 + diff --git a/MySQLdb/constants/FIELD_TYPE.py b/MySQLdb/constants/FIELD_TYPE.py new file mode 100644 index 0000000..8a57b17 --- /dev/null +++ b/MySQLdb/constants/FIELD_TYPE.py @@ -0,0 +1,37 @@ +"""MySQL FIELD_TYPE Constants + +These constants represent the various column (field) types that are +supported by MySQL. + +""" + +DECIMAL = 0 +TINY = 1 +SHORT = 2 +LONG = 3 +FLOAT = 4 +DOUBLE = 5 +NULL = 6 +TIMESTAMP = 7 +LONGLONG = 8 +INT24 = 9 +DATE = 10 +TIME = 11 +DATETIME = 12 +YEAR = 13 +NEWDATE = 14 +VARCHAR = 15 +BIT = 16 +NEWDECIMAL = 246 +ENUM = 247 +SET = 248 +TINY_BLOB = 249 +MEDIUM_BLOB = 250 +LONG_BLOB = 251 +BLOB = 252 +VAR_STRING = 253 +STRING = 254 +GEOMETRY = 255 + +CHAR = TINY +INTERVAL = ENUM diff --git a/MySQLdb/constants/FLAG.py b/MySQLdb/constants/FLAG.py new file mode 100644 index 0000000..00e6c7c --- /dev/null +++ b/MySQLdb/constants/FLAG.py @@ -0,0 +1,23 @@ +"""MySQL FLAG Constants + +These flags are used along with the FIELD_TYPE to indicate various +properties of columns in a result set. + +""" + +NOT_NULL = 1 +PRI_KEY = 2 +UNIQUE_KEY = 4 +MULTIPLE_KEY = 8 +BLOB = 16 +UNSIGNED = 32 +ZEROFILL = 64 +BINARY = 128 +ENUM = 256 +AUTO_INCREMENT = 512 +TIMESTAMP = 1024 +SET = 2048 +NUM = 32768 +PART_KEY = 16384 +GROUP = 32768 +UNIQUE = 65536 diff --git a/MySQLdb/constants/REFRESH.py b/MySQLdb/constants/REFRESH.py new file mode 100644 index 0000000..4a08b94 --- /dev/null +++ b/MySQLdb/constants/REFRESH.py @@ -0,0 +1,17 @@ +"""MySQL REFRESH Constants + +These constants seem to mostly deal with things internal to the +MySQL server. Forget you saw this. + +""" + +GRANT = 1 +LOG = 2 +TABLES = 4 +HOSTS = 8 +STATUS = 16 +THREADS = 32 +SLAVE = 64 +MASTER = 128 +READ_LOCK = 16384 +FAST = 32768 diff --git a/MySQLdb/constants/__init__.py b/MySQLdb/constants/__init__.py new file mode 100644 index 0000000..3da4a0e --- /dev/null +++ b/MySQLdb/constants/__init__.py @@ -0,0 +1 @@ +__all__ = ['CR', 'FIELD_TYPE','CLIENT','REFRESH','ER','FLAG'] diff --git a/MySQLdb/converters.py b/MySQLdb/converters.py new file mode 100644 index 0000000..14b1f52 --- /dev/null +++ b/MySQLdb/converters.py @@ -0,0 +1,181 @@ +"""MySQLdb type conversion module + +This module handles all the type conversions for MySQL. If the default +type conversions aren't what you need, you can make your own. The +dictionary conversions maps some kind of type to a conversion function +which returns the corresponding value: + +Key: FIELD_TYPE.* (from MySQLdb.constants) + +Conversion function: + + Arguments: string + + Returns: Python object + +Key: Python type object (from types) or class + +Conversion function: + + Arguments: Python object of indicated type or class AND + conversion dictionary + + Returns: SQL literal value + + Notes: Most conversion functions can ignore the dictionary, but + it is a required parameter. It is necessary for converting + things like sequences and instances. + +Don't modify conversions if you can avoid it. Instead, make copies +(with the copy() method), modify the copies, and then pass them to +MySQL.connect(). + +""" + +from _mysql import string_literal, escape_sequence, escape_dict, escape, NULL +from MySQLdb.constants import FIELD_TYPE, FLAG +from MySQLdb.times import * + +try: + from types import IntType, LongType, FloatType, NoneType, TupleType, ListType, DictType, InstanceType, \ + StringType, UnicodeType, ObjectType, BooleanType, ClassType, TypeType +except ImportError: + # Python 3 + long = int + IntType, LongType, FloatType, NoneType = int, long, float, type(None) + TupleType, ListType, DictType, InstanceType = tuple, list, dict, None + StringType, UnicodeType, ObjectType, BooleanType = bytes, str, object, bool + +import array + +try: + set +except NameError: + from sets import Set as set + +def Bool2Str(s, d): return str(int(s)) + +def Str2Set(s): + return set([ i for i in s.split(',') if i ]) + +def Set2Str(s, d): + return string_literal(','.join(s), d) + +def Thing2Str(s, d): + """Convert something into a string via str().""" + return str(s) + +def Unicode2Str(s, d): + """Convert a unicode object to a string using the default encoding. + This is only used as a placeholder for the real function, which + is connection-dependent.""" + return s.encode() + +Long2Int = Thing2Str + +def Float2Str(o, d): + return '%.15g' % o + +def None2NULL(o, d): + """Convert None to NULL.""" + return NULL # duh + +def Thing2Literal(o, d): + + """Convert something into a SQL string literal. If using + MySQL-3.23 or newer, string_literal() is a method of the + _mysql.MYSQL object, and this function will be overridden with + that method when the connection is created.""" + + return string_literal(o, d) + + +def Instance2Str(o, d): + + """ + + Convert an Instance to a string representation. If the __str__() + method produces acceptable output, then you don't need to add the + class to conversions; it will be handled by the default + converter. If the exact class is not found in d, it will use the + first class it can find for which o is an instance. + + """ + + if o.__class__ in d: + return d[o.__class__](o, d) + cl = filter(lambda x,o=o: + type(x) is ClassType + and isinstance(o, x), d.keys()) + if not cl and hasattr(types, 'ObjectType'): + cl = filter(lambda x,o=o: + type(x) is TypeType + and isinstance(o, x) + and d[x] is not Instance2Str, + d.keys()) + if not cl: + return d[types.StringType](o,d) + d[o.__class__] = d[cl[0]] + return d[cl[0]](o, d) + +def char_array(s): + return array.array('c', s) + +def array2Str(o, d): + return Thing2Literal(o.tostring(), d) + +conversions = { + IntType: Thing2Str, + LongType: Long2Int, + FloatType: Float2Str, + NoneType: None2NULL, + TupleType: escape_sequence, + ListType: escape_sequence, + DictType: escape_dict, + InstanceType: Instance2Str, + array.ArrayType: array2Str, + StringType: Thing2Literal, # default + UnicodeType: Unicode2Str, + ObjectType: Instance2Str, + BooleanType: Bool2Str, + DateTimeType: DateTime2literal, + DateTimeDeltaType: DateTimeDelta2literal, + set: Set2Str, + FIELD_TYPE.TINY: int, + FIELD_TYPE.SHORT: int, + FIELD_TYPE.LONG: long, + FIELD_TYPE.FLOAT: float, + FIELD_TYPE.DOUBLE: float, + FIELD_TYPE.DECIMAL: float, + FIELD_TYPE.NEWDECIMAL: float, + FIELD_TYPE.LONGLONG: long, + FIELD_TYPE.INT24: int, + FIELD_TYPE.YEAR: int, + FIELD_TYPE.SET: Str2Set, + FIELD_TYPE.TIMESTAMP: mysql_timestamp_converter, + FIELD_TYPE.DATETIME: DateTime_or_None, + FIELD_TYPE.TIME: TimeDelta_or_None, + FIELD_TYPE.DATE: Date_or_None, + FIELD_TYPE.BLOB: [ + (FLAG.BINARY, str), + ], + FIELD_TYPE.STRING: [ + (FLAG.BINARY, str), + ], + FIELD_TYPE.VAR_STRING: [ + (FLAG.BINARY, str), + ], + FIELD_TYPE.VARCHAR: [ + (FLAG.BINARY, str), + ], + } + +try: + from decimal import Decimal + conversions[FIELD_TYPE.DECIMAL] = Decimal + conversions[FIELD_TYPE.NEWDECIMAL] = Decimal +except ImportError: + pass + + + diff --git a/MySQLdb/cursors.py b/MySQLdb/cursors.py new file mode 100644 index 0000000..a8cfa3e --- /dev/null +++ b/MySQLdb/cursors.py @@ -0,0 +1,533 @@ +"""MySQLdb Cursors + +This module implements Cursors of various types for MySQLdb. By +default, MySQLdb uses the Cursor class. + +""" + +import re +import sys +try: + from types import ListType, TupleType, UnicodeType +except ImportError: + # Python 3 + ListType = list + TupleType = tuple + UnicodeType = str + +restr = r""" + \s + values + \s* + ( + \( + [^()']* + (?: + (?: + (?:\( + # ( - editor hightlighting helper + [^)]* + \)) + | + ' + [^\\']* + (?:\\.[^\\']*)* + ' + ) + [^()']* + )* + \) + ) +""" + +insert_values = re.compile(restr, re.S | re.I | re.X) + +from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ + DatabaseError, OperationalError, IntegrityError, InternalError, \ + NotSupportedError, ProgrammingError + + +class BaseCursor(object): + + """A base for Cursor classes. Useful attributes: + + description + A tuple of DB API 7-tuples describing the columns in + the last executed query; see PEP-249 for details. + + description_flags + Tuple of column flags for last query, one entry per column + in the result set. Values correspond to those in + MySQLdb.constants.FLAG. See MySQL documentation (C API) + for more information. Non-standard extension. + + arraysize + default number of rows fetchmany() will fetch + + """ + + from _mysql_exceptions import MySQLError, Warning, Error, InterfaceError, \ + DatabaseError, DataError, OperationalError, IntegrityError, \ + InternalError, ProgrammingError, NotSupportedError + + _defer_warnings = False + + def __init__(self, connection): + from weakref import proxy + + self.connection = proxy(connection) + self.description = None + self.description_flags = None + self.rowcount = -1 + self.arraysize = 1 + self._executed = None + self.lastrowid = None + self.messages = [] + self.errorhandler = connection.errorhandler + self._result = None + self._warnings = 0 + self._info = None + self.rownumber = None + + def __del__(self): + self.close() + self.errorhandler = None + self._result = None + + def close(self): + """Close the cursor. No further queries will be possible.""" + if not self.connection: return + while self.nextset(): pass + self.connection = None + + def _check_executed(self): + if not self._executed: + self.errorhandler(self, ProgrammingError, "execute() first") + + def _warning_check(self): + from warnings import warn + if self._warnings: + warnings = self._get_db().show_warnings() + if warnings: + # This is done in two loops in case + # Warnings are set to raise exceptions. + for w in warnings: + self.messages.append((self.Warning, w)) + for w in warnings: + warn(w[-1], self.Warning, 3) + elif self._info: + self.messages.append((self.Warning, self._info)) + warn(self._info, self.Warning, 3) + + def nextset(self): + """Advance to the next result set. + + Returns None if there are no more result sets. + """ + if self._executed: + self.fetchall() + del self.messages[:] + + db = self._get_db() + nr = db.next_result() + if nr == -1: + return None + self._do_get_result() + self._post_get_result() + self._warning_check() + return 1 + + def _post_get_result(self): pass + + def _do_get_result(self): + db = self._get_db() + self._result = self._get_result() + self.rowcount = db.affected_rows() + self.rownumber = 0 + self.description = self._result and self._result.describe() or None + self.description_flags = self._result and self._result.field_flags() or None + self.lastrowid = db.insert_id() + self._warnings = db.warning_count() + self._info = db.info() + + def setinputsizes(self, *args): + """Does nothing, required by DB API.""" + + def setoutputsizes(self, *args): + """Does nothing, required by DB API.""" + + def _get_db(self): + if not self.connection: + self.errorhandler(self, ProgrammingError, "cursor closed") + return self.connection + + def execute(self, query, args=None): + + """Execute a query. + + query -- string, query to execute on server + args -- optional sequence or mapping, parameters to use with query. + + Note: If args is a sequence, then %s must be used as the + parameter placeholder in the query. If a mapping is used, + %(key)s must be used as the placeholder. + + Returns long integer rows affected, if any + + """ + del self.messages[:] + db = self._get_db() + charset = db.character_set_name() + if isinstance(query, unicode): + query = query.encode(charset) + if args is not None: + query = query % db.literal(args) + try: + r = None + r = self._query(query) + except TypeError, m: + if m.args[0] in ("not enough arguments for format string", + "not all arguments converted"): + self.messages.append((ProgrammingError, m.args[0])) + self.errorhandler(self, ProgrammingError, m.args[0]) + else: + self.messages.append((TypeError, m)) + self.errorhandler(self, TypeError, m) + except (SystemExit, KeyboardInterrupt): + raise + except: + exc, value, tb = sys.exc_info() + del tb + self.messages.append((exc, value)) + self.errorhandler(self, exc, value) + self._executed = query + if not self._defer_warnings: self._warning_check() + return r + + def executemany(self, query, args): + + """Execute a multi-row query. + + query -- string, query to execute on server + + args + + Sequence of sequences or mappings, parameters to use with + query. + + Returns long integer rows affected, if any. + + This method improves performance on multiple-row INSERT and + REPLACE. Otherwise it is equivalent to looping over args with + execute(). + + """ + del self.messages[:] + db = self._get_db() + if not args: return + charset = db.character_set_name() + if isinstance(query, unicode): query = query.encode(charset) + m = insert_values.search(query) + if not m: + r = 0 + for a in args: + r = r + self.execute(query, a) + return r + p = m.start(1) + e = m.end(1) + qv = m.group(1) + try: + q = [ qv % db.literal(a) for a in args ] + except TypeError, msg: + if msg.args[0] in ("not enough arguments for format string", + "not all arguments converted"): + self.errorhandler(self, ProgrammingError, msg.args[0]) + else: + self.errorhandler(self, TypeError, msg) + except (SystemExit, KeyboardInterrupt): + raise + except: + exc, value, tb = sys.exc_info() + del tb + self.errorhandler(self, exc, value) + r = self._query('\n'.join([query[:p], ',\n'.join(q), query[e:]])) + if not self._defer_warnings: self._warning_check() + return r + + def callproc(self, procname, args=()): + + """Execute stored procedure procname with args + + procname -- string, name of procedure to execute on server + + args -- Sequence of parameters to use with procedure + + Returns the original args. + + 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 .execute() to get any OUT or INOUT values. + + 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 nextset() + to advance through all result sets; otherwise you may get + disconnected. + """ + + db = self._get_db() + charset = db.character_set_name() + for index, arg in enumerate(args): + q = "SET @_%s_%d=%s" % (procname, index, + db.literal(arg)) + if isinstance(q, unicode): + q = q.encode(charset) + self._query(q) + self.nextset() + + q = "CALL %s(%s)" % (procname, + ','.join(['@_%s_%d' % (procname, i) + for i in range(len(args))])) + if type(q) is UnicodeType: + q = q.encode(charset) + self._query(q) + self._executed = q + if not self._defer_warnings: self._warning_check() + return args + + def _do_query(self, q): + db = self._get_db() + self._last_executed = q + db.query(q) + self._do_get_result() + return self.rowcount + + def _query(self, q): return self._do_query(q) + + def _fetch_row(self, size=1): + if not self._result: + return () + return self._result.fetch_row(size, self._fetch_type) + + def __iter__(self): + return iter(self.fetchone, None) + + Warning = Warning + Error = Error + InterfaceError = InterfaceError + DatabaseError = DatabaseError + DataError = DataError + OperationalError = OperationalError + IntegrityError = IntegrityError + InternalError = InternalError + ProgrammingError = ProgrammingError + NotSupportedError = NotSupportedError + + +class CursorStoreResultMixIn(object): + + """This is a MixIn class which causes the entire result set to be + stored on the client side, i.e. it uses mysql_store_result(). If the + result set can be very large, consider adding a LIMIT clause to your + query, or using CursorUseResultMixIn instead.""" + + def _get_result(self): return self._get_db().store_result() + + def _query(self, q): + rowcount = self._do_query(q) + self._post_get_result() + return rowcount + + def _post_get_result(self): + self._rows = self._fetch_row(0) + self._result = None + + def fetchone(self): + """Fetches a single row from the cursor. None indicates that + no more rows are available.""" + self._check_executed() + if self.rownumber >= len(self._rows): return None + result = self._rows[self.rownumber] + self.rownumber = self.rownumber+1 + return result + + def fetchmany(self, size=None): + """Fetch up to size rows from the cursor. Result set may be smaller + than size. If size is not defined, cursor.arraysize is used.""" + self._check_executed() + end = self.rownumber + (size or self.arraysize) + result = self._rows[self.rownumber:end] + self.rownumber = min(end, len(self._rows)) + return result + + def fetchall(self): + """Fetchs all available rows from the cursor.""" + self._check_executed() + if self.rownumber: + result = self._rows[self.rownumber:] + else: + result = self._rows + self.rownumber = len(self._rows) + return result + + def scroll(self, value, mode='relative'): + """Scroll the cursor in the result set to a new position according + to mode. + + 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.""" + self._check_executed() + if mode == 'relative': + r = self.rownumber + value + elif mode == 'absolute': + r = value + else: + self.errorhandler(self, ProgrammingError, + "unknown scroll mode %s" % repr(mode)) + if r < 0 or r >= len(self._rows): + self.errorhandler(self, IndexError, "out of range") + self.rownumber = r + + def __iter__(self): + self._check_executed() + result = self.rownumber and self._rows[self.rownumber:] or self._rows + return iter(result) + + +class CursorUseResultMixIn(object): + + """This is a MixIn class which causes the result set to be stored + in the server and sent row-by-row to client side, i.e. it uses + mysql_use_result(). You MUST retrieve the entire result set and + close() the cursor before additional queries can be peformed on + the connection.""" + + _defer_warnings = True + + def _get_result(self): return self._get_db().use_result() + + def fetchone(self): + """Fetches a single row from the cursor.""" + self._check_executed() + r = self._fetch_row(1) + if not r: + self._warning_check() + return None + self.rownumber = self.rownumber + 1 + return r[0] + + def fetchmany(self, size=None): + """Fetch up to size rows from the cursor. Result set may be smaller + than size. If size is not defined, cursor.arraysize is used.""" + self._check_executed() + r = self._fetch_row(size or self.arraysize) + self.rownumber = self.rownumber + len(r) + if not r: + self._warning_check() + return r + + def fetchall(self): + """Fetchs all available rows from the cursor.""" + self._check_executed() + r = self._fetch_row(0) + self.rownumber = self.rownumber + len(r) + self._warning_check() + return r + + def __iter__(self): + return self + + def next(self): + row = self.fetchone() + if row is None: + raise StopIteration + return row + + +class CursorTupleRowsMixIn(object): + + """This is a MixIn class that causes all rows to be returned as tuples, + which is the standard form required by DB API.""" + + _fetch_type = 0 + + +class CursorDictRowsMixIn(object): + + """This is a MixIn class that causes all rows to be returned as + dictionaries. This is a non-standard feature.""" + + _fetch_type = 1 + + def fetchoneDict(self): + """Fetch a single row as a dictionary. Deprecated: + Use fetchone() instead. Will be removed in 1.3.""" + from warnings import warn + warn("fetchoneDict() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + return self.fetchone() + + def fetchmanyDict(self, size=None): + """Fetch several rows as a list of dictionaries. Deprecated: + Use fetchmany() instead. Will be removed in 1.3.""" + from warnings import warn + warn("fetchmanyDict() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + return self.fetchmany(size) + + def fetchallDict(self): + """Fetch all available rows as a list of dictionaries. Deprecated: + Use fetchall() instead. Will be removed in 1.3.""" + from warnings import warn + warn("fetchallDict() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + return self.fetchall() + + +class CursorOldDictRowsMixIn(CursorDictRowsMixIn): + + """This is a MixIn class that returns rows as dictionaries with + the same key convention as the old Mysqldb (MySQLmodule). Don't + use this.""" + + _fetch_type = 2 + + +class Cursor(CursorStoreResultMixIn, CursorTupleRowsMixIn, + BaseCursor): + + """This is the standard Cursor class that returns rows as tuples + and stores the result set in the client.""" + + +class DictCursor(CursorStoreResultMixIn, CursorDictRowsMixIn, + BaseCursor): + + """This is a Cursor class that returns rows as dictionaries and + stores the result set in the client.""" + + +class SSCursor(CursorUseResultMixIn, CursorTupleRowsMixIn, + BaseCursor): + + """This is a Cursor class that returns rows as tuples and stores + the result set in the server.""" + + +class SSDictCursor(CursorUseResultMixIn, CursorDictRowsMixIn, + BaseCursor): + + """This is a Cursor class that returns rows as dictionaries and + stores the result set in the server.""" + + diff --git a/MySQLdb/distribute_setup.py b/MySQLdb/distribute_setup.py deleted file mode 100644 index 8f5b063..0000000 --- a/MySQLdb/distribute_setup.py +++ /dev/null @@ -1,515 +0,0 @@ -#!python -"""Bootstrap distribute installation - -If you want to use setuptools in your package's setup.py, just include this -file in the same directory with it, and add this to the top of your setup.py:: - - from distribute_setup import use_setuptools - use_setuptools() - -If you want to require a specific version of setuptools, set a download -mirror, or use an alternate download directory, you can do so by supplying -the appropriate options to ``use_setuptools()``. - -This file can also be run as a script to install or upgrade setuptools. -""" -import os -import sys -import time -import fnmatch -import tempfile -import tarfile -from distutils import log - -try: - from site import USER_SITE -except ImportError: - USER_SITE = None - -try: - import subprocess - - def _python_cmd(*args): - args = (sys.executable,) + args - return subprocess.call(args) == 0 - -except ImportError: - # will be used for python 2.3 - def _python_cmd(*args): - args = (sys.executable,) + args - # quoting arguments if windows - if sys.platform == 'win32': - def quote(arg): - if ' ' in arg: - return '"%s"' % arg - return arg - args = [quote(arg) for arg in args] - return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 - -DEFAULT_VERSION = "0.6.28" -DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" -SETUPTOOLS_FAKED_VERSION = "0.6c11" - -SETUPTOOLS_PKG_INFO = """\ -Metadata-Version: 1.0 -Name: setuptools -Version: %s -Summary: xxxx -Home-page: xxx -Author: xxx -Author-email: xxx -License: xxx -Description: xxx -""" % SETUPTOOLS_FAKED_VERSION - - -def _install(tarball, install_args=()): - # extracting the tarball - tmpdir = tempfile.mkdtemp() - log.warn('Extracting in %s', tmpdir) - old_wd = os.getcwd() - try: - os.chdir(tmpdir) - tar = tarfile.open(tarball) - _extractall(tar) - tar.close() - - # going in the directory - subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) - os.chdir(subdir) - log.warn('Now working in %s', subdir) - - # installing - log.warn('Installing Distribute') - if not _python_cmd('setup.py', 'install', *install_args): - log.warn('Something went wrong during the installation.') - log.warn('See the error message above.') - finally: - os.chdir(old_wd) - - -def _build_egg(egg, tarball, to_dir): - # extracting the tarball - tmpdir = tempfile.mkdtemp() - log.warn('Extracting in %s', tmpdir) - old_wd = os.getcwd() - try: - os.chdir(tmpdir) - tar = tarfile.open(tarball) - _extractall(tar) - tar.close() - - # going in the directory - subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) - os.chdir(subdir) - log.warn('Now working in %s', subdir) - - # building an egg - log.warn('Building a Distribute egg in %s', to_dir) - _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) - - finally: - os.chdir(old_wd) - # returning the result - log.warn(egg) - if not os.path.exists(egg): - raise IOError('Could not build the egg.') - - -def _do_download(version, download_base, to_dir, download_delay): - egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg' - % (version, sys.version_info[0], sys.version_info[1])) - if not os.path.exists(egg): - tarball = download_setuptools(version, download_base, - to_dir, download_delay) - _build_egg(egg, tarball, to_dir) - sys.path.insert(0, egg) - import setuptools - setuptools.bootstrap_install_from = egg - - -def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, - to_dir=os.curdir, download_delay=15, no_fake=True): - # making sure we use the absolute path - to_dir = os.path.abspath(to_dir) - was_imported = 'pkg_resources' in sys.modules or \ - 'setuptools' in sys.modules - try: - try: - import pkg_resources - if not hasattr(pkg_resources, '_distribute'): - if not no_fake: - _fake_setuptools() - raise ImportError - except ImportError: - return _do_download(version, download_base, to_dir, download_delay) - try: - pkg_resources.require("distribute>=" + version) - return - except pkg_resources.VersionConflict: - e = sys.exc_info()[1] - if was_imported: - sys.stderr.write( - "The required version of distribute (>=%s) is not available,\n" - "and can't be installed while this script is running. Please\n" - "install a more recent version first, using\n" - "'easy_install -U distribute'." - "\n\n(Currently using %r)\n" % (version, e.args[0])) - sys.exit(2) - else: - del pkg_resources, sys.modules['pkg_resources'] # reload ok - return _do_download(version, download_base, to_dir, - download_delay) - except pkg_resources.DistributionNotFound: - return _do_download(version, download_base, to_dir, - download_delay) - finally: - if not no_fake: - _create_fake_setuptools_pkg_info(to_dir) - - -def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, - to_dir=os.curdir, delay=15): - """Download distribute from a specified location and return its filename - - `version` should be a valid distribute version number that is available - as an egg for download under the `download_base` URL (which should end - with a '/'). `to_dir` is the directory where the egg will be downloaded. - `delay` is the number of seconds to pause before an actual download - attempt. - """ - # making sure we use the absolute path - to_dir = os.path.abspath(to_dir) - try: - from urllib.request import urlopen - except ImportError: - from urllib2 import urlopen - tgz_name = "distribute-%s.tar.gz" % version - url = download_base + tgz_name - saveto = os.path.join(to_dir, tgz_name) - src = dst = None - if not os.path.exists(saveto): # Avoid repeated downloads - try: - log.warn("Downloading %s", url) - src = urlopen(url) - # Read/write all in one block, so we don't create a corrupt file - # if the download is interrupted. - data = src.read() - dst = open(saveto, "wb") - dst.write(data) - finally: - if src: - src.close() - if dst: - dst.close() - return os.path.realpath(saveto) - - -def _no_sandbox(function): - def __no_sandbox(*args, **kw): - try: - from setuptools.sandbox import DirectorySandbox - if not hasattr(DirectorySandbox, '_old'): - def violation(*args): - pass - DirectorySandbox._old = DirectorySandbox._violation - DirectorySandbox._violation = violation - patched = True - else: - patched = False - except ImportError: - patched = False - - try: - return function(*args, **kw) - finally: - if patched: - DirectorySandbox._violation = DirectorySandbox._old - del DirectorySandbox._old - - return __no_sandbox - - -def _patch_file(path, content): - """Will backup the file then patch it""" - existing_content = open(path).read() - if existing_content == content: - # already patched - log.warn('Already patched.') - return False - log.warn('Patching...') - _rename_path(path) - f = open(path, 'w') - try: - f.write(content) - finally: - f.close() - return True - -_patch_file = _no_sandbox(_patch_file) - - -def _same_content(path, content): - return open(path).read() == content - - -def _rename_path(path): - new_name = path + '.OLD.%s' % time.time() - log.warn('Renaming %s into %s', path, new_name) - os.rename(path, new_name) - return new_name - - -def _remove_flat_installation(placeholder): - if not os.path.isdir(placeholder): - log.warn('Unkown installation at %s', placeholder) - return False - found = False - for file in os.listdir(placeholder): - if fnmatch.fnmatch(file, 'setuptools*.egg-info'): - found = True - break - if not found: - log.warn('Could not locate setuptools*.egg-info') - return - - log.warn('Removing elements out of the way...') - pkg_info = os.path.join(placeholder, file) - if os.path.isdir(pkg_info): - patched = _patch_egg_dir(pkg_info) - else: - patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO) - - if not patched: - log.warn('%s already patched.', pkg_info) - return False - # now let's move the files out of the way - for element in ('setuptools', 'pkg_resources.py', 'site.py'): - element = os.path.join(placeholder, element) - if os.path.exists(element): - _rename_path(element) - else: - log.warn('Could not find the %s element of the ' - 'Setuptools distribution', element) - return True - -_remove_flat_installation = _no_sandbox(_remove_flat_installation) - - -def _after_install(dist): - log.warn('After install bootstrap.') - placeholder = dist.get_command_obj('install').install_purelib - _create_fake_setuptools_pkg_info(placeholder) - - -def _create_fake_setuptools_pkg_info(placeholder): - if not placeholder or not os.path.exists(placeholder): - log.warn('Could not find the install location') - return - pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1]) - setuptools_file = 'setuptools-%s-py%s.egg-info' % \ - (SETUPTOOLS_FAKED_VERSION, pyver) - pkg_info = os.path.join(placeholder, setuptools_file) - if os.path.exists(pkg_info): - log.warn('%s already exists', pkg_info) - return - - if not os.access(pkg_info, os.W_OK): - log.warn("Don't have permissions to write %s, skipping", pkg_info) - - log.warn('Creating %s', pkg_info) - f = open(pkg_info, 'w') - try: - f.write(SETUPTOOLS_PKG_INFO) - finally: - f.close() - - pth_file = os.path.join(placeholder, 'setuptools.pth') - log.warn('Creating %s', pth_file) - f = open(pth_file, 'w') - try: - f.write(os.path.join(os.curdir, setuptools_file)) - finally: - f.close() - -_create_fake_setuptools_pkg_info = _no_sandbox( - _create_fake_setuptools_pkg_info -) - - -def _patch_egg_dir(path): - # let's check if it's already patched - pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') - if os.path.exists(pkg_info): - if _same_content(pkg_info, SETUPTOOLS_PKG_INFO): - log.warn('%s already patched.', pkg_info) - return False - _rename_path(path) - os.mkdir(path) - os.mkdir(os.path.join(path, 'EGG-INFO')) - pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') - f = open(pkg_info, 'w') - try: - f.write(SETUPTOOLS_PKG_INFO) - finally: - f.close() - return True - -_patch_egg_dir = _no_sandbox(_patch_egg_dir) - - -def _before_install(): - log.warn('Before install bootstrap.') - _fake_setuptools() - - -def _under_prefix(location): - if 'install' not in sys.argv: - return True - args = sys.argv[sys.argv.index('install') + 1:] - for index, arg in enumerate(args): - for option in ('--root', '--prefix'): - if arg.startswith('%s=' % option): - top_dir = arg.split('root=')[-1] - return location.startswith(top_dir) - elif arg == option: - if len(args) > index: - top_dir = args[index + 1] - return location.startswith(top_dir) - if arg == '--user' and USER_SITE is not None: - return location.startswith(USER_SITE) - return True - - -def _fake_setuptools(): - log.warn('Scanning installed packages') - try: - import pkg_resources - except ImportError: - # we're cool - log.warn('Setuptools or Distribute does not seem to be installed.') - return - ws = pkg_resources.working_set - try: - setuptools_dist = ws.find( - pkg_resources.Requirement.parse('setuptools', replacement=False) - ) - except TypeError: - # old distribute API - setuptools_dist = ws.find( - pkg_resources.Requirement.parse('setuptools') - ) - - if setuptools_dist is None: - log.warn('No setuptools distribution found') - return - # detecting if it was already faked - setuptools_location = setuptools_dist.location - log.warn('Setuptools installation detected at %s', setuptools_location) - - # if --root or --preix was provided, and if - # setuptools is not located in them, we don't patch it - if not _under_prefix(setuptools_location): - log.warn('Not patching, --root or --prefix is installing Distribute' - ' in another location') - return - - # let's see if its an egg - if not setuptools_location.endswith('.egg'): - log.warn('Non-egg installation') - res = _remove_flat_installation(setuptools_location) - if not res: - return - else: - log.warn('Egg installation') - pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO') - if (os.path.exists(pkg_info) and - _same_content(pkg_info, SETUPTOOLS_PKG_INFO)): - log.warn('Already patched.') - return - log.warn('Patching...') - # let's create a fake egg replacing setuptools one - res = _patch_egg_dir(setuptools_location) - if not res: - return - log.warn('Patched done.') - _relaunch() - - -def _relaunch(): - log.warn('Relaunching...') - # we have to relaunch the process - # pip marker to avoid a relaunch bug - _cmd = ['-c', 'install', '--single-version-externally-managed'] - if sys.argv[:3] == _cmd: - sys.argv[0] = 'setup.py' - args = [sys.executable] + sys.argv - sys.exit(subprocess.call(args)) - - -def _extractall(self, path=".", members=None): - """Extract all members from the archive to the current working - directory and set owner, modification time and permissions on - directories afterwards. `path' specifies a different directory - to extract to. `members' is optional and must be a subset of the - list returned by getmembers(). - """ - import copy - import operator - from tarfile import ExtractError - directories = [] - - if members is None: - members = self - - for tarinfo in members: - if tarinfo.isdir(): - # Extract directories with a safe mode. - directories.append(tarinfo) - tarinfo = copy.copy(tarinfo) - tarinfo.mode = 448 # decimal for oct 0700 - self.extract(tarinfo, path) - - # Reverse sort directories. - if sys.version_info < (2, 4): - def sorter(dir1, dir2): - return cmp(dir1.name, dir2.name) - directories.sort(sorter) - directories.reverse() - else: - directories.sort(key=operator.attrgetter('name'), reverse=True) - - # Set correct owner, mtime and filemode on directories. - for tarinfo in directories: - dirpath = os.path.join(path, tarinfo.name) - try: - self.chown(tarinfo, dirpath) - self.utime(tarinfo, dirpath) - self.chmod(tarinfo, dirpath) - except ExtractError: - e = sys.exc_info()[1] - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - -def _build_install_args(argv): - install_args = [] - user_install = '--user' in argv - if user_install and sys.version_info < (2, 6): - log.warn("--user requires Python 2.6 or later") - raise SystemExit(1) - if user_install: - install_args.append('--user') - return install_args - - -def main(argv, version=DEFAULT_VERSION): - """Install or upgrade setuptools and EasyInstall""" - tarball = download_setuptools() - _install(tarball, _build_install_args(argv)) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/MySQLdb/doc/FAQ.txt b/MySQLdb/doc/FAQ.txt deleted file mode 100644 index b6a4ce9..0000000 --- a/MySQLdb/doc/FAQ.txt +++ /dev/null @@ -1,143 +0,0 @@ -==================================== - MySQLdb Frequently Asked Questions -==================================== - -.. contents:: -.. - - -Build Errors ------------- - - ld: fatal: library -lmysqlclient_r: not found - -mysqlclient_r is the thread-safe library. It's not available on -all platforms, or all installations, apparently. You'll need to -reconfigure site.cfg (in MySQLdb-1.2.1 and newer) to have -threadsafe = False. - - mysql.h: No such file or directory - -This almost always mean you don't have development packages -installed. On some systems, C headers for various things (like MySQL) -are distributed as a seperate package. You'll need to figure out -what that is and install it, but often the name ends with -devel. - -Another possibility: Some older versions of mysql_config behave oddly -and may throw quotes around some of the path names, which confused -MySQLdb-1.2.0. 1.2.1 works around these problems. If you see things -like -I'/usr/local/include/mysql' in your compile command, that's -probably the issue, but it shouldn't happen any more. - - -ImportError ------------ - - ImportError: No module named _mysql - -If you see this, it's likely you did some wrong when installing -MySQLdb; re-read (or read) README. _mysql is the low-level C module -that interfaces with the MySQL client library. - -Various versions of MySQLdb in the past have had build issues on -"weird" platforms; "weird" in this case means "not Linux", though -generally there aren't problems on Unix/POSIX platforms, including -BSDs and Mac OS X. Windows has been more problematic, in part because -there is no `mysql_config` available in the Windows installation of -MySQL. 1.2.1 solves most, if not all, of these problems, but you will -still have to edit a configuration file so that the setup knows where -to find MySQL and what libraries to include. - - - ImportError: libmysqlclient_r.so.14: cannot open shared object file: No such file or directory - -The number after .so may vary, but this means you have a version of -MySQLdb compiled against one version of MySQL, and are now trying to -run it against a different version. The shared library version tends -to change between major releases. - -Solution: Rebuilt MySQLdb, or get the matching version of MySQL. - -Another thing that can cause this: The MySQL libraries may not be on -your system path. - -Solutions: - -* set the LD_LIBRARY_PATH environment variable so that it includes - the path to the MySQL libraries. - -* set static=True in site.cfg for static linking - -* reconfigure your system so that the MySQL libraries are on the - default loader path. In Linux, you edit /etc/ld.so.conf and run - ldconfig. For Solaris, see `Linker and Libraries Guide - `_. - - - ImportError: ld.so.1: python: fatal: libmtmalloc.so.1: DF_1_NOOPEN tagged object may not be dlopen()'ed - -This is a weird one from Solaris. What does it mean? I have no idea. -However, things like this can happen if there is some sort of a compiler -or environment mismatch between Python and MySQL. For example, on some -commercial systems, you might have some code compiled with their own -compiler, and other things compiled with GCC. They don't always mesh -together. One way to encounter this is by getting binary packages from -different vendors. - -Solution: Rebuild Python or MySQL (or maybe both) from source. - - ImportError: dlopen(./_mysql.so, 2): Symbol not found: _sprintf$LDBLStub - Referenced from: ./_mysql.so - Expected in: dynamic lookup - -This is one from Mac OS X. It seems to have been a compiler mismatch, -but this time between two different versions of GCC. It seems nearly -every major release of GCC changes the ABI in some why, so linking -code compiled with GCC-3.3 and GCC-4.0, for example, can be -problematic. - - -My data disappeared! (or won't go away!) ----------------------------------------- - -Starting with 1.2.0, MySQLdb disables autocommit by default, as -required by the DB-API standard (`PEP-249`_). If you are using InnoDB -tables or some other type of transactional table type, you'll need -to do connection.commit() before closing the connection, or else -none of your changes will be written to the database. - -Conversely, you can also use connection.rollback() to throw away -any changes you've made since the last commit. - -Important note: Some SQL statements -- specifically DDL statements -like CREATE TABLE -- are non-transactional, so they can't be -rolled back, and they cause pending transactions to commit. - - -Other Errors ------------- - - OperationalError: (1251, 'Client does not support authentication protocol requested by server; consider upgrading MySQL client') - -This means your server and client libraries are not the same version. -More specifically, it probably means you have a 4.1 or newer server -and 4.0 or older client. You can either upgrade the client side, or -try some of the workarounds in `Password Hashing as of MySQL 4.1 -`_. - - -Other Resources ---------------- - -* Help forum. Please search before posting. - -* `Google `_ - -* READ README! - -* Read the User's Guide - -* Read `PEP-249`_ - -.. _`PEP-249`: http://www.python.org/peps/pep-0249.html - diff --git a/MySQLdb/doc/MySQLdb.txt b/MySQLdb/doc/MySQLdb.txt deleted file mode 100644 index fbc86e5..0000000 --- a/MySQLdb/doc/MySQLdb.txt +++ /dev/null @@ -1,718 +0,0 @@ -==================== -MySQLdb User's Guide -==================== - -.. contents:: -.. - -Introduction ------------- - -MySQLdb is an thread-compatible interface to the popular MySQL -database server that provides the Python database API. - -Installation ------------- - -The ``README`` file has complete installation instructions. - - -_mysql ------- - -If you want to write applications which are portable across databases, -use MySQLdb_, and avoid using this module directly. ``_mysql`` -provides an interface which mostly implements the MySQL C API. For -more information, see the `MySQL documentation`_. The documentation -for this module is intentionally weak because you probably should use -the higher-level MySQLdb module. If you really need it, use the -standard MySQL docs and transliterate as necessary. - -.. _`MySQL documentation`: http://dev.mysql.com/doc/ - - -MySQL C API translation -....................... - -The MySQL C API has been wrapped in an object-oriented way. The only -MySQL data structures which are implemented are the ``MYSQL`` -(database connection handle) and ``MYSQL_RES`` (result handle) -types. In general, any function which takes ``MYSQL *mysql`` as an -argument is now a method of the connection object, and any function -which takes ``MYSQL_RES *result`` as an argument is a method of the -result object. Functions requiring none of the MySQL data structures -are implemented as functions in the module. Functions requiring one of -the other MySQL data structures are generally not implemented. -Deprecated functions are not implemented. In all cases, the ``mysql_`` -prefix is dropped from the name. Most of the ``conn`` methods listed -are also available as MySQLdb Connection object methods. Their use is -non-portable. - -MySQL C API function mapping -............................ - -=================================== ================================== - C API ``_mysql`` -=================================== ================================== - ``mysql_affected_rows()`` ``conn.affected_rows()`` - ``mysql_autocommit()`` ``conn.autocommit()`` - ``mysql_character_set_name()`` ``conn.character_set_name()`` - ``mysql_close()`` ``conn.close()`` - ``mysql_commit()`` ``conn.commit()`` - ``mysql_connect()`` ``_mysql.connect()`` - ``mysql_data_seek()`` ``result.data_seek()`` - ``mysql_debug()`` ``_mysql.debug()`` - ``mysql_dump_debug_info`` ``conn.dump_debug_info()`` - ``mysql_escape_string()`` ``_mysql.escape_string()`` - ``mysql_fetch_row()`` ``result.fetch_row()`` - ``mysql_get_character_set_info()`` ``conn.get_character_set_info()`` - ``mysql_get_client_info()`` ``_mysql.get_client_info()`` - ``mysql_get_host_info()`` ``conn.get_host_info()`` - ``mysql_get_proto_info()`` ``conn.get_proto_info()`` - ``mysql_get_server_info()`` ``conn.get_server_info()`` - ``mysql_info()`` ``conn.info()`` - ``mysql_insert_id()`` ``conn.insert_id()`` - ``mysql_num_fields()`` ``result.num_fields()`` - ``mysql_num_rows()`` ``result.num_rows()`` - ``mysql_options()`` various options to ``_mysql.connect()`` - ``mysql_ping()`` ``conn.ping()`` - ``mysql_query()`` ``conn.query()`` - ``mysql_real_connect()`` ``_mysql.connect()`` - ``mysql_real_query()`` ``conn.query()`` - ``mysql_real_escape_string()`` ``conn.escape_string()`` - ``mysql_rollback()`` ``conn.rollback()`` - ``mysql_row_seek()`` ``result.row_seek()`` - ``mysql_row_tell()`` ``result.row_tell()`` - ``mysql_select_db()`` ``conn.select_db()`` - ``mysql_set_character_set()`` ``conn.set_character_set()`` - ``mysql_ssl_set()`` ``ssl`` option to ``_mysql.connect()`` - ``mysql_stat()`` ``conn.stat()`` - ``mysql_store_result()`` ``conn.store_result()`` - ``mysql_thread_id()`` ``conn.thread_id()`` - ``mysql_thread_safe_client()`` ``conn.thread_safe_client()`` - ``mysql_use_result()`` ``conn.use_result()`` - ``mysql_warning_count()`` ``conn.warning_count()`` - ``CLIENT_*`` ``MySQLdb.constants.CLIENT.*`` - ``CR_*`` ``MySQLdb.constants.CR.*`` - ``ER_*`` ``MySQLdb.constants.ER.*`` - ``FIELD_TYPE_*`` ``MySQLdb.constants.FIELD_TYPE.*`` - ``FLAG_*`` ``MySQLdb.constants.FLAG.*`` -=================================== ================================== - - -Some _mysql examples -.................... - -Okay, so you want to use ``_mysql`` anyway. Here are some examples. - -The simplest possible database connection is:: - - import _mysql - db=_mysql.connect() - -This creates a connection to the MySQL server running on the local -machine using the standard UNIX socket (or named pipe on Windows), -your login name (from the USER environment variable), no password, and -does not ``USE`` a database. Chances are you need to supply more -information.:: - - db=_mysql.connect("localhost","joebob","moonpie","thangs") - -This creates a connection to the MySQL server running on the local -machine via a UNIX socket (or named pipe), the user name "joebob", the -password "moonpie", and selects the initial database "thangs". - -We haven't even begun to touch upon all the parameters ``connect()`` -can take. For this reason, I prefer to use keyword parameters:: - - db=_mysql.connect(host="localhost",user="joebob", - passwd="moonpie",db="thangs") - -This does exactly what the last example did, but is arguably easier to -read. But since the default host is "localhost", and if your login -name really was "joebob", you could shorten it to this:: - - db=_mysql.connect(passwd="moonpie",db="thangs") - -UNIX sockets and named pipes don't work over a network, so if you -specify a host other than localhost, TCP will be used, and you can -specify an odd port if you need to (the default port is 3306):: - - db=_mysql.connect(host="outhouse",port=3307,passwd="moonpie",db="thangs") - -If you really had to, you could connect to the local host with TCP by -specifying the full host name, or 127.0.0.1. - -Generally speaking, putting passwords in your code is not such a good -idea:: - - db=_mysql.connect(host="outhouse",db="thangs",read_default_file="~/.my.cnf") - -This does what the previous example does, but gets the username and -password and other parameters from ~/.my.cnf (UNIX-like systems). Read -about `option files`_ for more details. - -.. _`option files`: http://dev.mysql.com/doc/mysql/en/Option_files.html - -So now you have an open connection as ``db`` and want to do a -query. Well, there are no cursors in MySQL, and no parameter -substitution, so you have to pass a complete query string to -``db.query()``:: - - db.query("""SELECT spam, eggs, sausage FROM breakfast - WHERE price < 5""") - -There's no return value from this, but exceptions can be raised. The -exceptions are defined in a separate module, ``_mysql_exceptions``, -but ``_mysql`` exports them. Read DB API specification PEP-249_ to -find out what they are, or you can use the catch-all ``MySQLError``. - -.. _PEP-249: http://www.python.org/peps/pep-0249.html - -At this point your query has been executed and you need to get the -results. You have two options:: - - r=db.store_result() - # ...or... - r=db.use_result() - -Both methods return a result object. What's the difference? -``store_result()`` returns the entire result set to the client -immediately. If your result set is really large, this could be a -problem. One way around this is to add a ``LIMIT`` clause to your -query, to limit the number of rows returned. The other is to use -``use_result()``, which keeps the result set in the server and sends -it row-by-row when you fetch. This does, however, tie up server -resources, and it ties up the connection: You cannot do any more -queries until you have fetched **all** the rows. Generally I -recommend using ``store_result()`` unless your result set is really -huge and you can't use ``LIMIT`` for some reason. - -Now, for actually getting real results:: - - >>> r.fetch_row() - (('3','2','0'),) - -This might look a little odd. The first thing you should know is, -``fetch_row()`` takes some additional parameters. The first one is, -how many rows (``maxrows``) should be returned. By default, it returns -one row. It may return fewer rows than you asked for, but never -more. If you set ``maxrows=0``, it returns all rows of the result -set. If you ever get an empty tuple back, you ran out of rows. - -The second parameter (``how``) tells it how the row should be -represented. By default, it is zero which means, return as a tuple. -``how=1`` means, return it as a dictionary, where the keys are the -column names, or ``table.column`` if there are two columns with the -same name (say, from a join). ``how=2`` means the same as ``how=1`` -except that the keys are *always* ``table.column``; this is for -compatibility with the old ``Mysqldb`` module. - -OK, so why did we get a 1-tuple with a tuple inside? Because we -implicitly asked for one row, since we didn't specify ``maxrows``. - -The other oddity is: Assuming these are numeric columns, why are they -returned as strings? Because MySQL returns all data as strings and -expects you to convert it yourself. This would be a real pain in the -ass, but in fact, ``_mysql`` can do this for you. (And ``MySQLdb`` -does do this for you.) To have automatic type conversion done, you -need to create a type converter dictionary, and pass this to -``connect()`` as the ``conv`` keyword parameter. - -The keys of ``conv`` should be MySQL column types, which in the -C API are ``FIELD_TYPE_*``. You can get these values like this:: - - from MySQLdb.constants import FIELD_TYPE - -By default, any column type that can't be found in ``conv`` is -returned as a string, which works for a lot of stuff. For our -purposes, we probably want this:: - - my_conv = { FIELD_TYPE.LONG: int } - -This means, if it's a ``FIELD_TYPE_LONG``, call the builtin ``int()`` -function on it. Note that ``FIELD_TYPE_LONG`` is an ``INTEGER`` -column, which corresponds to a C ``long``, which is also the type used -for a normal Python integer. But beware: If it's really an ``UNSIGNED -INTEGER`` column, this could cause overflows. For this reason, -``MySQLdb`` actually uses ``long()`` to do the conversion. But we'll -ignore this potential problem for now. - -Then if you use ``db=_mysql.connect(conv=my_conv...)``, the -results will come back ``((3, 2, 0),)``, which is what you would -expect. - -MySQLdb -------- - -MySQLdb is a thin Python wrapper around ``_mysql`` which makes it -compatible with the Python DB API interface (version 2). In reality, -a fair amount of the code which implements the API is in ``_mysql`` -for the sake of efficiency. - -The DB API specification PEP-249_ should be your primary guide for -using this module. Only deviations from the spec and other -database-dependent things will be documented here. - -Functions and attributes -........................ - -Only a few top-level functions and attributes are defined within -MySQLdb. - -connect(parameters...) - Constructor for creating a connection to the - database. Returns a Connection Object. Parameters are the - same as for the MySQL C API. In addition, there are a few - additional keywords that correspond to what you would pass - ``mysql_options()`` before connecting. Note that some - parameters must be specified as keyword arguments! The - default value for each parameter is NULL or zero, as - appropriate. Consult the MySQL documentation for more - details. The important parameters are: - - host - name of host to connect to. Default: use the local host - via a UNIX socket (where applicable) - - user - user to authenticate as. Default: current effective user. - - passwd - password to authenticate with. Default: no password. - - db - database to use. Default: no default database. - - port - TCP port of MySQL server. Default: standard port (3306). - - unix_socket - location of UNIX socket. Default: use default location or - TCP for remote hosts. - - conv - type conversion dictionary. Default: a copy of - ``MySQLdb.converters.conversions`` - - compress - Enable protocol compression. Default: no compression. - - connect_timeout - Abort if connect is not completed within - given number of seconds. Default: no timeout (?) - - named_pipe - Use a named pipe (Windows). Default: don't. - - init_command - Initial command to issue to server upon - connection. Default: Nothing. - - read_default_file - MySQL configuration file to read; see - the MySQL documentation for ``mysql_options()``. - - read_default_group - Default group to read; see the MySQL - documentation for ``mysql_options()``. - - cursorclass - cursor class that ``cursor()`` uses, unless - overridden. Default: ``MySQLdb.cursors.Cursor``. *This - must be a keyword parameter.* - - use_unicode - If True, CHAR and VARCHAR and TEXT columns are returned as - Unicode strings, using the configured character set. It is - best to set the default encoding in the server - configuration, or client configuration (read with - read_default_file). If you change the character set after - connecting (MySQL-4.1 and later), you'll need to put the - correct character set name in connection.charset. - - If False, text-like columns are returned as normal strings, - but you can always write Unicode strings. - - *This must be a keyword parameter.* - - charset - If present, the connection character set will be changed - to this character set, if they are not equal. Support for - changing the character set requires MySQL-4.1 and later - server; if the server is too old, UnsupportedError will be - raised. This option implies use_unicode=True, but you can - override this with use_unicode=False, though you probably - shouldn't. - - If not present, the default character set is used. - - *This must be a keyword parameter.* - - sql_mode - If present, the session SQL mode will be set to the given - string. For more information on sql_mode, see the MySQL - documentation. Only available for 4.1 and newer servers. - - If not present, the session SQL mode will be unchanged. - - *This must be a keyword parameter.* - - ssl - This parameter takes a dictionary or mapping, where the - keys are parameter names used by the mysql_ssl_set_ MySQL - C API call. If this is set, it initiates an SSL connection - to the server; if there is no SSL support in the client, - an exception is raised. *This must be a keyword - parameter.* - -.. _mysql_ssl_set: http://dev.mysql.com/doc/mysql/en/mysql_ssl_set.html - - -apilevel - String constant stating the supported DB API level. '2.0' - -threadsafety - Integer constant stating the level of thread safety the - interface supports. This is set to 1, which means: Threads may - share the module. - - The MySQL protocol can not handle multiple threads using the - same connection at once. Some earlier versions of MySQLdb - utilized locking to achieve a threadsafety of 2. While this is - not terribly hard to accomplish using the standard Cursor class - (which uses ``mysql_store_result()``), it is complicated by - SSCursor (which uses ``mysql_use_result()``; with the latter you - must ensure all the rows have been read before another query can - be executed. It is further complicated by the addition of - transactions, since transactions start when a cursor execute a - query, but end when ``COMMIT`` or ``ROLLBACK`` is executed by - the Connection object. Two threads simply cannot share a - connection while a transaction is in progress, in addition to - not being able to share it during query execution. This - excessively complicated the code to the point where it just - isn't worth it. - - The general upshot of this is: Don't share connections between - threads. It's really not worth your effort or mine, and in the - end, will probably hurt performance, since the MySQL server runs - a separate thread for each connection. You can certainly do - things like cache connections in a pool, and give those - connections to one thread at a time. If you let two threads use - a connection simultaneously, the MySQL client library will - probably upchuck and die. You have been warned. - - For threaded applications, try using a connection pool. - This can be done using the `Pool module`_. - - .. _`Pool module`: http://dustman.net/andy/python/Pool - -charset - The character set used by the connection. In MySQL-4.1 and newer, - it is possible (but not recommended) to change the connection's - character set with an SQL statement. If you do this, you'll also - need to change this attribute. Otherwise, you'll get encoding - errors. - -paramstyle - String constant stating the type of parameter marker formatting - expected by the interface. Set to 'format' = ANSI C printf - format codes, e.g. '...WHERE name=%s'. If a mapping object is - used for conn.execute(), then the interface actually uses - 'pyformat' = Python extended format codes, e.g. '...WHERE - name=%(name)s'. However, the API does not presently allow the - specification of more than one style in paramstyle. - - Note that any literal percent signs in the query string passed - to execute() must be escaped, i.e. %%. - - Parameter placeholders can **only** be used to insert column - values. They can **not** be used for other parts of SQL, such as - table names, statements, etc. - -conv - A dictionary or mapping which controls how types are converted - from MySQL to Python and vice versa. - - If the key is a MySQL type (from ``FIELD_TYPE.*``), then the value - can be either: - - * a callable object which takes a string argument (the MySQL - value),' returning a Python value - - * a sequence of 2-tuples, where the first value is a combination - of flags from ``MySQLdb.constants.FLAG``, and the second value - is a function as above. The sequence is tested until the flags - on the field match those of the first value. If both values - are None, then the default conversion is done. Presently this - is only used to distinquish TEXT and BLOB columns. - - If the key is a Python type or class, then the value is a - callable Python object (usually a function) taking two arguments - (value to convert, and the conversion dictionary) which converts - values of this type to a SQL literal string value. - - This is initialized with reasonable defaults for most - types. When creating a Connection object, you can pass your own - type converter dictionary as a keyword parameter. Otherwise, it - uses a copy of ``MySQLdb.converters.conversions``. Several - non-standard types are returned as strings, which is how MySQL - returns all columns. For more details, see the built-in module - documentation. - - -Connection Objects -.................. - -Connection objects are returned by the ``connect()`` function. - -commit() - If the database and the tables support transactions, this - commits the current transaction; otherwise this method - successfully does nothing. - -rollback() - If the database and tables support transactions, this rolls back - (cancels) the current transaction; otherwise a - ``NotSupportedError`` is raised. - -cursor([cursorclass]) - MySQL does not support cursors; however, cursors are easily - emulated. You can supply an alternative cursor class as an - optional parameter. If this is not present, it defaults to the - value given when creating the connection object, or the standard - ``Cursor`` class. Also see the additional supplied cursor - classes in the usage section. - -There are many more methods defined on the connection object which -are MySQL-specific. For more information on them, consult the internal -documentation using ``pydoc``. - - -Cursor Objects -.............. - -callproc(procname, args) - Calls stored procedure procname with the sequence of arguments - in args. Returns the original arguments. Stored procedure - support only works with MySQL-5.0 and newer. - - **Compatibility note:** PEP-249_ specifies that if there are - OUT or INOUT parameters, the modified values are to be - returned. This is not consistently possible with MySQL. Stored - procedure arguments must be passed as server variables, and - can only be returned with a SELECT statement. Since a stored - procedure may return zero or more result sets, it is impossible - for MySQLdb to determine if there are result sets to fetch - before the modified parmeters are accessible. - - The parameters are stored in the server as @_*procname*_*n*, - where *n* is the position of the parameter. I.e., if you - cursor.callproc('foo', (a, b, c)), the parameters will be - accessible by a SELECT statement as @_foo_0, @_foo_1, and - @_foo_2. - - **Compatibility note:** It appears that the mere act of - executing the CALL statement produces an empty result set, which - appears after any result sets which might be generated by the - stored procedure. Thus, you will always need to use nextset() to - advance result sets. - -close() - Closes the cursor. Future operations raise ``ProgrammingError``. - If you are using server-side cursors, it is very important to - close the cursor when you are done with it and before creating a - new one. - -info() - Returns some information about the last query. Normally - you don't need to check this. If there are any MySQL - warnings, it will cause a Warning to be issued through - the Python warning module. By default, Warning causes a - message to appear on the console. However, it is possible - to filter these out or cause Warning to be raised as exception. - See the MySQL docs for ``mysql_info()``, and the Python warning - module. (Non-standard) - -setinputsizes() - Does nothing, successfully. - -setoutputsizes() - Does nothing, successfully. - -nextset() - Advances the cursor to the next result set, discarding the remaining - rows in the current result set. If there are no additional result - sets, it returns None; otherwise it returns a true value. - - Note that MySQL doesn't support multiple result sets until 4.1. - - -Some examples -............. - -The ``connect()`` method works nearly the same as with `_mysql`_:: - - import MySQLdb - db=MySQLdb.connect(passwd="moonpie",db="thangs") - -To perform a query, you first need a cursor, and then you can execute -queries on it:: - - c=db.cursor() - max_price=5 - c.execute("""SELECT spam, eggs, sausage FROM breakfast - WHERE price < %s""", (max_price,)) - -In this example, ``max_price=5`` Why, then, use ``%s`` in the -string? Because MySQLdb will convert it to a SQL literal value, which -is the string '5'. When it's finished, the query will actually say, -"...WHERE price < 5". - -Why the tuple? Because the DB API requires you to pass in any -parameters as a sequence. Due to the design of the parser, (max_price) -is interpreted as using algebraic grouping and simply as max_price and -not a tuple. Adding a comma, i.e. (max_price,) forces it to make a -tuple. - -And now, the results:: - - >>> c.fetchone() - (3L, 2L, 0L) - -Quite unlike the ``_mysql`` example, this returns a single tuple, -which is the row, and the values are properly converted by default... -except... What's with the L's? - -As mentioned earlier, while MySQL's INTEGER column translates -perfectly into a Python integer, UNSIGNED INTEGER could overflow, so -these values are converted to Python long integers instead. - -If you wanted more rows, you could use ``c.fetchmany(n)`` or -``c.fetchall()``. These do exactly what you think they do. On -``c.fetchmany(n)``, the ``n`` is optional and defaults to -``c.arraysize``, which is normally 1. Both of these methods return a -sequence of rows, or an empty sequence if there are no more rows. If -you use a weird cursor class, the rows themselves might not be tuples. - -Note that in contrast to the above, ``c.fetchone()`` returns ``None`` -when there are no more rows to fetch. - -The only other method you are very likely to use is when you have to -do a multi-row insert:: - - c.executemany( - """INSERT INTO breakfast (name, spam, eggs, sausage, price) - VALUES (%s, %s, %s, %s, %s)""", - [ - ("Spam and Sausage Lover's Plate", 5, 1, 8, 7.95 ), - ("Not So Much Spam Plate", 3, 2, 0, 3.95 ), - ("Don't Wany ANY SPAM! Plate", 0, 4, 3, 5.95 ) - ] ) - -Here we are inserting three rows of five values. Notice that there is -a mix of types (strings, ints, floats) though we still only use -``%s``. And also note that we only included format strings for one -row. MySQLdb picks those out and duplicates them for each row. - -Using and extending -------------------- - -In general, it is probably wise to not directly interact with the DB -API except for small applicatons. Databases, even SQL databases, vary -widely in capabilities and may have non-standard features. The DB API -does a good job of providing a reasonably portable interface but some -methods are non-portable. Specifically, the parameters accepted by -``connect()`` are completely implementation-dependent. - -If you believe your application may need to run on several different -databases, the author recommends the following approach, based on -personal experience: Write a simplified API for your application which -implements the specific queries and operations your application needs -to perform. Implement this API as a base class which should be have -few database dependencies, and then derive a subclass from this which -implements the necessary dependencies. In this way, porting your -application to a new database should be a relatively simple matter of -creating a new subclass, assuming the new database is reasonably -standard. - -Because MySQLdb's Connection and Cursor objects are written in Python, -you can easily derive your own subclasses. There are several Cursor -classes in MySQLdb.cursors: - -BaseCursor - The base class for Cursor objects. This does not raise Warnings. - -CursorStoreResultMixIn - Causes the Cursor to use the ``mysql_store_result()`` function to - get the query result. The entire result set is stored on the - client side. - -CursorUseResultMixIn - Causes the cursor to use the ``mysql_use_result()`` function to - get the query result. The result set is stored on the server side - and is transferred row by row using fetch operations. - -CursorTupleRowsMixIn - Causes the cursor to return rows as a tuple of the column values. - -CursorDictRowsMixIn - - Causes the cursor to return rows as a dictionary, where the keys - are column names and the values are column values. Note that if - the column names are not unique, i.e., you are selecting from two - tables that share column names, some of them will be rewritten as - ``table.column``. This can be avoided by using the SQL ``AS`` - keyword. (This is yet-another reason not to use ``*`` in SQL - queries, particularly where ``JOIN`` is involved.) - -Cursor - The default cursor class. This class is composed of - ``CursorWarningMixIn``, ``CursorStoreResultMixIn``, - ``CursorTupleRowsMixIn,`` and ``BaseCursor``, i.e. it raises - ``Warning``, uses ``mysql_store_result()``, and returns rows as - tuples. - -DictCursor - Like ``Cursor`` except it returns rows as dictionaries. - -SSCursor - A "server-side" cursor. Like ``Cursor`` but uses - ``CursorUseResultMixIn``. Use only if you are dealing with - potentially large result sets. - -SSDictCursor - Like ``SSCursor`` except it returns rows as dictionaries. - - -Embedded Server ---------------- - -Instead of connecting to a stand-alone server over the network, -the embedded server support lets you run a full server right in -your Python code or application server. - -If you have built MySQLdb with embedded server support, there -are two additional functions you will need to make use of: - - server_init(args, groups) - Initialize embedded server. If this client is not linked against - the embedded server library, this function does nothing. - - args - sequence of command-line arguments - groups - sequence of groups to use in defaults files - - server_end() - Shut down embedded server. If not using an embedded server, this - does nothing. - -See the MySQL documentation for more information on the embedded -server. - - - -:Title: MySQLdb: a Python interface for MySQL -:Author: Andy Dustman -:Version: $Revision$ diff --git a/MySQLdb/ez_setup.py b/MySQLdb/ez_setup.py deleted file mode 100644 index 1ff1d3e..0000000 --- a/MySQLdb/ez_setup.py +++ /dev/null @@ -1,284 +0,0 @@ -#!python -"""Bootstrap setuptools installation - -If you want to use setuptools in your package's setup.py, just include this -file in the same directory with it, and add this to the top of your setup.py:: - - from ez_setup import use_setuptools - use_setuptools() - -If you want to require a specific version of setuptools, set a download -mirror, or use an alternate download directory, you can do so by supplying -the appropriate options to ``use_setuptools()``. - -This file can also be run as a script to install or upgrade setuptools. -""" -import sys -DEFAULT_VERSION = "0.6c11" -DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] - -md5_data = { - 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', - 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', - 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', - 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', - 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', - 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', - 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', - 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', - 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', - 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', - 'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090', - 'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4', - 'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7', - 'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5', - 'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de', - 'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b', - 'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2', - 'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086', - 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', - 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', - 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', - 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', - 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', - 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', - 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', - 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', - 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', - 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', - 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', - 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', - 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', - 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', - 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2', - 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e', - 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372', - 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902', - 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de', - 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b', - 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03', - 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a', - 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6', - 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', -} - -import sys, os -try: from hashlib import md5 -except ImportError: from md5 import md5 - -def _validate_md5(egg_name, data): - if egg_name in md5_data: - digest = md5(data).hexdigest() - if digest != md5_data[egg_name]: - print >>sys.stderr, ( - "md5 validation of %s failed! (Possible download problem?)" - % egg_name - ) - sys.exit(2) - return data - -def use_setuptools( - version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, - download_delay=15 -): - """Automatically find/download setuptools and make it available on sys.path - - `version` should be a valid setuptools version number that is available - as an egg for download under the `download_base` URL (which should end with - a '/'). `to_dir` is the directory where setuptools will be downloaded, if - it is not already available. If `download_delay` is specified, it should - be the number of seconds that will be paused before initiating a download, - should one be required. If an older version of setuptools is installed, - this routine will print a message to ``sys.stderr`` and raise SystemExit in - an attempt to abort the calling script. - """ - was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules - def do_download(): - egg = download_setuptools(version, download_base, to_dir, download_delay) - sys.path.insert(0, egg) - import setuptools; setuptools.bootstrap_install_from = egg - try: - import pkg_resources - except ImportError: - return do_download() - try: - pkg_resources.require("setuptools>="+version); return - except pkg_resources.VersionConflict, e: - if was_imported: - print >>sys.stderr, ( - "The required version of setuptools (>=%s) is not available, and\n" - "can't be installed while this script is running. Please install\n" - " a more recent version first, using 'easy_install -U setuptools'." - "\n\n(Currently using %r)" - ) % (version, e.args[0]) - sys.exit(2) - else: - del pkg_resources, sys.modules['pkg_resources'] # reload ok - return do_download() - except pkg_resources.DistributionNotFound: - return do_download() - -def download_setuptools( - version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, - delay = 15 -): - """Download setuptools from a specified location and return its filename - - `version` should be a valid setuptools version number that is available - as an egg for download under the `download_base` URL (which should end - with a '/'). `to_dir` is the directory where the egg will be downloaded. - `delay` is the number of seconds to pause before an actual download attempt. - """ - import urllib2, shutil - egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) - url = download_base + egg_name - saveto = os.path.join(to_dir, egg_name) - src = dst = None - if not os.path.exists(saveto): # Avoid repeated downloads - try: - from distutils import log - if delay: - log.warn(""" ---------------------------------------------------------------------------- -This script requires setuptools version %s to run (even to display -help). I will attempt to download it for you (from -%s), but -you may need to enable firewall access for this script first. -I will start the download in %d seconds. - -(Note: if this machine does not have network access, please obtain the file - - %s - -and place it in this directory before rerunning this script.) ----------------------------------------------------------------------------""", - version, download_base, delay, url - ); from time import sleep; sleep(delay) - log.warn("Downloading %s", url) - src = urllib2.urlopen(url) - # Read/write all in one block, so we don't create a corrupt file - # if the download is interrupted. - data = _validate_md5(egg_name, src.read()) - dst = open(saveto,"wb"); dst.write(data) - finally: - if src: src.close() - if dst: dst.close() - return os.path.realpath(saveto) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -def main(argv, version=DEFAULT_VERSION): - """Install or upgrade setuptools and EasyInstall""" - try: - import setuptools - except ImportError: - egg = None - try: - egg = download_setuptools(version, delay=0) - sys.path.insert(0,egg) - from setuptools.command.easy_install import main - return main(list(argv)+[egg]) # we're done here - finally: - if egg and os.path.exists(egg): - os.unlink(egg) - else: - if setuptools.__version__ == '0.0.1': - print >>sys.stderr, ( - "You have an obsolete version of setuptools installed. Please\n" - "remove it from your system entirely before rerunning this script." - ) - sys.exit(2) - - req = "setuptools>="+version - import pkg_resources - try: - pkg_resources.require(req) - except pkg_resources.VersionConflict: - try: - from setuptools.command.easy_install import main - except ImportError: - from easy_install import main - main(list(argv)+[download_setuptools(delay=0)]) - sys.exit(0) # try to force an exit - else: - if argv: - from setuptools.command.easy_install import main - main(argv) - else: - print "Setuptools version",version,"or greater has been installed." - print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' - -def update_md5(filenames): - """Update our built-in md5 registry""" - - import re - - for name in filenames: - base = os.path.basename(name) - f = open(name,'rb') - md5_data[base] = md5(f.read()).hexdigest() - f.close() - - data = [" %r: %r,\n" % it for it in md5_data.items()] - data.sort() - repl = "".join(data) - - import inspect - srcfile = inspect.getsourcefile(sys.modules[__name__]) - f = open(srcfile, 'rb'); src = f.read(); f.close() - - match = re.search("\nmd5_data = {\n([^}]+)}", src) - if not match: - print >>sys.stderr, "Internal error!" - sys.exit(2) - - src = src[:match.start(1)] + repl + src[match.end(1):] - f = open(srcfile,'w') - f.write(src) - f.close() - - -if __name__=='__main__': - if len(sys.argv)>2 and sys.argv[1]=='--md5update': - update_md5(sys.argv[2:]) - else: - main(sys.argv[1:]) - - - - - - diff --git a/MySQLdb/metadata.cfg b/MySQLdb/metadata.cfg deleted file mode 100644 index 79edfff..0000000 --- a/MySQLdb/metadata.cfg +++ /dev/null @@ -1,58 +0,0 @@ -[metadata] -version: 1.2.4b3 -version_info: (1,2,4,'beta',3) -description: Python interface to MySQL -long_description: - ========================= - Python interface to MySQL - ========================= - \n - MySQLdb is an interface to the popular MySQL_ database server for - Python. The design goals are: - \n - - Compliance with Python database API version 2.0 [PEP-0249]_ - - Thread-safety - - Thread-friendliness (threads will not block each other) - \n - MySQL-3.23 through 5.5 and Python-2.4 through 2.7 are currently - supported. Python-3.0 will be supported in a future release. - \n - MySQLdb is `Free Software`_. - \n - .. _MySQL: http://www.mysql.com/ - .. _`Free Software`: http://www.gnu.org/ - .. [PEP-0249] http://www.python.org/peps/pep-0249.html -author: Andy Dustman -author_email: farcepest@gmail.com -license: GPL -platforms: ALL -url: http://sourceforge.net/projects/mysql-python -download_url: http://osdn.dl.sourceforge.net/sourceforge/mysql-python/MySQL-python-%(version)s.tar.gz -classifiers: - Development Status :: 5 - Production/Stable - Environment :: Other Environment - License :: OSI Approved :: GNU General Public License (GPL) - Operating System :: MacOS :: MacOS X - Operating System :: Microsoft :: Windows :: Windows NT/2000 - Operating System :: OS Independent - Operating System :: POSIX - Operating System :: POSIX :: Linux - Operating System :: Unix - Programming Language :: C - Programming Language :: Python - Topic :: Database - Topic :: Database :: Database Engines/Servers -py_modules: - _mysql_exceptions - MySQLdb.converters - MySQLdb.connections - MySQLdb.cursors - MySQLdb.release - MySQLdb.times - MySQLdb.constants.CR - MySQLdb.constants.FIELD_TYPE - MySQLdb.constants.ER - MySQLdb.constants.FLAG - MySQLdb.constants.REFRESH - MySQLdb.constants.CLIENT - diff --git a/MySQLdb/pymemcompat.h b/MySQLdb/pymemcompat.h deleted file mode 100644 index e7c538c..0000000 --- a/MySQLdb/pymemcompat.h +++ /dev/null @@ -1,87 +0,0 @@ - -/* The idea of this file is that you bundle it with your extension, - #include it, program to Python 2.3's memory API and have your - extension build with any version of Python from 1.5.2 through to - 2.3 (and hopefully beyond). */ - -#ifndef Py_PYMEMCOMPAT_H -#define Py_PYMEMCOMPAT_H - -#include "Python.h" - -/* There are three "families" of memory API: the "raw memory", "object - memory" and "object" families. (This is ignoring the matter of the - cycle collector, about which more is said below). - - Raw Memory: - - PyMem_Malloc, PyMem_Realloc, PyMem_Free - - Object Memory: - - PyObject_Malloc, PyObject_Realloc, PyObject_Free - - Object: - - PyObject_New, PyObject_NewVar, PyObject_Del - - The raw memory and object memory allocators both mimic the - malloc/realloc/free interface from ANSI C, but the object memory - allocator can (and, since 2.3, does by default) use a different - allocation strategy biased towards lots of lots of "small" - allocations. - - The object family is used for allocating Python objects, and the - initializers take care of some basic initialization (setting the - refcount to 1 and filling out the ob_type field) as well as having - a somewhat different interface. - - Do not mix the families! E.g. do not allocate memory with - PyMem_Malloc and free it with PyObject_Free. You may get away with - it quite a lot of the time, but there *are* scenarios where this - will break. You Have Been Warned. - - Also, in many versions of Python there are an insane amount of - memory interfaces to choose from. Use the ones described above. */ - -#if PY_VERSION_HEX < 0x01060000 -/* raw memory interface already present */ - -/* there is no object memory interface in 1.5.2 */ -#define PyObject_Malloc PyMem_Malloc -#define PyObject_Realloc PyMem_Realloc -#define PyObject_Free PyMem_Free - -/* the object interface is there, but the names have changed */ -#define PyObject_New PyObject_NEW -#define PyObject_NewVar PyObject_NEW_VAR -#define PyObject_Del PyMem_Free -#endif - -/* If your object is a container you probably want to support the - cycle collector, which was new in Python 2.0. - - Unfortunately, the interface to the collector that was present in - Python 2.0 and 2.1 proved to be tricky to use, and so changed in - 2.2 -- in a way that can't easily be papered over with macros. - - This file contains macros that let you program to the 2.2 GC API. - Your module will compile against any Python since version 1.5.2, - but the type will only participate in the GC in versions 2.2 and - up. Some work is still necessary on your part to only fill out the - tp_traverse and tp_clear fields when they exist and set tp_flags - appropriately. - - It is possible to support both the 2.0 and 2.2 GC APIs, but it's - not pretty and this comment block is too narrow to contain a - desciption of what's required... */ - -#if PY_VERSION_HEX < 0x020200B1 -#define PyObject_GC_New PyObject_New -#define PyObject_GC_NewVar PyObject_NewVar -#define PyObject_GC_Del PyObject_Del -#define PyObject_GC_Track(op) -#define PyObject_GC_UnTrack(op) -#endif - -#endif /* !Py_PYMEMCOMPAT_H */ diff --git a/MySQLdb/release.py b/MySQLdb/release.py new file mode 100644 index 0000000..d0767e1 --- /dev/null +++ b/MySQLdb/release.py @@ -0,0 +1,4 @@ + +__author__ = "Andy Dustman " +version_info = (1,2,4,'beta',3) +__version__ = "1.2.4b3" diff --git a/MySQLdb/setup.cfg b/MySQLdb/setup.cfg deleted file mode 100644 index e357362..0000000 --- a/MySQLdb/setup.cfg +++ /dev/null @@ -1,20 +0,0 @@ -[test] -test_suite = nose.collector - -[build_ext] -## Only uncomment/set these if the default configuration doesn't work -## Also see http://docs.python.org/dist/setup-config.html -# include-dirs = ? -# library-dirs = ? -# link-objects = ? -# rpath = ? -# libraries = ? - -[bdist_rpm] -doc_files = README MANIFEST doc/*.txt -vendor = MySQL-python SourceForge Project -packager = Andy Dustman -distribution-name = Red Stains Linux -requires = python -install-requires = distribute -build-requires = python-devel mysql-devel zlib-devel openssl-devel diff --git a/MySQLdb/setup.py b/MySQLdb/setup.py deleted file mode 100644 index 798f96f..0000000 --- a/MySQLdb/setup.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python - -import os -import sys - -from distribute_setup import use_setuptools -use_setuptools() -from setuptools import setup, Extension - -if not hasattr(sys, "hexversion") or sys.hexversion < 0x02040000: - raise Error("Python 2.4 or newer is required") - -if os.name == "posix": - from setup_posix import get_config -else: # assume windows - from setup_windows import get_config - -metadata, options = get_config() -metadata['ext_modules'] = [Extension(sources=['_mysql.c'], **options)] -metadata['long_description'] = metadata['long_description'].replace(r'\n', '') -setup(**metadata) diff --git a/MySQLdb/setup_common.py b/MySQLdb/setup_common.py deleted file mode 100644 index 03c39bb..0000000 --- a/MySQLdb/setup_common.py +++ /dev/null @@ -1,37 +0,0 @@ -try: - # Python 2.x - from ConfigParser import SafeConfigParser -except ImportError: - # Python 3.x - from configparser import ConfigParser as SafeConfigParser - -def get_metadata_and_options(): - config = SafeConfigParser() - config.read(['metadata.cfg', 'site.cfg']) - - metadata = dict(config.items('metadata')) - options = dict(config.items('options')) - - metadata['py_modules'] = list(filter(None, metadata['py_modules'].split('\n'))) - metadata['classifiers'] = list(filter(None, metadata['classifiers'].split('\n'))) - - return metadata, options - -def enabled(options, option): - value = options[option] - s = value.lower() - if s in ('yes','true','1','y'): - return True - elif s in ('no', 'false', '0', 'n'): - return False - else: - raise ValueError("Unknown value %s for option %s" % (value, option)) - -def create_release_file(metadata): - rel = open("MySQLdb/release.py",'w') - rel.write(""" -__author__ = "%(author)s <%(author_email)s>" -version_info = %(version_info)s -__version__ = "%(version)s" -""" % metadata) - rel.close() diff --git a/MySQLdb/setup_posix.py b/MySQLdb/setup_posix.py deleted file mode 100644 index f7cb588..0000000 --- a/MySQLdb/setup_posix.py +++ /dev/null @@ -1,102 +0,0 @@ -import os, sys -from ConfigParser import SafeConfigParser - -# This dequote() business is required for some older versions -# of mysql_config - -def dequote(s): - if s[0] in "\"'" and s[0] == s[-1]: - s = s[1:-1] - return s - -def compiler_flag(f): - return "-%s" % f - -def mysql_config(what): - from os import popen - - f = popen("%s --%s" % (mysql_config.path, what)) - data = f.read().strip().split() - ret = f.close() - if ret: - if ret/256: - data = [] - if ret/256 > 1: - raise EnvironmentError("%s not found" % (mysql_config.path,)) - return data -mysql_config.path = "mysql_config" - -def get_config(): - from setup_common import get_metadata_and_options, enabled, create_release_file - - metadata, options = get_metadata_and_options() - - if 'mysql_config' in options: - mysql_config.path = options['mysql_config'] - - extra_objects = [] - static = enabled(options, 'static') - if enabled(options, 'embedded'): - libs = mysql_config("libmysqld-libs") - client = "mysqld" - elif enabled(options, 'threadsafe'): - libs = mysql_config("libs_r") - client = "mysqlclient_r" - if not libs: - libs = mysql_config("libs") - client = "mysqlclient" - else: - libs = mysql_config("libs") - client = "mysqlclient" - - library_dirs = [ dequote(i[2:]) for i in libs if i.startswith(compiler_flag("L")) ] - libraries = [ dequote(i[2:]) for i in libs if i.startswith(compiler_flag("l")) ] - - removable_compile_args = [ compiler_flag(f) for f in "ILl" ] - extra_compile_args = [ i.replace("%", "%%") for i in mysql_config("cflags") - if i[:2] not in removable_compile_args ] - - # Copy the arch flags for linking as well - extra_link_args = list() - for i in range(len(extra_compile_args)): - if extra_compile_args[i] == '-arch': - extra_link_args += ['-arch', extra_compile_args[i + 1]] - - include_dirs = [ dequote(i[2:]) - for i in mysql_config('include') - if i.startswith(compiler_flag('I')) ] - if not include_dirs: # fix for MySQL-3.23 - include_dirs = [ dequote(i[2:]) - for i in mysql_config('cflags') - if i.startswith(compiler_flag('I')) ] - - if static: - extra_objects.append(os.path.join( - library_dirs[0],'lib%s.a' % client)) - - name = "MySQL-python" - if enabled(options, 'embedded'): - name = name + "-embedded" - metadata['name'] = name - - define_macros = [ - ('version_info', metadata['version_info']), - ('__version__', metadata['version']), - ] - create_release_file(metadata) - del metadata['version_info'] - ext_options = dict( - name = "_mysql", - library_dirs = library_dirs, - libraries = libraries, - extra_compile_args = extra_compile_args, - extra_link_args = extra_link_args, - include_dirs = include_dirs, - extra_objects = extra_objects, - define_macros = define_macros, - ) - return metadata, ext_options - -if __name__ == "__main__": - sys.stderr.write("""You shouldn't be running this directly; it is used by setup.py.""") - diff --git a/MySQLdb/setup_windows.py b/MySQLdb/setup_windows.py deleted file mode 100644 index ffe6397..0000000 --- a/MySQLdb/setup_windows.py +++ /dev/null @@ -1,46 +0,0 @@ -import os, sys - -def get_config(): - from setup_common import get_metadata_and_options, enabled, create_release_file - - metadata, options = get_metadata_and_options() - - connector = options["connector"] - - extra_objects = [] - - if enabled(options, 'embedded'): - client = "mysqld" - else: - client = "mysqlclient" - - library_dirs = [ os.path.join(connector, r'lib\opt') ] - libraries = [ 'kernel32', 'advapi32', 'wsock32', client ] - include_dirs = [ os.path.join(connector, r'include') ] - extra_compile_args = [ '/Zl' ] - - name = "MySQL-python" - if enabled(options, 'embedded'): - name = name + "-embedded" - metadata['name'] = name - - define_macros = [ - ('version_info', metadata['version_info']), - ('__version__', metadata['version']), - ] - create_release_file(metadata) - del metadata['version_info'] - ext_options = dict( - name = "_mysql", - library_dirs = library_dirs, - libraries = libraries, - extra_compile_args = extra_compile_args, - include_dirs = include_dirs, - extra_objects = extra_objects, - define_macros = define_macros, - ) - return metadata, ext_options - -if __name__ == "__main__": - sys.stderr.write("""You shouldn't be running this directly; it is used by setup.py.""") - diff --git a/MySQLdb/site.cfg b/MySQLdb/site.cfg deleted file mode 100644 index 369c87e..0000000 --- a/MySQLdb/site.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[options] -# embedded: link against the embedded server library -# threadsafe: use the threadsafe client -# static: link against a static library (probably required for embedded) - -embedded = False -threadsafe = True -static = False - -# The path to mysql_config. -# Only use this if mysql_config is not on your PATH, or you have some weird -# setup that requires it. -#mysql_config = /usr/local/bin/mysql_config - -# http://stackoverflow.com/questions/1972259/mysql-python-install-problem-using-virtualenv-windows-pip -# Windows connector libs for MySQL. You need a 32-bit connector for your 32-bit Python build. -connector = C:\Program Files (x86)\MySQL\MySQL Connector C 6.0.2 diff --git a/MySQLdb/tests/capabilities.py b/MySQLdb/tests/capabilities.py deleted file mode 100644 index 076361c..0000000 --- a/MySQLdb/tests/capabilities.py +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env python -O -""" Script to test database capabilities and the DB-API interface - for functionality and memory leaks. - - Adapted from a script by M-A Lemburg. - -""" -from time import time -import array -import unittest -from configdb import connection_factory - - -class DatabaseTest(unittest.TestCase): - - db_module = None - connect_args = () - connect_kwargs = dict() - create_table_extra = '' - rows = 10 - debug = False - - def setUp(self): - import gc - db = connection_factory(**self.connect_kwargs) - self.connection = db - self.cursor = db.cursor() - # TODO: this needs to be re-evaluated for Python 3 - self.BLOBText = ''.join([chr(i) for i in range(256)] * 100); - self.BLOBUText = u''.join([unichr(i) for i in range(16384)]) - self.BLOBBinary = self.db_module.Binary(''.join([chr(i) for i in range(256)] * 16)) - - leak_test = True - - def tearDown(self): - if self.leak_test: - import gc - del self.cursor - orphans = gc.collect() - self.failIf(orphans, "%d orphaned objects found after deleting cursor" % orphans) - - del self.connection - orphans = gc.collect() - self.failIf(orphans, "%d orphaned objects found after deleting connection" % orphans) - - def table_exists(self, name): - try: - self.cursor.execute('select * from %s where 1=0' % name) - except: - return False - else: - return True - - def quote_identifier(self, ident): - return '"%s"' % ident - - def new_table_name(self): - i = id(self.cursor) - while True: - name = self.quote_identifier('tb%08x' % i) - if not self.table_exists(name): - return name - i = i + 1 - - def create_table(self, columndefs): - - """ Create a table using a list of column definitions given in - columndefs. - - generator must be a function taking arguments (row_number, - col_number) returning a suitable data object for insertion - into the table. - - """ - self.table = self.new_table_name() - self.cursor.execute('CREATE TABLE %s (%s) %s' % - (self.table, - ',\n'.join(columndefs), - self.create_table_extra)) - - def check_data_integrity(self, columndefs, generator): - # insert - self.create_table(columndefs) - insert_statement = ('INSERT INTO %s VALUES (%s)' % - (self.table, - ','.join(['%s'] * len(columndefs)))) - data = [ [ generator(i,j) for j in range(len(columndefs)) ] - for i in range(self.rows) ] - self.cursor.executemany(insert_statement, data) - self.connection.commit() - # verify - self.cursor.execute('select * from %s' % self.table) - l = self.cursor.fetchall() - self.assertEquals(len(l), self.rows) - try: - for i in range(self.rows): - for j in range(len(columndefs)): - self.assertEquals(l[i][j], generator(i,j)) - finally: - if not self.debug: - self.cursor.execute('drop table %s' % (self.table)) - - def test_transactions(self): - columndefs = ( 'col1 INT', 'col2 VARCHAR(255)') - def generator(row, col): - if col == 0: return row - else: return ('%i' % (row%10))*255 - self.create_table(columndefs) - insert_statement = ('INSERT INTO %s VALUES (%s)' % - (self.table, - ','.join(['%s'] * len(columndefs)))) - data = [ [ generator(i,j) for j in range(len(columndefs)) ] - for i in range(self.rows) ] - self.cursor.executemany(insert_statement, data) - # verify - self.connection.commit() - self.cursor.execute('select * from %s' % self.table) - l = self.cursor.fetchall() - self.assertEquals(len(l), self.rows) - for i in range(self.rows): - for j in range(len(columndefs)): - self.assertEquals(l[i][j], generator(i,j)) - delete_statement = 'delete from %s where col1=%%s' % self.table - self.cursor.execute(delete_statement, (0,)) - self.cursor.execute('select col1 from %s where col1=%s' % \ - (self.table, 0)) - l = self.cursor.fetchall() - self.assertFalse(l, "DELETE didn't work") - self.connection.rollback() - self.cursor.execute('select col1 from %s where col1=%s' % \ - (self.table, 0)) - l = self.cursor.fetchall() - self.assertTrue(len(l) == 1, "ROLLBACK didn't work") - self.cursor.execute('drop table %s' % (self.table)) - - def test_truncation(self): - columndefs = ( 'col1 INT', 'col2 VARCHAR(255)') - def generator(row, col): - if col == 0: return row - else: return ('%i' % (row%10))*((255-self.rows/2)+row) - self.create_table(columndefs) - insert_statement = ('INSERT INTO %s VALUES (%s)' % - (self.table, - ','.join(['%s'] * len(columndefs)))) - - try: - self.cursor.execute(insert_statement, (0, '0'*256)) - except self.connection.DataError: - pass - else: - self.fail("Over-long column did not generate warnings/exception with single insert") - - self.connection.rollback() - - try: - for i in range(self.rows): - data = [] - for j in range(len(columndefs)): - data.append(generator(i,j)) - self.cursor.execute(insert_statement,tuple(data)) - except self.connection.DataError: - pass - else: - self.fail("Over-long columns did not generate warnings/exception with execute()") - - self.connection.rollback() - - try: - data = [ [ generator(i,j) for j in range(len(columndefs)) ] - for i in range(self.rows) ] - self.cursor.executemany(insert_statement, data) - except self.connection.DataError: - pass - else: - self.fail("Over-long columns did not generate warnings/exception with executemany()") - - self.connection.rollback() - self.cursor.execute('drop table %s' % (self.table)) - - def test_CHAR(self): - # Character data - def generator(row,col): - return ('%i' % ((row+col) % 10)) * 255 - self.check_data_integrity( - ('col1 char(255)','col2 char(255)'), - generator) - - def test_INT(self): - # Number data - def generator(row,col): - return row*row - self.check_data_integrity( - ('col1 INT',), - generator) - - def test_DECIMAL(self): - # DECIMAL - def generator(row,col): - from decimal import Decimal - return Decimal("%d.%02d" % (row, col)) - self.check_data_integrity( - ('col1 DECIMAL(5,2)',), - generator) - - def test_DATE(self): - ticks = time() - def generator(row,col): - return self.db_module.DateFromTicks(ticks+row*86400-col*1313) - self.check_data_integrity( - ('col1 DATE',), - generator) - - def test_TIME(self): - ticks = time() - def generator(row,col): - return self.db_module.TimeFromTicks(ticks+row*86400-col*1313) - self.check_data_integrity( - ('col1 TIME',), - generator) - - def test_DATETIME(self): - ticks = time() - def generator(row,col): - return self.db_module.TimestampFromTicks(ticks+row*86400-col*1313) - self.check_data_integrity( - ('col1 DATETIME',), - generator) - - def test_TIMESTAMP(self): - ticks = time() - def generator(row,col): - return self.db_module.TimestampFromTicks(ticks+row*86400-col*1313) - self.check_data_integrity( - ('col1 TIMESTAMP',), - generator) - - def test_fractional_TIMESTAMP(self): - ticks = time() - def generator(row,col): - return self.db_module.TimestampFromTicks(ticks+row*86400-col*1313+row*0.7*col/3.0) - self.check_data_integrity( - ('col1 TIMESTAMP',), - generator) - - def test_LONG(self): - def generator(row,col): - if col == 0: - return row - else: - return self.BLOBUText # 'BLOB Text ' * 1024 - self.check_data_integrity( - ('col1 INT','col2 LONG'), - generator) - - def test_TEXT(self): - def generator(row,col): - return self.BLOBUText # 'BLOB Text ' * 1024 - self.check_data_integrity( - ('col2 TEXT',), - generator) - - def test_LONG_BYTE(self): - def generator(row,col): - if col == 0: - return row - else: - return self.BLOBBinary # 'BLOB\000Binary ' * 1024 - self.check_data_integrity( - ('col1 INT','col2 LONG BYTE'), - generator) - - def test_BLOB(self): - def generator(row,col): - if col == 0: - return row - else: - return self.BLOBBinary # 'BLOB\000Binary ' * 1024 - self.check_data_integrity( - ('col1 INT','col2 BLOB'), - generator) - diff --git a/MySQLdb/tests/configdb.py b/MySQLdb/tests/configdb.py deleted file mode 100644 index cd6d43d..0000000 --- a/MySQLdb/tests/configdb.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Configure database connection for tests.""" - -from os import environ, path - -tests_path = path.dirname(__file__) -conf_file = environ.get('TESTDB', 'default.cnf') -conf_path = path.join(tests_path, conf_file) -connect_kwargs = dict( - read_default_file = conf_path, - read_default_group = "MySQLdb-tests", -) - -def connection_kwargs(kwargs): - db_kwargs = connect_kwargs.copy() - db_kwargs.update(kwargs) - return db_kwargs - -def connection_factory(**kwargs): - import MySQLdb - db_kwargs = connection_kwargs(kwargs) - db = MySQLdb.connect(**db_kwargs) - return db - - - diff --git a/MySQLdb/tests/dbapi20.py b/MySQLdb/tests/dbapi20.py deleted file mode 100644 index ad292ae..0000000 --- a/MySQLdb/tests/dbapi20.py +++ /dev/null @@ -1,853 +0,0 @@ -#!/usr/bin/env python -''' Python DB API 2.0 driver compliance unit test suite. - - This software is Public Domain and may be used without restrictions. - - "Now we have booze and barflies entering the discussion, plus rumours of - DBAs on drugs... and I won't tell you what flashes through my mind each - time I read the subject line with 'Anal Compliance' in it. All around - this is turning out to be a thoroughly unwholesome unit test." - - -- Ian Bicking -''' - -__rcs_id__ = '$Id$' -__version__ = '$Revision$'[11:-2] -__author__ = 'Stuart Bishop ' - -import unittest -import time - -# $Log$ -# Revision 1.1.2.1 2006/02/25 03:44:32 adustman -# Generic DB-API unit test module -# -# Revision 1.10 2003/10/09 03:14:14 zenzen -# Add test for DB API 2.0 optional extension, where database exceptions -# are exposed as attributes on the Connection object. -# -# Revision 1.9 2003/08/13 01:16:36 zenzen -# Minor tweak from Stefan Fleiter -# -# Revision 1.8 2003/04/10 00:13:25 zenzen -# Changes, as per suggestions by M.-A. Lemburg -# - Add a table prefix, to ensure namespace collisions can always be avoided -# -# Revision 1.7 2003/02/26 23:33:37 zenzen -# Break out DDL into helper functions, as per request by David Rushby -# -# Revision 1.6 2003/02/21 03:04:33 zenzen -# Stuff from Henrik Ekelund: -# added test_None -# added test_nextset & hooks -# -# Revision 1.5 2003/02/17 22:08:43 zenzen -# Implement suggestions and code from Henrik Eklund - test that cursor.arraysize -# defaults to 1 & generic cursor.callproc test added -# -# Revision 1.4 2003/02/15 00:16:33 zenzen -# Changes, as per suggestions and bug reports by M.-A. Lemburg, -# Matthew T. Kromer, Federico Di Gregorio and Daniel Dittmar -# - Class renamed -# - Now a subclass of TestCase, to avoid requiring the driver stub -# to use multiple inheritance -# - Reversed the polarity of buggy test in test_description -# - Test exception heirarchy correctly -# - self.populate is now self._populate(), so if a driver stub -# overrides self.ddl1 this change propogates -# - VARCHAR columns now have a width, which will hopefully make the -# DDL even more portible (this will be reversed if it causes more problems) -# - cursor.rowcount being checked after various execute and fetchXXX methods -# - Check for fetchall and fetchmany returning empty lists after results -# are exhausted (already checking for empty lists if select retrieved -# nothing -# - Fix bugs in test_setoutputsize_basic and test_setinputsizes -# - -class DatabaseAPI20Test(unittest.TestCase): - ''' Test a database self.driver for DB API 2.0 compatibility. - This implementation tests Gadfly, but the TestCase - is structured so that other self.drivers can subclass this - test case to ensure compiliance with the DB-API. It is - expected that this TestCase may be expanded in the future - if ambiguities or edge conditions are discovered. - - The 'Optional Extensions' are not yet being tested. - - self.drivers should subclass this test, overriding setUp, tearDown, - self.driver, connect_args and connect_kw_args. Class specification - should be as follows: - - import dbapi20 - class mytest(dbapi20.DatabaseAPI20Test): - [...] - - Don't 'import DatabaseAPI20Test from dbapi20', or you will - confuse the unit tester - just 'import dbapi20'. - ''' - - # The self.driver module. This should be the module where the 'connect' - # method is to be found - driver = None - connect_args = () # List of arguments to pass to connect - connect_kw_args = {} # Keyword arguments for connect - table_prefix = 'dbapi20test_' # If you need to specify a prefix for tables - - ddl1 = 'create table %sbooze (name varchar(20))' % table_prefix - ddl2 = 'create table %sbarflys (name varchar(20))' % table_prefix - xddl1 = 'drop table %sbooze' % table_prefix - xddl2 = 'drop table %sbarflys' % table_prefix - - lowerfunc = 'lower' # Name of stored procedure to convert string->lowercase - - # Some drivers may need to override these helpers, for example adding - # a 'commit' after the execute. - def executeDDL1(self,cursor): - cursor.execute(self.ddl1) - - def executeDDL2(self,cursor): - cursor.execute(self.ddl2) - - def setUp(self): - ''' self.drivers should override this method to perform required setup - if any is necessary, such as creating the database. - ''' - pass - - def tearDown(self): - ''' self.drivers should override this method to perform required cleanup - if any is necessary, such as deleting the test database. - The default drops the tables that may be created. - ''' - con = self._connect() - try: - cur = con.cursor() - for ddl in (self.xddl1,self.xddl2): - try: - cur.execute(ddl) - con.commit() - except self.driver.Error: - # Assume table didn't exist. Other tests will check if - # execute is busted. - pass - finally: - con.close() - - def _connect(self): - try: - return self.driver.connect( - *self.connect_args,**self.connect_kw_args - ) - except AttributeError: - self.fail("No connect method found in self.driver module") - - def test_connect(self): - con = self._connect() - con.close() - - def test_apilevel(self): - try: - # Must exist - apilevel = self.driver.apilevel - # Must equal 2.0 - self.assertEqual(apilevel,'2.0') - except AttributeError: - self.fail("Driver doesn't define apilevel") - - def test_threadsafety(self): - try: - # Must exist - threadsafety = self.driver.threadsafety - # Must be a valid value - self.assertTrue(threadsafety in (0,1,2,3)) - except AttributeError: - self.fail("Driver doesn't define threadsafety") - - def test_paramstyle(self): - try: - # Must exist - paramstyle = self.driver.paramstyle - # Must be a valid value - self.assertTrue(paramstyle in ( - 'qmark','numeric','named','format','pyformat' - )) - except AttributeError: - self.fail("Driver doesn't define paramstyle") - - def test_Exceptions(self): - # Make sure required exceptions exist, and are in the - # defined heirarchy. - self.assertTrue(issubclass(self.driver.Warning,StandardError)) - self.assertTrue(issubclass(self.driver.Error,StandardError)) - self.assertTrue( - issubclass(self.driver.InterfaceError,self.driver.Error) - ) - self.assertTrue( - issubclass(self.driver.DatabaseError,self.driver.Error) - ) - self.assertTrue( - issubclass(self.driver.OperationalError,self.driver.Error) - ) - self.assertTrue( - issubclass(self.driver.IntegrityError,self.driver.Error) - ) - self.assertTrue( - issubclass(self.driver.InternalError,self.driver.Error) - ) - self.assertTrue( - issubclass(self.driver.ProgrammingError,self.driver.Error) - ) - self.assertTrue( - issubclass(self.driver.NotSupportedError,self.driver.Error) - ) - - def test_ExceptionsAsConnectionAttributes(self): - # OPTIONAL EXTENSION - # Test for the optional DB API 2.0 extension, where the exceptions - # are exposed as attributes on the Connection object - # I figure this optional extension will be implemented by any - # driver author who is using this test suite, so it is enabled - # by default. - con = self._connect() - drv = self.driver - self.assertTrue(con.Warning is drv.Warning) - self.assertTrue(con.Error is drv.Error) - self.assertTrue(con.InterfaceError is drv.InterfaceError) - self.assertTrue(con.DatabaseError is drv.DatabaseError) - self.assertTrue(con.OperationalError is drv.OperationalError) - self.assertTrue(con.IntegrityError is drv.IntegrityError) - self.assertTrue(con.InternalError is drv.InternalError) - self.assertTrue(con.ProgrammingError is drv.ProgrammingError) - self.assertTrue(con.NotSupportedError is drv.NotSupportedError) - - - def test_commit(self): - con = self._connect() - try: - # Commit must work, even if it doesn't do anything - con.commit() - finally: - con.close() - - def test_rollback(self): - con = self._connect() - # If rollback is defined, it should either work or throw - # the documented exception - if hasattr(con,'rollback'): - try: - con.rollback() - except self.driver.NotSupportedError: - pass - - def test_cursor(self): - con = self._connect() - try: - cur = con.cursor() - finally: - con.close() - - def test_cursor_isolation(self): - con = self._connect() - try: - # Make sure cursors created from the same connection have - # the documented transaction isolation level - cur1 = con.cursor() - cur2 = con.cursor() - self.executeDDL1(cur1) - cur1.execute("insert into %sbooze values ('Victoria Bitter')" % ( - self.table_prefix - )) - cur2.execute("select name from %sbooze" % self.table_prefix) - booze = cur2.fetchall() - self.assertEqual(len(booze),1) - self.assertEqual(len(booze[0]),1) - self.assertEqual(booze[0][0],'Victoria Bitter') - finally: - con.close() - - def test_description(self): - con = self._connect() - try: - cur = con.cursor() - self.executeDDL1(cur) - self.assertEqual(cur.description,None, - 'cursor.description should be none after executing a ' - 'statement that can return no rows (such as DDL)' - ) - cur.execute('select name from %sbooze' % self.table_prefix) - self.assertEqual(len(cur.description),1, - 'cursor.description describes too many columns' - ) - self.assertEqual(len(cur.description[0]),7, - 'cursor.description[x] tuples must have 7 elements' - ) - self.assertEqual(cur.description[0][0].lower(),'name', - 'cursor.description[x][0] must return column name' - ) - self.assertEqual(cur.description[0][1],self.driver.STRING, - 'cursor.description[x][1] must return column type. Got %r' - % cur.description[0][1] - ) - - # Make sure self.description gets reset - self.executeDDL2(cur) - self.assertEqual(cur.description,None, - 'cursor.description not being set to None when executing ' - 'no-result statements (eg. DDL)' - ) - finally: - con.close() - - def test_rowcount(self): - con = self._connect() - try: - cur = con.cursor() - self.executeDDL1(cur) - self.assertEqual(cur.rowcount,-1, - 'cursor.rowcount should be -1 after executing no-result ' - 'statements' - ) - cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( - self.table_prefix - )) - self.assertTrue(cur.rowcount in (-1,1), - 'cursor.rowcount should == number or rows inserted, or ' - 'set to -1 after executing an insert statement' - ) - cur.execute("select name from %sbooze" % self.table_prefix) - self.assertTrue(cur.rowcount in (-1,1), - 'cursor.rowcount should == number of rows returned, or ' - 'set to -1 after executing a select statement' - ) - self.executeDDL2(cur) - self.assertEqual(cur.rowcount,-1, - 'cursor.rowcount not being reset to -1 after executing ' - 'no-result statements' - ) - finally: - con.close() - - lower_func = 'lower' - def test_callproc(self): - con = self._connect() - try: - cur = con.cursor() - if self.lower_func and hasattr(cur,'callproc'): - r = cur.callproc(self.lower_func,('FOO',)) - self.assertEqual(len(r),1) - self.assertEqual(r[0],'FOO') - r = cur.fetchall() - self.assertEqual(len(r),1,'callproc produced no result set') - self.assertEqual(len(r[0]),1, - 'callproc produced invalid result set' - ) - self.assertEqual(r[0][0],'foo', - 'callproc produced invalid results' - ) - finally: - con.close() - - def test_close(self): - con = self._connect() - try: - cur = con.cursor() - finally: - con.close() - - # cursor.execute should raise an Error if called after connection - # closed - self.assertRaises(self.driver.Error,self.executeDDL1,cur) - - # connection.commit should raise an Error if called after connection' - # closed.' - self.assertRaises(self.driver.Error,con.commit) - - # connection.close should raise an Error if called more than once - self.assertRaises(self.driver.Error,con.close) - - def test_execute(self): - con = self._connect() - try: - cur = con.cursor() - self._paraminsert(cur) - finally: - con.close() - - def _paraminsert(self,cur): - self.executeDDL1(cur) - cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( - self.table_prefix - )) - self.assertTrue(cur.rowcount in (-1,1)) - - if self.driver.paramstyle == 'qmark': - cur.execute( - 'insert into %sbooze values (?)' % self.table_prefix, - ("Cooper's",) - ) - elif self.driver.paramstyle == 'numeric': - cur.execute( - 'insert into %sbooze values (:1)' % self.table_prefix, - ("Cooper's",) - ) - elif self.driver.paramstyle == 'named': - cur.execute( - 'insert into %sbooze values (:beer)' % self.table_prefix, - {'beer':"Cooper's"} - ) - elif self.driver.paramstyle == 'format': - cur.execute( - 'insert into %sbooze values (%%s)' % self.table_prefix, - ("Cooper's",) - ) - elif self.driver.paramstyle == 'pyformat': - cur.execute( - 'insert into %sbooze values (%%(beer)s)' % self.table_prefix, - {'beer':"Cooper's"} - ) - else: - self.fail('Invalid paramstyle') - self.assertTrue(cur.rowcount in (-1,1)) - - cur.execute('select name from %sbooze' % self.table_prefix) - res = cur.fetchall() - self.assertEqual(len(res),2,'cursor.fetchall returned too few rows') - beers = [res[0][0],res[1][0]] - beers.sort() - self.assertEqual(beers[0],"Cooper's", - 'cursor.fetchall retrieved incorrect data, or data inserted ' - 'incorrectly' - ) - self.assertEqual(beers[1],"Victoria Bitter", - 'cursor.fetchall retrieved incorrect data, or data inserted ' - 'incorrectly' - ) - - def test_executemany(self): - con = self._connect() - try: - cur = con.cursor() - self.executeDDL1(cur) - largs = [ ("Cooper's",) , ("Boag's",) ] - margs = [ {'beer': "Cooper's"}, {'beer': "Boag's"} ] - if self.driver.paramstyle == 'qmark': - cur.executemany( - 'insert into %sbooze values (?)' % self.table_prefix, - largs - ) - elif self.driver.paramstyle == 'numeric': - cur.executemany( - 'insert into %sbooze values (:1)' % self.table_prefix, - largs - ) - elif self.driver.paramstyle == 'named': - cur.executemany( - 'insert into %sbooze values (:beer)' % self.table_prefix, - margs - ) - elif self.driver.paramstyle == 'format': - cur.executemany( - 'insert into %sbooze values (%%s)' % self.table_prefix, - largs - ) - elif self.driver.paramstyle == 'pyformat': - cur.executemany( - 'insert into %sbooze values (%%(beer)s)' % ( - self.table_prefix - ), - margs - ) - else: - self.fail('Unknown paramstyle') - self.assertTrue(cur.rowcount in (-1,2), - 'insert using cursor.executemany set cursor.rowcount to ' - 'incorrect value %r' % cur.rowcount - ) - cur.execute('select name from %sbooze' % self.table_prefix) - res = cur.fetchall() - self.assertEqual(len(res),2, - 'cursor.fetchall retrieved incorrect number of rows' - ) - beers = [res[0][0],res[1][0]] - beers.sort() - self.assertEqual(beers[0],"Boag's",'incorrect data retrieved') - self.assertEqual(beers[1],"Cooper's",'incorrect data retrieved') - finally: - con.close() - - def test_fetchone(self): - con = self._connect() - try: - cur = con.cursor() - - # cursor.fetchone should raise an Error if called before - # executing a select-type query - self.assertRaises(self.driver.Error,cur.fetchone) - - # cursor.fetchone should raise an Error if called after - # executing a query that cannnot return rows - self.executeDDL1(cur) - self.assertRaises(self.driver.Error,cur.fetchone) - - cur.execute('select name from %sbooze' % self.table_prefix) - self.assertEqual(cur.fetchone(),None, - 'cursor.fetchone should return None if a query retrieves ' - 'no rows' - ) - self.assertTrue(cur.rowcount in (-1,0)) - - # cursor.fetchone should raise an Error if called after - # executing a query that cannnot return rows - cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( - self.table_prefix - )) - self.assertRaises(self.driver.Error,cur.fetchone) - - cur.execute('select name from %sbooze' % self.table_prefix) - r = cur.fetchone() - self.assertEqual(len(r),1, - 'cursor.fetchone should have retrieved a single row' - ) - self.assertEqual(r[0],'Victoria Bitter', - 'cursor.fetchone retrieved incorrect data' - ) - self.assertEqual(cur.fetchone(),None, - 'cursor.fetchone should return None if no more rows available' - ) - self.assertTrue(cur.rowcount in (-1,1)) - finally: - con.close() - - samples = [ - 'Carlton Cold', - 'Carlton Draft', - 'Mountain Goat', - 'Redback', - 'Victoria Bitter', - 'XXXX' - ] - - def _populate(self): - ''' Return a list of sql commands to setup the DB for the fetch - tests. - ''' - populate = [ - "insert into %sbooze values ('%s')" % (self.table_prefix,s) - for s in self.samples - ] - return populate - - def test_fetchmany(self): - con = self._connect() - try: - cur = con.cursor() - - # cursor.fetchmany should raise an Error if called without - #issuing a query - self.assertRaises(self.driver.Error,cur.fetchmany,4) - - self.executeDDL1(cur) - for sql in self._populate(): - cur.execute(sql) - - cur.execute('select name from %sbooze' % self.table_prefix) - r = cur.fetchmany() - self.assertEqual(len(r),1, - 'cursor.fetchmany retrieved incorrect number of rows, ' - 'default of arraysize is one.' - ) - cur.arraysize=10 - r = cur.fetchmany(3) # Should get 3 rows - self.assertEqual(len(r),3, - 'cursor.fetchmany retrieved incorrect number of rows' - ) - r = cur.fetchmany(4) # Should get 2 more - self.assertEqual(len(r),2, - 'cursor.fetchmany retrieved incorrect number of rows' - ) - r = cur.fetchmany(4) # Should be an empty sequence - self.assertEqual(len(r),0, - 'cursor.fetchmany should return an empty sequence after ' - 'results are exhausted' - ) - self.assertTrue(cur.rowcount in (-1,6)) - - # Same as above, using cursor.arraysize - cur.arraysize=4 - cur.execute('select name from %sbooze' % self.table_prefix) - r = cur.fetchmany() # Should get 4 rows - self.assertEqual(len(r),4, - 'cursor.arraysize not being honoured by fetchmany' - ) - r = cur.fetchmany() # Should get 2 more - self.assertEqual(len(r),2) - r = cur.fetchmany() # Should be an empty sequence - self.assertEqual(len(r),0) - self.assertTrue(cur.rowcount in (-1,6)) - - cur.arraysize=6 - cur.execute('select name from %sbooze' % self.table_prefix) - rows = cur.fetchmany() # Should get all rows - self.assertTrue(cur.rowcount in (-1,6)) - self.assertEqual(len(rows),6) - self.assertEqual(len(rows),6) - rows = [r[0] for r in rows] - rows.sort() - - # Make sure we get the right data back out - for i in range(0,6): - self.assertEqual(rows[i],self.samples[i], - 'incorrect data retrieved by cursor.fetchmany' - ) - - rows = cur.fetchmany() # Should return an empty list - self.assertEqual(len(rows),0, - 'cursor.fetchmany should return an empty sequence if ' - 'called after the whole result set has been fetched' - ) - self.assertTrue(cur.rowcount in (-1,6)) - - self.executeDDL2(cur) - cur.execute('select name from %sbarflys' % self.table_prefix) - r = cur.fetchmany() # Should get empty sequence - self.assertEqual(len(r),0, - 'cursor.fetchmany should return an empty sequence if ' - 'query retrieved no rows' - ) - self.assertTrue(cur.rowcount in (-1,0)) - - finally: - con.close() - - def test_fetchall(self): - con = self._connect() - try: - cur = con.cursor() - # cursor.fetchall should raise an Error if called - # without executing a query that may return rows (such - # as a select) - self.assertRaises(self.driver.Error, cur.fetchall) - - self.executeDDL1(cur) - for sql in self._populate(): - cur.execute(sql) - - # cursor.fetchall should raise an Error if called - # after executing a a statement that cannot return rows - self.assertRaises(self.driver.Error,cur.fetchall) - - cur.execute('select name from %sbooze' % self.table_prefix) - rows = cur.fetchall() - self.assertTrue(cur.rowcount in (-1,len(self.samples))) - self.assertEqual(len(rows),len(self.samples), - 'cursor.fetchall did not retrieve all rows' - ) - rows = [r[0] for r in rows] - rows.sort() - for i in range(0,len(self.samples)): - self.assertEqual(rows[i],self.samples[i], - 'cursor.fetchall retrieved incorrect rows' - ) - rows = cur.fetchall() - self.assertEqual( - len(rows),0, - 'cursor.fetchall should return an empty list if called ' - 'after the whole result set has been fetched' - ) - self.assertTrue(cur.rowcount in (-1,len(self.samples))) - - self.executeDDL2(cur) - cur.execute('select name from %sbarflys' % self.table_prefix) - rows = cur.fetchall() - self.assertTrue(cur.rowcount in (-1,0)) - self.assertEqual(len(rows),0, - 'cursor.fetchall should return an empty list if ' - 'a select query returns no rows' - ) - - finally: - con.close() - - def test_mixedfetch(self): - con = self._connect() - try: - cur = con.cursor() - self.executeDDL1(cur) - for sql in self._populate(): - cur.execute(sql) - - cur.execute('select name from %sbooze' % self.table_prefix) - rows1 = cur.fetchone() - rows23 = cur.fetchmany(2) - rows4 = cur.fetchone() - rows56 = cur.fetchall() - self.assertTrue(cur.rowcount in (-1,6)) - self.assertEqual(len(rows23),2, - 'fetchmany returned incorrect number of rows' - ) - self.assertEqual(len(rows56),2, - 'fetchall returned incorrect number of rows' - ) - - rows = [rows1[0]] - rows.extend([rows23[0][0],rows23[1][0]]) - rows.append(rows4[0]) - rows.extend([rows56[0][0],rows56[1][0]]) - rows.sort() - for i in range(0,len(self.samples)): - self.assertEqual(rows[i],self.samples[i], - 'incorrect data retrieved or inserted' - ) - finally: - con.close() - - def help_nextset_setUp(self,cur): - ''' Should create a procedure called deleteme - that returns two result sets, first the - number of rows in booze then "name from booze" - ''' - raise NotImplementedError('Helper not implemented') - #sql=""" - # create procedure deleteme as - # begin - # select count(*) from booze - # select name from booze - # end - #""" - #cur.execute(sql) - - def help_nextset_tearDown(self,cur): - 'If cleaning up is needed after nextSetTest' - raise NotImplementedError('Helper not implemented') - #cur.execute("drop procedure deleteme") - - def test_nextset(self): - con = self._connect() - try: - cur = con.cursor() - if not hasattr(cur,'nextset'): - return - - try: - self.executeDDL1(cur) - sql=self._populate() - for sql in self._populate(): - cur.execute(sql) - - self.help_nextset_setUp(cur) - - cur.callproc('deleteme') - numberofrows=cur.fetchone() - assert numberofrows[0]== len(self.samples) - assert cur.nextset() - names=cur.fetchall() - assert len(names) == len(self.samples) - s=cur.nextset() - assert s == None,'No more return sets, should return None' - finally: - self.help_nextset_tearDown(cur) - - finally: - con.close() - - def test_nextset(self): - raise NotImplementedError('Drivers need to override this test') - - def test_arraysize(self): - # Not much here - rest of the tests for this are in test_fetchmany - con = self._connect() - try: - cur = con.cursor() - self.assertTrue(hasattr(cur,'arraysize'), - 'cursor.arraysize must be defined' - ) - finally: - con.close() - - def test_setinputsizes(self): - con = self._connect() - try: - cur = con.cursor() - cur.setinputsizes( (25,) ) - self._paraminsert(cur) # Make sure cursor still works - finally: - con.close() - - def test_setoutputsize_basic(self): - # Basic test is to make sure setoutputsize doesn't blow up - con = self._connect() - try: - cur = con.cursor() - cur.setoutputsize(1000) - cur.setoutputsize(2000,0) - self._paraminsert(cur) # Make sure the cursor still works - finally: - con.close() - - def test_setoutputsize(self): - # Real test for setoutputsize is driver dependant - raise NotImplementedError('Driver need to override this test') - - def test_None(self): - con = self._connect() - try: - cur = con.cursor() - self.executeDDL1(cur) - cur.execute('insert into %sbooze values (NULL)' % self.table_prefix) - cur.execute('select name from %sbooze' % self.table_prefix) - r = cur.fetchall() - self.assertEqual(len(r),1) - self.assertEqual(len(r[0]),1) - self.assertEqual(r[0][0],None,'NULL value not returned as None') - finally: - con.close() - - def test_Date(self): - d1 = self.driver.Date(2002,12,25) - d2 = self.driver.DateFromTicks(time.mktime((2002,12,25,0,0,0,0,0,0))) - # Can we assume this? API doesn't specify, but it seems implied - # self.assertEqual(str(d1),str(d2)) - - def test_Time(self): - t1 = self.driver.Time(13,45,30) - t2 = self.driver.TimeFromTicks(time.mktime((2001,1,1,13,45,30,0,0,0))) - # Can we assume this? API doesn't specify, but it seems implied - # self.assertEqual(str(t1),str(t2)) - - def test_Timestamp(self): - t1 = self.driver.Timestamp(2002,12,25,13,45,30) - t2 = self.driver.TimestampFromTicks( - time.mktime((2002,12,25,13,45,30,0,0,0)) - ) - # Can we assume this? API doesn't specify, but it seems implied - # self.assertEqual(str(t1),str(t2)) - - def test_Binary(self): - b = self.driver.Binary('Something') - b = self.driver.Binary('') - - def test_STRING(self): - self.assertTrue(hasattr(self.driver,'STRING'), - 'module.STRING must be defined' - ) - - def test_BINARY(self): - self.assertTrue(hasattr(self.driver,'BINARY'), - 'module.BINARY must be defined.' - ) - - def test_NUMBER(self): - self.assertTrue(hasattr(self.driver,'NUMBER'), - 'module.NUMBER must be defined.' - ) - - def test_DATETIME(self): - self.assertTrue(hasattr(self.driver,'DATETIME'), - 'module.DATETIME must be defined.' - ) - - def test_ROWID(self): - self.assertTrue(hasattr(self.driver,'ROWID'), - 'module.ROWID must be defined.' - ) - diff --git a/MySQLdb/tests/default.cnf b/MySQLdb/tests/default.cnf deleted file mode 100644 index 2aeda7c..0000000 --- a/MySQLdb/tests/default.cnf +++ /dev/null @@ -1,10 +0,0 @@ -# To create your own custom version of this file, read -# http://dev.mysql.com/doc/refman/5.1/en/option-files.html -# and set TESTDB in your environment to the name of the file - -[MySQLdb-tests] -host = 127.0.0.1 -user = test -database = test -#password = -default-character-set = utf8 diff --git a/MySQLdb/tests/test_MySQLdb_capabilities.py b/MySQLdb/tests/test_MySQLdb_capabilities.py deleted file mode 100644 index 60bbfad..0000000 --- a/MySQLdb/tests/test_MySQLdb_capabilities.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -import capabilities -import unittest -import MySQLdb -import warnings - -warnings.filterwarnings('error') - -class test_MySQLdb(capabilities.DatabaseTest): - - db_module = MySQLdb - connect_args = () - connect_kwargs = dict(use_unicode=True, sql_mode="ANSI,STRICT_TRANS_TABLES,TRADITIONAL") - create_table_extra = "ENGINE=INNODB CHARACTER SET UTF8" - leak_test = False - - def quote_identifier(self, ident): - return "`%s`" % ident - - def test_TIME(self): - from datetime import timedelta - def generator(row,col): - return timedelta(0, row*8000) - self.check_data_integrity( - ('col1 TIME',), - generator) - - def test_TINYINT(self): - # Number data - def generator(row,col): - v = (row*row) % 256 - if v > 127: - v = v-256 - return v - self.check_data_integrity( - ('col1 TINYINT',), - generator) - - def test_stored_procedures(self): - db = self.connection - c = self.cursor - self.create_table(('pos INT', 'tree CHAR(20)')) - c.executemany("INSERT INTO %s (pos,tree) VALUES (%%s,%%s)" % self.table, - list(enumerate('ash birch cedar larch pine'.split()))) - db.commit() - - c.execute(""" - CREATE PROCEDURE test_sp(IN t VARCHAR(255)) - BEGIN - SELECT pos FROM %s WHERE tree = t; - END - """ % self.table) - db.commit() - - c.callproc('test_sp', ('larch',)) - rows = c.fetchall() - self.assertEquals(len(rows), 1) - self.assertEquals(rows[0][0], 3) - c.nextset() - - c.execute("DROP PROCEDURE test_sp") - c.execute('drop table %s' % (self.table)) - - def test_small_CHAR(self): - # Character data - def generator(row,col): - i = (row*col+62)%256 - if i == 62: return '' - if i == 63: return None - return chr(i) - self.check_data_integrity( - ('col1 char(1)','col2 char(1)'), - generator) - - def test_bug_2671682(self): - from MySQLdb.constants import ER - try: - self.cursor.execute("describe some_non_existent_table"); - except self.connection.ProgrammingError, msg: - self.assertTrue(msg[0] == ER.NO_SUCH_TABLE) - - def test_bug_3514287(self): - c = self.cursor - try: - c.execute("""create table bug_3541287 ( - c1 CHAR(10), - t1 TIMESTAMP)""") - c.execute("insert into bug_3541287 (c1,t1) values (%s, NOW())", - ("blah",)) - finally: - c.execute("drop table if exists bug_3541287") - - def test_ping(self): - self.connection.ping() - - -if __name__ == '__main__': - if test_MySQLdb.leak_test: - import gc - gc.enable() - gc.set_debug(gc.DEBUG_LEAK) - unittest.main() diff --git a/MySQLdb/tests/test_MySQLdb_dbapi20.py b/MySQLdb/tests/test_MySQLdb_dbapi20.py deleted file mode 100644 index 44830e0..0000000 --- a/MySQLdb/tests/test_MySQLdb_dbapi20.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python -import dbapi20 -import unittest -import MySQLdb -from configdb import connection_kwargs - -class test_MySQLdb(dbapi20.DatabaseAPI20Test): - driver = MySQLdb - connect_args = () - connect_kw_args = connection_kwargs(dict(sql_mode="ANSI,STRICT_TRANS_TABLES,TRADITIONAL")) - - def test_setoutputsize(self): pass - def test_setoutputsize_basic(self): pass - def test_nextset(self): pass - - """The tests on fetchone and fetchall and rowcount bogusly - test for an exception if the statement cannot return a - result set. MySQL always returns a result set; it's just that - some things return empty result sets.""" - - def test_fetchall(self): - con = self._connect() - try: - cur = con.cursor() - # cursor.fetchall should raise an Error if called - # without executing a query that may return rows (such - # as a select) - self.assertRaises(self.driver.Error, cur.fetchall) - - self.executeDDL1(cur) - for sql in self._populate(): - cur.execute(sql) - - # cursor.fetchall should raise an Error if called - # after executing a a statement that cannot return rows -## self.assertRaises(self.driver.Error,cur.fetchall) - - cur.execute('select name from %sbooze' % self.table_prefix) - rows = cur.fetchall() - self.assertTrue(cur.rowcount in (-1,len(self.samples))) - self.assertEqual(len(rows),len(self.samples), - 'cursor.fetchall did not retrieve all rows' - ) - rows = [r[0] for r in rows] - rows.sort() - for i in range(0,len(self.samples)): - self.assertEqual(rows[i],self.samples[i], - 'cursor.fetchall retrieved incorrect rows' - ) - rows = cur.fetchall() - self.assertEqual( - len(rows),0, - 'cursor.fetchall should return an empty list if called ' - 'after the whole result set has been fetched' - ) - self.assertTrue(cur.rowcount in (-1,len(self.samples))) - - self.executeDDL2(cur) - cur.execute('select name from %sbarflys' % self.table_prefix) - rows = cur.fetchall() - self.assertTrue(cur.rowcount in (-1,0)) - self.assertEqual(len(rows),0, - 'cursor.fetchall should return an empty list if ' - 'a select query returns no rows' - ) - - finally: - con.close() - - def test_fetchone(self): - con = self._connect() - try: - cur = con.cursor() - - # cursor.fetchone should raise an Error if called before - # executing a select-type query - self.assertRaises(self.driver.Error,cur.fetchone) - - # cursor.fetchone should raise an Error if called after - # executing a query that cannnot return rows - self.executeDDL1(cur) -## self.assertRaises(self.driver.Error,cur.fetchone) - - cur.execute('select name from %sbooze' % self.table_prefix) - self.assertEqual(cur.fetchone(),None, - 'cursor.fetchone should return None if a query retrieves ' - 'no rows' - ) - self.assertTrue(cur.rowcount in (-1,0)) - - # cursor.fetchone should raise an Error if called after - # executing a query that cannnot return rows - cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( - self.table_prefix - )) -## self.assertRaises(self.driver.Error,cur.fetchone) - - cur.execute('select name from %sbooze' % self.table_prefix) - r = cur.fetchone() - self.assertEqual(len(r),1, - 'cursor.fetchone should have retrieved a single row' - ) - self.assertEqual(r[0],'Victoria Bitter', - 'cursor.fetchone retrieved incorrect data' - ) -## self.assertEqual(cur.fetchone(),None, -## 'cursor.fetchone should return None if no more rows available' -## ) - self.assertTrue(cur.rowcount in (-1,1)) - finally: - con.close() - - # Same complaint as for fetchall and fetchone - def test_rowcount(self): - con = self._connect() - try: - cur = con.cursor() - self.executeDDL1(cur) -## self.assertEqual(cur.rowcount,-1, -## 'cursor.rowcount should be -1 after executing no-result ' -## 'statements' -## ) - cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( - self.table_prefix - )) -## self.assertTrue(cur.rowcount in (-1,1), -## 'cursor.rowcount should == number or rows inserted, or ' -## 'set to -1 after executing an insert statement' -## ) - cur.execute("select name from %sbooze" % self.table_prefix) - self.assertTrue(cur.rowcount in (-1,1), - 'cursor.rowcount should == number of rows returned, or ' - 'set to -1 after executing a select statement' - ) - self.executeDDL2(cur) -## self.assertEqual(cur.rowcount,-1, -## 'cursor.rowcount not being reset to -1 after executing ' -## 'no-result statements' -## ) - finally: - con.close() - - def test_callproc(self): - pass # performed in test_MySQL_capabilities - - def help_nextset_setUp(self,cur): - ''' Should create a procedure called deleteme - that returns two result sets, first the - number of rows in booze then "name from booze" - ''' - sql=""" - create procedure deleteme() - begin - select count(*) from %(tp)sbooze; - select name from %(tp)sbooze; - end - """ % dict(tp=self.table_prefix) - cur.execute(sql) - - def help_nextset_tearDown(self,cur): - 'If cleaning up is needed after nextSetTest' - cur.execute("drop procedure deleteme") - - def test_nextset(self): - from warnings import warn - con = self._connect() - try: - cur = con.cursor() - if not hasattr(cur,'nextset'): - return - - try: - self.executeDDL1(cur) - sql=self._populate() - for sql in self._populate(): - cur.execute(sql) - - self.help_nextset_setUp(cur) - - cur.callproc('deleteme') - numberofrows=cur.fetchone() - assert numberofrows[0]== len(self.samples) - assert cur.nextset() - names=cur.fetchall() - assert len(names) == len(self.samples) - s=cur.nextset() - if s: - empty = cur.fetchall() - self.assertEquals(len(empty), 0, - "non-empty result set after other result sets") - #warn("Incompatibility: MySQL returns an empty result set for the CALL itself", - # Warning) - #assert s == None,'No more return sets, should return None' - finally: - self.help_nextset_tearDown(cur) - - finally: - con.close() - - -if __name__ == '__main__': - unittest.main() diff --git a/MySQLdb/tests/test_MySQLdb_nonstandard.py b/MySQLdb/tests/test_MySQLdb_nonstandard.py deleted file mode 100644 index 92fcbdc..0000000 --- a/MySQLdb/tests/test_MySQLdb_nonstandard.py +++ /dev/null @@ -1,86 +0,0 @@ -import unittest - -import _mysql -import MySQLdb -from MySQLdb.constants import FIELD_TYPE -from configdb import connection_factory - - -class TestDBAPISet(unittest.TestCase): - def test_set_equality(self): - self.assertTrue(MySQLdb.STRING == MySQLdb.STRING) - - def test_set_inequality(self): - self.assertTrue(MySQLdb.STRING != MySQLdb.NUMBER) - - def test_set_equality_membership(self): - self.assertTrue(FIELD_TYPE.VAR_STRING == MySQLdb.STRING) - - def test_set_inequality_membership(self): - self.assertTrue(FIELD_TYPE.DATE != MySQLdb.STRING) - - -class CoreModule(unittest.TestCase): - """Core _mysql module features.""" - - def test_NULL(self): - """Should have a NULL constant.""" - self.assertEqual(_mysql.NULL, 'NULL') - - def test_version(self): - """Version information sanity.""" - self.assertTrue(isinstance(_mysql.__version__, str)) - - self.assertTrue(isinstance(_mysql.version_info, tuple)) - self.assertEqual(len(_mysql.version_info), 5) - - def test_client_info(self): - self.assertTrue(isinstance(_mysql.get_client_info(), str)) - - def test_thread_safe(self): - self.assertTrue(isinstance(_mysql.thread_safe(), int)) - - -class CoreAPI(unittest.TestCase): - """Test _mysql interaction internals.""" - - def setUp(self): - self.conn = connection_factory(use_unicode=True) - - def tearDown(self): - self.conn.close() - - def test_thread_id(self): - tid = self.conn.thread_id() - self.assertTrue(isinstance(tid, int), - "thread_id didn't return an int.") - - self.assertRaises(TypeError, self.conn.thread_id, ('evil',), - "thread_id shouldn't accept arguments.") - - def test_affected_rows(self): - self.assertEquals(self.conn.affected_rows(), 0, - "Should return 0 before we do anything.") - - - #def test_debug(self): - ## FIXME Only actually tests if you lack SUPER - #self.assertRaises(MySQLdb.OperationalError, - #self.conn.dump_debug_info) - - def test_charset_name(self): - self.assertTrue(isinstance(self.conn.character_set_name(), str), - "Should return a string.") - - def test_host_info(self): - self.assertTrue(isinstance(self.conn.get_host_info(), str), - "Should return a string.") - - def test_proto_info(self): - self.assertTrue(isinstance(self.conn.get_proto_info(), int), - "Should return an int.") - - def test_server_info(self): - self.assertTrue(isinstance(self.conn.get_server_info(), str), - "Should return an str.") - diff --git a/MySQLdb/tests/travis.cnf b/MySQLdb/tests/travis.cnf deleted file mode 100644 index e78f52d..0000000 --- a/MySQLdb/tests/travis.cnf +++ /dev/null @@ -1,10 +0,0 @@ -# To create your own custom version of this file, read -# http://dev.mysql.com/doc/refman/5.1/en/option-files.html -# and set TESTDB in your environment to the name of the file - -[MySQLdb-tests] -host = 127.0.0.1 -user = root -database = mysqldb_test -#password = -default-character-set = utf8 diff --git a/MySQLdb/times.py b/MySQLdb/times.py new file mode 100644 index 0000000..bc92eb4 --- /dev/null +++ b/MySQLdb/times.py @@ -0,0 +1,111 @@ +"""times module + +This module provides some Date and Time classes for dealing with MySQL data. + +Use Python datetime module to handle date and time columns.""" + +import math +from time import localtime +from datetime import date, datetime, time, timedelta +from _mysql import string_literal + +Date = date +Time = time +TimeDelta = timedelta +Timestamp = datetime + +DateTimeDeltaType = timedelta +DateTimeType = datetime + +def DateFromTicks(ticks): + """Convert UNIX ticks into a date instance.""" + return date(*localtime(ticks)[:3]) + +def TimeFromTicks(ticks): + """Convert UNIX ticks into a time instance.""" + return time(*localtime(ticks)[3:6]) + +def TimestampFromTicks(ticks): + """Convert UNIX ticks into a datetime instance.""" + return datetime(*localtime(ticks)[:6]) + +format_TIME = format_DATE = str + +def format_TIMEDELTA(v): + seconds = int(v.seconds) % 60 + minutes = int(v.seconds / 60) % 60 + hours = int(v.seconds / 3600) % 24 + return '%d %d:%d:%d' % (v.days, hours, minutes, seconds) + +def format_TIMESTAMP(d): + return d.isoformat(" ") + + +def DateTime_or_None(s): + if ' ' in s: + sep = ' ' + elif 'T' in s: + sep = 'T' + else: + return Date_or_None(s) + + try: + d, t = s.split(sep, 1) + return datetime(*[ int(x) for x in d.split('-')+t.split(':') ]) + except (SystemExit, KeyboardInterrupt): + raise + except: + return Date_or_None(s) + +def TimeDelta_or_None(s): + try: + h, m, s = s.split(':') + h, m, s = int(h), int(m), float(s) + td = timedelta(hours=abs(h), minutes=m, seconds=int(s), + microseconds=int(math.modf(s)[0] * 1000000)) + if h < 0: + return -td + else: + return td + except ValueError: + # unpacking or int/float conversion failed + return None + +def Time_or_None(s): + try: + h, m, s = s.split(':') + h, m, s = int(h), int(m), float(s) + return time(hour=h, minute=m, second=int(s), + microsecond=int(math.modf(s)[0] * 1000000)) + except ValueError: + return None + +def Date_or_None(s): + try: + return date(*[ int(x) for x in s.split('-',2)]) + except (SystemExit, KeyboardInterrupt): + raise + except: + return None + +def DateTime2literal(d, c): + """Format a DateTime object as an ISO timestamp.""" + return string_literal(format_TIMESTAMP(d),c) + +def DateTimeDelta2literal(d, c): + """Format a DateTimeDelta object as a time.""" + return string_literal(format_TIMEDELTA(d),c) + +def mysql_timestamp_converter(s): + """Convert a MySQL TIMESTAMP to a Timestamp object.""" + # MySQL>4.1 returns TIMESTAMP in the same format as DATETIME + if s[4] == '-': return DateTime_or_None(s) + s = s + "0"*(14-len(s)) # padding + parts = map(int, filter(None, (s[:4],s[4:6],s[6:8], + s[8:10],s[10:12],s[12:14]))) + try: + return Timestamp(*parts) + except (SystemExit, KeyboardInterrupt): + raise + except: + return None -- cgit v1.2.1