diff --git a/.gitignore b/.gitignore index 7488960..02521ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,7 @@ -*.pyc -*.pyo -*.o -*.so -*.pyd -*.gz -*.zip -*.egg -*.egg-info/ -.tox/ -build/ -dist/ +# git-ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): # *.[oa] # *~ *.pyc @@ -22,6 +14,8 @@ dist/ #profiling/outputs *.log +dist +build regress.py test.py PKG-INFO diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ecf9029..0000000 --- a/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: python -python: - - "3.2" - - "2.7" - - "pypy" -install: python setup.py install -before_script: mysql -e 'create database mysqldb_test charset utf8;' -script: TESTDB=travis.cnf nosetests diff --git a/GPL-2.0 b/GPL-2.0 deleted file mode 100644 index d159169..0000000 --- a/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/HISTORY b/HISTORY index 6a567d5..4ca7e5a 100644 --- a/HISTORY +++ b/HISTORY @@ -1,193 +1,116 @@ -===================== - What's new in 1.2.4 -===================== - -final -===== - -No changes. - - -rc 1 -==== - -Fixed a dangling reference to the old types module. - - -beta 5 -====== - -Another internal fix for handling remapped character sets. - -_mysql.c was broken for the case where read_timeout was *not* available. (Issue #6) - -Documentation was converted to sphinx but there is a lot of cleanup left to do. - - -beta 4 -====== - -Added support for the MySQL read_timeout option. Contributed by -Jean Schurger (jean@schurger.org). - -Added a workaround so that the MySQL character set utf8mb4 works with Python; utf8 is substituted -on the Python side. - - -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. - +===================== + 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/MANIFEST.in b/MANIFEST.in index 54b1fd5..9a8a4d5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,14 +1,13 @@ -recursive-include doc *.rst -recursive-include tests *.py -include doc/conf.py -include MANIFEST.in -include HISTORY -include INSTALL -include README.md -include GPL-2.0 -include pymemcompat.h -include metadata.cfg -include site.cfg -include setup_common.py -include setup_posix.py -include setup_windows.py +recursive-include doc *.txt +recursive-include tests *.py +include MANIFEST.in +include MANIFEST +include ChangeLog +include HISTORY +include GPL +include pymemcompat.h +include metadata.cfg +include site.cfg +include setup_common.py +include setup_posix.py +include setup_windows.py diff --git a/MySQL_python.egg-info/SOURCES.txt b/MySQL_python.egg-info/SOURCES.txt new file mode 100644 index 0000000..8acb862 --- /dev/null +++ b/MySQL_python.egg-info/SOURCES.txt @@ -0,0 +1,42 @@ +.cvsignore +HISTORY +MANIFEST.in +README +_mysql.c +_mysql_exceptions.py +ez_setup.py +metadata.cfg +pymemcompat.h +setup.cfg +setup.py +setup_common.py +setup_posix.py +setup_windows.py +site.cfg +MySQL_python.egg-info/PKG-INFO +MySQL_python.egg-info/SOURCES.txt +MySQL_python.egg-info/dependency_links.txt +MySQL_python.egg-info/top_level.txt +MySQLdb/.cvsignore +MySQLdb/__init__.py +MySQLdb/connections.py +MySQLdb/converters.py +MySQLdb/cursors.py +MySQLdb/release.py +MySQLdb/times.py +MySQLdb/constants/.cvsignore +MySQLdb/constants/CLIENT.py +MySQLdb/constants/CR.py +MySQLdb/constants/ER.py +MySQLdb/constants/FIELD_TYPE.py +MySQLdb/constants/FLAG.py +MySQLdb/constants/REFRESH.py +MySQLdb/constants/__init__.py +doc/.cvsignore +doc/FAQ.txt +doc/MySQLdb.txt +tests/capabilities.py +tests/dbapi20.py +tests/test_MySQLdb_capabilities.py +tests/test_MySQLdb_dbapi20.py +tests/test_MySQLdb_nonstandard.py \ No newline at end of file diff --git a/MySQL_python.egg-info/dependency_links.txt b/MySQL_python.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/MySQL_python.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/MySQL_python.egg-info/top_level.txt b/MySQL_python.egg-info/top_level.txt new file mode 100644 index 0000000..47e6f18 --- /dev/null +++ b/MySQL_python.egg-info/top_level.txt @@ -0,0 +1,3 @@ +_mysql +MySQLdb +_mysql_exceptions diff --git a/MySQLdb/__init__.py b/MySQLdb/__init__.py index 8761671..5157daf 100644 --- a/MySQLdb/__init__.py +++ b/MySQLdb/__init__.py @@ -13,8 +13,8 @@ """ -__revision__ = """$Revision$"""[11:-2] -from MySQLdb.release import __version__, version_info, __author__ +__revision__ = """$Revision: 603 $"""[11:-2] +from .release import __version__, version_info, __author__ import _mysql @@ -77,7 +77,7 @@ def Binary(x): def Connect(*args, **kwargs): """Factory function for connections.Connection.""" - from MySQLdb.connections import Connection + from .connections import Connection return Connection(*args, **kwargs) connect = Connection = Connect diff --git a/MySQLdb/connections.py b/MySQLdb/connections.py index 6d5a883..e4af6b6 100644 --- a/MySQLdb/connections.py +++ b/MySQLdb/connections.py @@ -6,7 +6,7 @@ override Connection.default_cursor with a non-standard Cursor class. """ -from MySQLdb import cursors +import MySQLdb.cursors from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ DatabaseError, OperationalError, IntegrityError, InternalError, \ NotSupportedError, ProgrammingError @@ -41,14 +41,14 @@ def defaulterrorhandler(connection, cursor, errorclass, errorvalue): 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)) @@ -59,9 +59,8 @@ class Connection(_mysql.connection): """MySQL Database Connection Object""" - default_cursor = cursors.Cursor - - + default_cursor = MySQLdb.cursors.Cursor + def __init__(self, *args, **kwargs): """ @@ -71,7 +70,7 @@ def __init__(self, *args, **kwargs): host string, host to connect - + user string, user to connect as @@ -120,7 +119,7 @@ class object, used to create cursors (keyword only) 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) @@ -133,22 +132,19 @@ class object, used to create cursors (keyword only) local_infile integer, non-zero enables LOAD LOCAL INFILE; zero disables - - autocommit - If False (default), autocommit is disabled. - If True, autocommit is enabled. - If None, autocommit isn't set and server default is used. - + 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 .constants import CLIENT, FIELD_TYPE + from .converters import conversions from weakref import proxy, WeakValueDictionary + + import types kwargs2 = kwargs.copy() - + if 'conv' in kwargs: conv = kwargs['conv'] else: @@ -162,7 +158,7 @@ class object, used to create cursors (keyword only) conv2[k] = v kwargs2['conv'] = conv2 - cursorclass = kwargs2.pop('cursorclass', self.default_cursor) + self.cursorclass = kwargs2.pop('cursorclass', self.default_cursor) charset = kwargs2.pop('charset', 'utf8') sql_mode = kwargs2.pop('sql_mode', '') @@ -173,17 +169,14 @@ class object, used to create cursors (keyword only) client_flag |= CLIENT.MULTI_STATEMENTS if client_version >= (5, 0): client_flag |= CLIENT.MULTI_RESULTS - + kwargs2['client_flag'] = client_flag - # PEP-249 requires autocommit to be initially off - autocommit = kwargs2.pop('autocommit', False) - 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) @@ -196,7 +189,7 @@ def _get_bytes_literal(): def bytes_literal(u, dummy=None): return db.literal(u.decode(bytes_literal.charset)) return bytes_literal - + string_literal = _get_string_literal() self.bytes_literal = bytes_literal = _get_bytes_literal() if not charset: @@ -208,18 +201,13 @@ def bytes_literal(u, dummy=None): self.encoders[str] = string_literal self.encoders[bytes] = bytes_literal - + self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS if self._transactional: - if autocommit is not None: - self.autocommit(autocommit) + # PEP-249 requires autocommit to be initially off + self.autocommit(False) self.messages = [] - - def autocommit(self, on): - on = bool(on) - if self.get_autocommit() != on: - _mysql.connection.autocommit(self, on) - + def cursor(self, cursorclass=None): """ @@ -231,17 +219,14 @@ def cursor(self, cursorclass=None): """ return (cursorclass or self.cursorclass)(self) - def __enter__(self): - if self.get_autocommit(): - self.query("BEGIN") - return self.cursor() - + def __enter__(self): return self.cursor() + def __exit__(self, exc, value, tb): if exc: self.rollback() else: self.commit() - + def literal(self, o): """ @@ -263,7 +248,7 @@ def begin(self): 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): @@ -281,10 +266,6 @@ def set_character_set(self, charset): 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 charset == "utf8mb4": - py_charset = "utf8" - else: - py_charset = charset if self.character_set_name() != charset: try: super(Connection, self).set_character_set(charset) @@ -302,7 +283,7 @@ def set_sql_mode(self, sql_mode): raise NotSupportedError("server is too old to set sql_mode") self.query("SET SESSION sql_mode='{!s}'".format(sql_mode)) self.store_result() - + def show_warnings(self): """Return detailed information about warnings as a sequence of tuples of (Level, Code, Message). This @@ -313,7 +294,7 @@ def show_warnings(self): r = self.store_result() warnings = r.fetch_row(0) return warnings - + Warning = Warning Error = Error InterfaceError = InterfaceError diff --git a/MySQLdb/converters.py b/MySQLdb/converters.py index 514de18..fd1c856 100644 --- a/MySQLdb/converters.py +++ b/MySQLdb/converters.py @@ -33,8 +33,8 @@ """ from _mysql import string_literal, escape_sequence, escape_dict, escape, NULL -from MySQLdb.constants import FIELD_TYPE, FLAG -from MySQLdb.times import * +from .constants import FIELD_TYPE, FLAG +from .times import * import datetime import array @@ -92,19 +92,19 @@ class to conversions; it will be handled by the default """ - if o.__class__ in d: + if d.has_key(o.__class__): return d[o.__class__](o, d) cl = filter(lambda x,o=o: - type(x) is ClassType + type(x) is types.ClassType and isinstance(o, x), d.keys()) - if not cl: + if not cl and hasattr(types, 'ObjectType'): cl = filter(lambda x,o=o: - type(x) is TypeType + type(x) is types.TypeType and isinstance(o, x) and d[x] is not Instance2Str, d.keys()) if not cl: - return d[StringType](o,d) + return d[types.StringType](o,d) d[o.__class__] = d[cl[0]] return d[cl[0]](o, d) @@ -114,15 +114,12 @@ def char_array(s): def array2Str(o, d): return Thing2Literal(o.tostring(), d) -def quote_tuple(t, d): - return escape_sequence(t, d) - conversions = { int: Long2Int, float: Float2Str, type(None): None2NULL, - tuple: quote_tuple, - list: quote_tuple, + tuple: escape_sequence, + list: escape_sequence, dict: escape_dict, object: Instance2Str, array.ArrayType: array2Str, diff --git a/MySQLdb/cursors.py b/MySQLdb/cursors.py index 7f8637d..a2a65d9 100644 --- a/MySQLdb/cursors.py +++ b/MySQLdb/cursors.py @@ -8,33 +8,14 @@ import re import sys -restr = r""" - \s - values - \s* - ( - \( - [^()']* - (?: - (?: - (?:\( - # ( - editor hightlighting helper - .* - \)) - | - ' - [^\\']* - (?:\\.[^\\']*)* - ' - ) - [^()']* - )* - \) - ) -""" -insert_values = re.compile(restr, re.S | re.I | re.X) +restr = (r"\svalues\s*" + r"(\(((?= len(self._rows): self.errorhandler(self, IndexError, "out of range") self.rownumber = r diff --git a/MySQLdb/release.py b/MySQLdb/release.py index 4ce9412..d0d2db8 100644 --- a/MySQLdb/release.py +++ b/MySQLdb/release.py @@ -1,4 +1,4 @@ -__author__ = "Andy Dustman " -version_info = (1,2,4,'final',1) -__version__ = "1.2.4" +__author__ = "Andy Dustman " +version_info = (1,2,3,'final',0) +__version__ = "1.2.3" diff --git a/MySQLdb/times.py b/MySQLdb/times.py index 13742ce..abd360c 100644 --- a/MySQLdb/times.py +++ b/MySQLdb/times.py @@ -38,7 +38,7 @@ def format_TIMEDELTA(v): return '%d %d:%d:%d' % (v.days, hours, minutes, seconds) def format_TIMESTAMP(d): - return d.isoformat() + return d.strftime("%Y-%m-%d %H:%M:%S") def DateTime_or_None(s): @@ -51,28 +51,16 @@ def DateTime_or_None(s): try: d, t = s.split(sep, 1) - if '.' in t: - t, ms = t.split('.',1) - ms = ms.ljust(6, '0') - else: - ms = 0 - return datetime(*[ int(x) for x in d.split('-')+t.split(':')+[ms] ]) - except (SystemExit, KeyboardInterrupt): - raise + return datetime(*[ int(x) for x in d.split('-')+t.split(':') ]) except: return Date_or_None(s) def TimeDelta_or_None(s): try: h, m, s = s.split(':') - if '.' in s: - s, ms = s.split('.') - ms = ms.ljust(6, '0') - else: - ms = 0 - h, m, s, ms = int(h), int(m), int(s), int(ms) - td = timedelta(hours=abs(h), minutes=m, seconds=s, - microseconds=ms) + 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: @@ -84,24 +72,15 @@ def TimeDelta_or_None(s): def Time_or_None(s): try: h, m, s = s.split(':') - if '.' in s: - s, ms = s.split('.') - ms = ms.ljust(6, '0') - else: - ms = 0 - h, m, s, ms = int(h), int(m), int(s), int(ms) - return time(hour=h, minute=m, second=s, - microsecond=ms) + 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 + try: return date(*[ int(x) for x in s.split('-',2)]) + except: return None def DateTime2literal(d, c): """Format a DateTime object as an ISO timestamp.""" @@ -118,9 +97,5 @@ def mysql_timestamp_converter(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 + try: return Timestamp(*parts) + except: return None diff --git a/INSTALL b/README similarity index 99% rename from INSTALL rename to README index 04a798c..231bd28 100644 --- a/INSTALL +++ b/README @@ -246,4 +246,4 @@ GPL or the original license based on Python 1.5.2's license. :Author: Andy Dustman -:Revision: $Id$ +:Revision: $Id: README 641 2010-02-25 21:28:13Z kylev $ diff --git a/README.md b/README.md deleted file mode 100644 index f0ca032..0000000 --- a/README.md +++ /dev/null @@ -1,41 +0,0 @@ -MySQLdb1 -======== - -This is the legacy (1.x) version of MySQLdb. While it is still being -maintained, there will not be a lot of new feature development. - -[![Build Status](https://secure.travis-ci.org/farcepest/MySQLdb1.png)](http://travis-ci.org/farcepest/MySQLdb1) - -TODO ----- - -* A bugfix 1.2.4 release -* A 1.3.0 release that will support Python 2.7-3.3 -* The 2.0 version is being renamed [moist][] and is heavily refactored. - -Projects --------- - -* [MySQLdb-svn][] - - This is the old Subversion repository located on SourceForge. - It has all the early historical development of MySQLdb through 1.2.3, - and also is the working repository for ZMySQLDA. The trunk on this - repository was forked to create the [MySQLdb2][] repository. - -* [MySQLdb1][] - - This is the new (active) git repository. - Only updates to the 1.x series will happen here. - -* [MySQLdb2][] - - This is the now obsolete Mercurial repository for MySQLdb-2.0 - located on SourceForge. This repository has been migrated to the - [moist][] repository. - - -[MySQLdb1]: https://github.com/farcepest/MySQLdb1 -[moist]: https://github.com/farcepest/moist -[MySQLdb-svn]: https://sourceforge.net/p/mysql-python/svn/ -[MySQLdb2]: https://sourceforge.net/p/mysql-python/mysqldb-2/ \ No newline at end of file diff --git a/_mysql.c b/_mysql.c index 33eeeec..6f4dc8e 100644 --- a/_mysql.c +++ b/_mysql.c @@ -26,12 +26,12 @@ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "Python.h" -#if PY_VERSION_HEX > 0x02060000 -#include "bytesobject.h" -#endif #include "pymemcompat.h" #include "structmember.h" +#if defined(MS_WINDOWS) +#include +#include +#endif #include "my_config.h" #include "mysql.h" #include "mysqld_error.h" @@ -41,7 +41,7 @@ PERFORMANCE OF THIS SOFTWARE. # 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) -# define MyFree(ob) ob->ob_base.ob_type->tp_free((PyObject *)ob) +# define MyFree(ob) ob->ob_base.ob_type->tp_free((PyObject *)ob) static PyObject *_mysql_MySQLError; static PyObject *_mysql_Warning; @@ -86,16 +86,6 @@ static int _mysql_server_init_done = 0; #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 - -/* According to https://dev.mysql.com/doc/refman/5.1/en/mysql-options.html - The MYSQL_OPT_READ_TIMEOUT apear in the version 5.1.12 */ -#if MYSQL_VERSION_ID > 50112 -#define HAVE_MYSQL_OPT_TIMEOUTS 1 -#endif - PyObject * _mysql_Exception(_mysql_ConnectionObject *c) { PyObject *t, *e, *code, *message; @@ -367,14 +357,9 @@ _mysql_ResultObject_Initialize( 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; + if (!conv) conv = PyDict_New(); + if (!conv) return -1; + self->conn = conn; Py_INCREF(conn); self->use = use; Py_BEGIN_ALLOW_THREADS ; @@ -385,88 +370,60 @@ _mysql_ResultObject_Initialize( 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; - } + if (!(self->converter = PyTuple_New(n))) return -1; fields = mysql_fetch_fields(result); for (i=0; iconverter, i, fun); } - - Py_DECREF(conv); return 0; } @@ -518,16 +475,8 @@ _mysql_ConnectionObject_Initialize( "read_default_file", "read_default_group", "client_flag", "ssl", "local_infile", -#ifdef HAVE_MYSQL_OPT_TIMEOUTS - "read_timeout", - "write_timeout", -#endif NULL } ; int connect_timeout = 0; -#ifdef HAVE_MYSQL_OPT_TIMEOUTS - int read_timeout = 0; - int write_timeout = 0; -#endif int compress = -1, named_pipe = -1, local_infile = -1; char *init_command=NULL, *read_default_file=NULL, @@ -536,13 +485,7 @@ _mysql_ConnectionObject_Initialize( self->converter = NULL; self->open = 0; check_server_init(-1); - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, -#ifdef HAVE_MYSQL_OPT_TIMEOUTS - "|ssssisOiiisssiOiii:connect", -#else - "|ssssisOiiisssiOi:connect", -#endif + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssisOiiisssiOi:connect", kwlist, &host, &user, &passwd, &db, &port, &unix_socket, &conv, @@ -551,19 +494,15 @@ _mysql_ConnectionObject_Initialize( &init_command, &read_default_file, &read_default_group, &client_flag, &ssl, - &local_infile -#ifdef HAVE_MYSQL_OPT_TIMEOUTS - , &read_timeout - , &write_timeout -#endif - )) + &local_infile /* DO NOT PATCH FOR RECONNECT, IDIOTS + IF YOU DO THIS, I WILL NOT SUPPORT YOUR PACKAGES. */ + )) return -1; #define _stringsuck(d,t,s) {t=PyMapping_GetItemString(s,#d);\ - if(t){d=PyUnicode_AS_DATA(t);Py_DECREF(t);}\ + if(t){d=PyBytes_AsString(t);Py_DECREF(t);}\ PyErr_Clear();} - if (ssl) { #if HAVE_OPENSSL PyObject *value = NULL; @@ -586,18 +525,6 @@ _mysql_ConnectionObject_Initialize( mysql_options(&(self->connection), MYSQL_OPT_CONNECT_TIMEOUT, (char *)&timeout); } -#ifdef HAVE_MYSQL_OPT_TIMEOUTS - if (read_timeout) { - unsigned int timeout = read_timeout; - mysql_options(&(self->connection), MYSQL_OPT_READ_TIMEOUT, - (char *)&timeout); - } - if (write_timeout) { - unsigned int timeout = write_timeout; - mysql_options(&(self->connection), MYSQL_OPT_WRITE_TIMEOUT, - (char *)&timeout); - } -#endif if (compress != -1) { mysql_options(&(self->connection), MYSQL_OPT_COMPRESS, 0); client_flag |= CLIENT_COMPRESS; @@ -731,6 +658,7 @@ static int _mysql_ConnectionObject_traverse( return 0; } + static int _mysql_ConnectionObject_clear( _mysql_ConnectionObject *self) { @@ -844,21 +772,7 @@ _mysql_ConnectionObject_autocommit( if (err) return _mysql_Exception(self); Py_INCREF(Py_None); return Py_None; -} - -static char _mysql_ConnectionObject_get_autocommit__doc__[] = -"Get the autocommit mode. True when enable; False when disable.\n"; - -static PyObject * -_mysql_ConnectionObject_get_autocommit( - _mysql_ConnectionObject *self, - PyObject *args) -{ - if (self->connection.server_status & SERVER_STATUS_AUTOCOMMIT) { - Py_RETURN_TRUE; - } - Py_RETURN_FALSE; -} +} static char _mysql_ConnectionObject_commit__doc__[] = "Commits the current transaction\n\ @@ -977,7 +891,7 @@ _mysql_ConnectionObject_sqlstate( { if (!PyArg_ParseTuple(args, "")) return NULL; return PyUnicode_FromString(mysql_sqlstate(&(self->connection))); -} +} static char _mysql_ConnectionObject_warning_count__doc__[] = "Returns the number of warnings generated during execution\n\ @@ -1036,7 +950,7 @@ _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_ConnectionObject_escape_string( _mysql_ConnectionObject *self, PyObject *args) +static PyObject *_mysql_ConnectionObject_escape_string( _mysql_ConnectionObject *self, PyObject *args) { PyObject *str; char *in, *out; @@ -1092,7 +1006,7 @@ static PyObject *_mysql_ConnectionObject_string_literal(_mysql_ConnectionObject len = mysql_escape_string(out+1, in, size); #else check_server_init(NULL); - if (self && self->open) + if (self && self->open ) { len = mysql_real_escape_string(&(self->connection), out+1, in, size); } else @@ -1126,16 +1040,14 @@ static PyObject *_escape_item( PyObject *item, PyObject *d) if (!itemconv) { PyErr_Clear(); itemconv = PyObject_GetItem(d, - (PyObject *) &PyUnicode_Type); + (PyObject *) &PyUnicode_Type); } if (!itemconv) { PyErr_SetString(PyExc_TypeError, - "no default type converter defined"); + "no default type converter defined"); goto error; } - Py_INCREF(d); quoted = PyObject_CallFunction(itemconv, "OO", item, d); - Py_DECREF(d); Py_DECREF(itemconv); error: return quoted; @@ -1163,8 +1075,7 @@ static PyObject *_mysql_ConnectionObject_escape( _mysql_ConnectionObject *self, PyErr_SetString(PyExc_TypeError, "argument 2 must be a mapping"); return NULL; } - return _escape_item(o, - ((_mysql_ConnectionObject *) self)->converter); + return _escape_item(o, self->converter); } } @@ -1248,7 +1159,7 @@ static PyObject * _mysql_ResultObject_describe ( _mysql_ResultObject *self, PyOb PyObject *d = NULL; MYSQL_FIELD *fields; unsigned int i, n; - + if ( !PyArg_ParseTuple(args, "")) { return NULL; @@ -1281,7 +1192,8 @@ static PyObject * _mysql_ResultObject_describe ( _mysql_ResultObject *self, PyOb break; }; PyTuple_SET_ITEM(d, i, t); - } + }; + return d; } @@ -1396,7 +1308,7 @@ _mysql_row_to_dict( unsigned int n, i; unsigned long *length; PyObject *r, *c; - MYSQL_FIELD *fields; + MYSQL_FIELD *fields; const char *charset; n = mysql_num_fields(self->result); @@ -1443,7 +1355,7 @@ _mysql_row_to_dict_old( unsigned int n, i; unsigned long *length; PyObject *r, *c; - MYSQL_FIELD *fields; + MYSQL_FIELD *fields; const char *charset; n = mysql_num_fields(self->result); @@ -1730,8 +1642,8 @@ static char _mysql_get_client_info__doc__[] = the client library version."; static PyObject * _mysql_get_client_info( - PyObject *self, - PyObject *args) + PyObject *self, + PyObject *args) { if (!PyArg_ParseTuple(args, "")) return NULL; check_server_init(NULL); @@ -2259,12 +2171,6 @@ static PyMethodDef _mysql_ConnectionObject_methods[] = { METH_VARARGS, _mysql_ConnectionObject_autocommit__doc__ }, - { - "get_autocommit", - (PyCFunction)_mysql_ConnectionObject_get_autocommit, - METH_NOARGS, - _mysql_ConnectionObject_get_autocommit__doc__ - }, { "commit", (PyCFunction)_mysql_ConnectionObject_commit, @@ -2569,9 +2475,8 @@ static MyMemberlist(_mysql_ResultObject_memberlist)[] = { {NULL} /* Sentinel */ }; - PyTypeObject _mysql_ConnectionObject_Type = { - PyVarObject_HEAD_INIT(NULL, 0) + PyVarObject_HEAD_INIT(NULL, 0) "_mysql.connection", /* (char *)tp_name For printing */ sizeof(_mysql_ConnectionObject), 0, @@ -2638,7 +2543,7 @@ PyTypeObject _mysql_ConnectionObject_Type = { } ; PyTypeObject _mysql_ResultObject_Type = { - PyVarObject_HEAD_INIT(NULL, 0) + PyVarObject_HEAD_INIT(NULL, 0) "_mysql.result", sizeof(_mysql_ResultObject), 0, @@ -2704,8 +2609,7 @@ PyTypeObject _mysql_ResultObject_Type = { 0, /* (PyObject *) tp_defined */ }; -static PyMethodDef -_mysql_methods[] = { +static PyMethodDef _mysql_methods[] = { { "connect", (PyCFunction)_mysql_connect, @@ -2777,20 +2681,12 @@ _mysql_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyObject * -_mysql_NewException( - PyObject *dict, - PyObject *edict, - char *name) +static PyObject *_mysql_NewException( PyObject *dict, PyObject *edict, char *name) { PyObject *e; - if (!(e = PyDict_GetItemString(edict, name))) - return NULL; + if (!(e = PyDict_GetItemString(edict, name))) return NULL; if (PyDict_SetItemString(dict, name, e)) return NULL; -#ifdef PYPY_VERSION - Py_INCREF(e); -#endif return e; } @@ -2844,7 +2740,7 @@ PyMODINIT_FUNC PyInit__mysql(void) _mysql_ResultObject_Type.ob_base.ob_base.ob_type = &PyType_Type; _mysql_ConnectionObject_Type.tp_alloc = PyType_GenericAlloc; _mysql_ConnectionObject_Type.tp_new = PyType_GenericNew; - _mysql_ConnectionObject_Type.tp_free = PyObject_GC_Del; + _mysql_ConnectionObject_Type.tp_free = PyObject_GC_Del; _mysql_ResultObject_Type.tp_alloc = PyType_GenericAlloc; _mysql_ResultObject_Type.tp_new = PyType_GenericNew; _mysql_ResultObject_Type.tp_free = PyObject_GC_Del; @@ -2853,12 +2749,12 @@ PyMODINIT_FUNC PyInit__mysql(void) if (PyType_Ready(&_mysql_ResultObject_Type) < 0) return NULL; module = PyModule_Create2(&mysqlModule,PYTHON_API_VERSION); - + if (module == NULL) { return NULL; }; - + dict = PyModule_GetDict(module); if (PyDict_SetItemString(dict, "version_info", PyRun_String(QUOTE(version_info), Py_eval_input, dict, dict)) == -1) { diff --git a/distribute_setup.py b/distribute_setup.py deleted file mode 100644 index 8f5b063..0000000 --- a/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/doc/FAQ.rst b/doc/FAQ.rst deleted file mode 100644 index b6a4ce9..0000000 --- a/doc/FAQ.rst +++ /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/doc/Makefile b/doc/Makefile deleted file mode 100644 index 6bf78bd..0000000 --- a/doc/Makefile +++ /dev/null @@ -1,153 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MySQLdb.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MySQLdb.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/MySQLdb" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MySQLdb" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/MySQLdb.constants.rst b/doc/MySQLdb.constants.rst deleted file mode 100644 index e28dee2..0000000 --- a/doc/MySQLdb.constants.rst +++ /dev/null @@ -1,59 +0,0 @@ -constants Package -================= - -:mod:`constants` Package ------------------------- - -.. automodule:: MySQLdb.constants - :members: - :undoc-members: - :show-inheritance: - -:mod:`CLIENT` Module --------------------- - -.. automodule:: MySQLdb.constants.CLIENT - :members: - :undoc-members: - :show-inheritance: - -:mod:`CR` Module ----------------- - -.. automodule:: MySQLdb.constants.CR - :members: - :undoc-members: - :show-inheritance: - -:mod:`ER` Module ----------------- - -.. automodule:: MySQLdb.constants.ER - :members: - :undoc-members: - :show-inheritance: - -:mod:`FIELD_TYPE` Module ------------------------- - -.. automodule:: MySQLdb.constants.FIELD_TYPE - :members: - :undoc-members: - :show-inheritance: - -:mod:`FLAG` Module ------------------- - -.. automodule:: MySQLdb.constants.FLAG - :members: - :undoc-members: - :show-inheritance: - -:mod:`REFRESH` Module ---------------------- - -.. automodule:: MySQLdb.constants.REFRESH - :members: - :undoc-members: - :show-inheritance: - diff --git a/doc/MySQLdb.rst b/doc/MySQLdb.rst deleted file mode 100644 index 26138ec..0000000 --- a/doc/MySQLdb.rst +++ /dev/null @@ -1,50 +0,0 @@ -MySQLdb Package -=============== - -:mod:`MySQLdb` Package ----------------------- - -.. automodule:: MySQLdb.__init__ - :members: - :undoc-members: - :show-inheritance: - -:mod:`connections` Module -------------------------- - -.. automodule:: MySQLdb.connections - :members: Connection - :undoc-members: - :show-inheritance: - -:mod:`converters` Module ------------------------- - -.. automodule:: MySQLdb.converters - :members: - :undoc-members: - :show-inheritance: - -:mod:`cursors` Module ---------------------- - -.. automodule:: MySQLdb.cursors - :members: Cursor - :undoc-members: - :show-inheritance: - -:mod:`times` Module -------------------- - -.. automodule:: MySQLdb.times - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - - MySQLdb.constants - diff --git a/doc/MySQLdb.txt b/doc/MySQLdb.txt index fbc86e5..e09f120 100644 --- a/doc/MySQLdb.txt +++ b/doc/MySQLdb.txt @@ -715,4 +715,4 @@ server. :Title: MySQLdb: a Python interface for MySQL :Author: Andy Dustman -:Version: $Revision$ +:Version: $Revision: 421 $ diff --git a/doc/_mysql.rst b/doc/_mysql.rst deleted file mode 100644 index 4a60591..0000000 --- a/doc/_mysql.rst +++ /dev/null @@ -1,7 +0,0 @@ -_mysql Module -============= - -.. automodule:: _mysql - :members: - :undoc-members: - :show-inheritance: \ No newline at end of file diff --git a/doc/_mysql_exceptions.rst b/doc/_mysql_exceptions.rst deleted file mode 100644 index 9b65de3..0000000 --- a/doc/_mysql_exceptions.rst +++ /dev/null @@ -1,7 +0,0 @@ -_mysql_exceptions Module -======================== - -.. automodule:: _mysql_exceptions - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/conf.py b/doc/conf.py deleted file mode 100644 index ab36b07..0000000 --- a/doc/conf.py +++ /dev/null @@ -1,242 +0,0 @@ -# -*- coding: utf-8 -*- -# -# MySQLdb documentation build configuration file, created by -# sphinx-quickstart on Sun Oct 07 19:36:17 2012. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'MySQLdb' -copyright = u'2012, Andy Dustman' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '1.2' -# The full version, including alpha/beta/rc tags. -release = '1.2.4b4' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'MySQLdbdoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'MySQLdb.tex', u'MySQLdb Documentation', - u'Andy Dustman', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'mysqldb', u'MySQLdb Documentation', - [u'Andy Dustman'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'MySQLdb', u'MySQLdb Documentation', - u'Andy Dustman', 'MySQLdb', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' diff --git a/doc/index.rst b/doc/index.rst deleted file mode 100644 index a0b3fd5..0000000 --- a/doc/index.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. MySQLdb documentation master file, created by - sphinx-quickstart on Sun Oct 07 19:36:17 2012. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to MySQLdb's documentation! -=================================== - -Contents: - -.. toctree:: - :maxdepth: 3 - - user_guide - MySQLdb - FAQ - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/doc/make.bat b/doc/make.bat deleted file mode 100644 index 6211b53..0000000 --- a/doc/make.bat +++ /dev/null @@ -1,190 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -set I18NSPHINXOPTS=%SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\MySQLdb.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\MySQLdb.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -:end diff --git a/doc/modules.rst b/doc/modules.rst deleted file mode 100644 index 7cf3faa..0000000 --- a/doc/modules.rst +++ /dev/null @@ -1,7 +0,0 @@ -MySQLdb -======= - -.. toctree:: - :maxdepth: 4 - - MySQLdb diff --git a/doc/user_guide.rst b/doc/user_guide.rst deleted file mode 100644 index fbc86e5..0000000 --- a/doc/user_guide.rst +++ /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/ez_setup.py b/ez_setup.py new file mode 100644 index 0000000..1ff1d3e --- /dev/null +++ b/ez_setup.py @@ -0,0 +1,284 @@ +#!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/metadata.cfg b/metadata.cfg index 49841c1..469b478 100644 --- a/metadata.cfg +++ b/metadata.cfg @@ -1,6 +1,6 @@ [metadata] -version: 1.2.4 -version_info: (1,2,4,'final',1) +version: 1.2.3 +version_info: (1,2,3,'final',0) description: Python interface to MySQL long_description: ========================= @@ -11,12 +11,13 @@ long_description: Python. The design goals are: \n - Compliance with Python database API version 2.0 [PEP-0249]_ + \n - Thread-safety + \n - Thread-friendliness (threads will not block each other) \n - MySQL-3.23 through 5.5 and Python-2.4 through 2.7 are currently + MySQL-3.23 through 5.0 and Python-2.3 through 2.6 are currently supported. Python-3.0 will be supported in a future release. - PyPy is supported. \n MySQLdb is `Free Software`_. \n @@ -24,10 +25,11 @@ long_description: .. _`Free Software`: http://www.gnu.org/ .. [PEP-0249] http://www.python.org/peps/pep-0249.html author: Andy Dustman -author_email: farcepest@gmail.com +author_email: adustman@users.sourceforge.net license: GPL platforms: ALL -url: https://github.com/farcepest/MySQLdb1 +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 diff --git a/setup.cfg b/setup.cfg index 5b21f6d..14d6b42 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,19 +1,18 @@ [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 +doc_files = README MANIFEST doc/*.txt distribution-name = Red Stains Linux +packager = Andy Dustman requires = python build-requires = python-devel mysql-devel zlib-devel openssl-devel + +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + +[build_ext] + diff --git a/setup_common.py b/setup_common.py index a1a11ca..831fd71 100644 --- a/setup_common.py +++ b/setup_common.py @@ -30,3 +30,4 @@ def create_release_file(metadata): __version__ = "%(version)s" """ % metadata) rel.close() + diff --git a/setup_posix.py b/setup_posix.py index 9aef8df..13d69a8 100644 --- a/setup_posix.py +++ b/setup_posix.py @@ -1,4 +1,3 @@ -import os, sys from configparser import SafeConfigParser # This dequote() business is required for some older versions @@ -27,6 +26,7 @@ def mysql_config(what): mysql_config.path = "mysql_config" def get_config(): + import os, sys from setup_common import get_metadata_and_options, enabled, create_release_file metadata, options = get_metadata_and_options() @@ -71,9 +71,8 @@ def get_config(): if i.startswith(compiler_flag('I')) ] if static: - extra_objects.append(os.path.join(library_dirs[0],'lib{}.a'.format(client))) - if client in libraries: - libraries.remove(client) + extra_objects.append(os.path.join( + library_dirs[0],'lib{}.a'.format(client))) name = "MySQL-python" if enabled(options, 'embedded'): @@ -99,5 +98,5 @@ def get_config(): return metadata, ext_options if __name__ == "__main__": - sys.stderr.write("""You shouldn't be running this directly; it is used by setup.py.""") + print ("""You shouldn't be running this directly; it is used by setup.py.""") diff --git a/setup_windows.py b/setup_windows.py index 25c25e2..5986cc4 100644 --- a/setup_windows.py +++ b/setup_windows.py @@ -1,22 +1,22 @@ -import os, sys - def get_config(): + import os, sys from setup_common import get_metadata_and_options, enabled, create_release_file metadata, options = get_metadata_and_options() - connector = options["connector"] + mysql_root = options['mysql_location'] extra_objects = [] - + static = enabled(options, 'static') + # XXX static doesn't actually do anything on Windows if enabled(options, 'embedded'): client = "mysqld" else: client = "mysqlclient" - library_dirs = [ os.path.join(connector, r'lib\vs11') ] + library_dirs = [ os.path.join(mysql_root, r'lib') ] libraries = [ 'kernel32', 'advapi32', 'wsock32', client ] - include_dirs = [ os.path.join(connector, r'include') ] + include_dirs = [ os.path.join(mysql_root, r'include') ] extra_compile_args = [ '/Zl' ] name = "MySQL-python" @@ -42,5 +42,5 @@ def get_config(): return metadata, ext_options if __name__ == "__main__": - sys.stderr.write("""You shouldn't be running this directly; it is used by setup.py.""") + print ("""You shouldn't be running this directly; it is used by setup.py.""") diff --git a/site.cfg b/site.cfg index b4ea9ea..5e3ea98 100644 --- a/site.cfg +++ b/site.cfg @@ -12,6 +12,6 @@ static = False # 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.1 +# For Windows, the path to MySQL server directory. +# This has to be set for Windows builds to work. +mysql_location = C:\Program Files\MySQL\MySQL Server 5.5 diff --git a/tests/capabilities.py b/tests/capabilities.py index b70369b..4b19bdd 100644 --- a/tests/capabilities.py +++ b/tests/capabilities.py @@ -3,12 +3,11 @@ 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): @@ -19,30 +18,29 @@ class DatabaseTest(unittest.TestCase): create_table_extra = '' rows = 10 debug = False - + def setUp(self): import gc - db = connection_factory(**self.connect_kwargs) + db = self.db_module.connect(*self.connect_args, **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.BLOBText = ''.join([chr(i) for i in range(256)] * 100); self.BLOBUText = ''.join([chr(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.assertFalse(orphans, "%d orphaned objects found after deleting cursor" % orphans) - + del self.connection orphans = gc.collect() self.assertFalse(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) @@ -53,7 +51,7 @@ def table_exists(self, name): def quote_identifier(self, ident): return '"%s"' % ident - + def new_table_name(self): i = id(self.cursor) while True: @@ -66,14 +64,14 @@ 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.cursor.execute('CREATE TABLE %s (%s) %s' % (self.table, ',\n'.join(columndefs), self.create_table_extra)) @@ -81,16 +79,20 @@ def create_table(self, columndefs): def check_data_integrity(self, columndefs, generator): # insert self.create_table(columndefs) - insert_statement = ('INSERT INTO %s VALUES (%s)' % + 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) ] + if self.debug: + print(data) self.cursor.executemany(insert_statement, data) self.connection.commit() # verify self.cursor.execute('select * from %s' % self.table) l = self.cursor.fetchall() + if self.debug: + print(l) self.assertEqual(len(l), self.rows) try: for i in range(self.rows): @@ -106,7 +108,7 @@ 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)' % + insert_statement = ('INSERT INTO %s VALUES (%s)' % (self.table, ','.join(['{!s}'] * len(columndefs)))) data = [ [ generator(i,j) for j in range(len(columndefs)) ] @@ -139,36 +141,42 @@ def generator(row, col): if col == 0: return row else: return ('{:d}'.format(row%10))*(round(255-self.rows/2)+row) self.create_table(columndefs) - insert_statement = ('INSERT INTO %s VALUES (%s)' % + insert_statement = ('INSERT INTO %s VALUES (%s)' % (self.table, ','.join(['{!s}'] * len(columndefs)))) try: self.cursor.execute(insert_statement, (0, '0'*256)) + except Warning: + if self.debug: print(self.cursor.messages) 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 Warning: + if self.debug: print(self.cursor.messages) 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 Warning: + if self.debug: print(self.cursor.messages) except self.connection.DataError: pass else: diff --git a/tests/configdb.py b/tests/configdb.py deleted file mode 100644 index cd6d43d..0000000 --- a/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/tests/dbapi20.py b/tests/dbapi20.py index 98d14fc..62f0e9c 100644 --- a/tests/dbapi20.py +++ b/tests/dbapi20.py @@ -11,8 +11,8 @@ -- Ian Bicking ''' -__rcs_id__ = '$Id$' -__version__ = '$Revision$'[11:-2] +__rcs_id__ = '$Id: dbapi20.py 613 2009-03-08 17:45:52Z adustman $' +__version__ = '$Revision: 613 $'[11:-2] __author__ = 'Stuart Bishop ' import unittest @@ -392,7 +392,7 @@ def _paraminsert(self,cur): ) elif self.driver.paramstyle == 'named': cur.execute( - 'insert into %sbooze values ({beer})' % self.table_prefix, + 'insert into %sbooze values ({beer})' % self.table_prefix, {'beer':"Cooper's"} ) elif self.driver.paramstyle == 'format': diff --git a/tests/default.cnf b/tests/default.cnf deleted file mode 100644 index 2aeda7c..0000000 --- a/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/tests/test_MySQLdb_capabilities.py b/tests/test_MySQLdb_capabilities.py index 25d95f4..409687c 100644 --- a/tests/test_MySQLdb_capabilities.py +++ b/tests/test_MySQLdb_capabilities.py @@ -4,16 +4,17 @@ import MySQLdb import warnings -warnings.filterwarnings('ignore') +warnings.filterwarnings('error') class test_MySQLdb(capabilities.DatabaseTest): db_module = MySQLdb connect_args = () - connect_kwargs = dict(sql_mode="ANSI,STRICT_TRANS_TABLES,TRADITIONAL") + connect_kwargs = dict(db='test', read_default_file='~/.my.cnf', + charset='utf8', 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 @@ -35,14 +36,14 @@ def generator(row,col): 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()))) + 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 @@ -56,7 +57,7 @@ def test_stored_procedures(self): self.assertEqual(len(rows), 1) self.assertEqual(rows[0][0], 3) c.nextset() - + c.execute("DROP PROCEDURE test_sp") c.execute('drop table %s' % (self.table)) @@ -70,32 +71,22 @@ def generator(row,col): 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 as msg: self.assertTrue(msg.code == 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() + print ('''"Huh-huh, he said 'unit'." -- Butthead''') diff --git a/tests/test_MySQLdb_dbapi20.py b/tests/test_MySQLdb_dbapi20.py index eb1d3af..18e6ee1 100644 --- a/tests/test_MySQLdb_dbapi20.py +++ b/tests/test_MySQLdb_dbapi20.py @@ -2,14 +2,14 @@ import dbapi20 import unittest import MySQLdb -from configdb import connection_kwargs -import warnings -warnings.simplefilter("ignore") class test_MySQLdb(dbapi20.DatabaseAPI20Test): driver = MySQLdb connect_args = () - connect_kw_args = connection_kwargs(dict(sql_mode="ANSI,STRICT_TRANS_TABLES,TRADITIONAL")) + connect_kw_args = dict(db='test', + read_default_file='~/.my.cnf', + charset='utf8', + sql_mode="ANSI,STRICT_TRANS_TABLES,TRADITIONAL") def test_setoutputsize(self): pass def test_setoutputsize_basic(self): pass @@ -19,7 +19,7 @@ def test_nextset(self): pass 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: @@ -65,10 +65,10 @@ def test_fetchall(self): '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: @@ -147,8 +147,8 @@ def test_callproc(self): 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" + that returns two result sets, first the + number of rows in booze then "name from booze" ''' sql=""" create procedure deleteme() @@ -199,6 +199,7 @@ def test_nextset(self): finally: con.close() - + if __name__ == '__main__': unittest.main() + print ('''"Huh-huh, he said 'unit'." -- Butthead''') diff --git a/tests/test_MySQLdb_nonstandard.py b/tests/test_MySQLdb_nonstandard.py index 8c44aca..c659970 100644 --- a/tests/test_MySQLdb_nonstandard.py +++ b/tests/test_MySQLdb_nonstandard.py @@ -3,9 +3,7 @@ import _mysql import MySQLdb from MySQLdb.constants import FIELD_TYPE -from configdb import connection_factory -import warnings -warnings.simplefilter("ignore") + class TestDBAPISet(unittest.TestCase): def test_set_equality(self): @@ -46,7 +44,7 @@ class CoreAPI(unittest.TestCase): """Test _mysql interaction internals.""" def setUp(self): - self.conn = connection_factory() + self.conn = _mysql.connect(db='test', read_default_file="~/.my.cnf") def tearDown(self): self.conn.close() diff --git a/tests/travis.cnf b/tests/travis.cnf deleted file mode 100644 index eb37c29..0000000 --- a/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 = utf8mb4 diff --git a/tox.ini b/tox.ini deleted file mode 100644 index e7bb971..0000000 --- a/tox.ini +++ /dev/null @@ -1,11 +0,0 @@ -[tox] -envlist = py25, py26, py27, py33 - -[testenv] -setenv = - TESTDB=travis.cnf -commands = - nosetests {posargs:-w tests -v} -deps = - ipdb - nose