o k`f@sLddlZddlZddlZddlZddlmZmZddlm Z ddl m Z m Z ddl mZmZmZmZddlTddlmZddlmZdd lmZdd lmZdd lmZdd lmZdd lm Z m!Z!Gddde"Z#Gddde#Z$Gddde#Z%Gddde"edZ&Gddde'Z(Gddde)Z*ddZ+ddZ,dd Z-d!d"Z.dS)#N)ABCMetaabstractmethod) db_default)IEnvironmentSetupParticipantISystemInfoProvider) BoolOptionConfigurationError IntOptionOption)*)ConnectionPool)Table)ConnectionWrapper) ThreadLocal)tag)unicode_passwd)_tag_c@s4eZdZdZdZddZd ddZeZd ddZdS) DbContextManagerz^Database Context Manager The outermost `DbContextManager` will close the connection. NcCst||_dSN)DatabaseManagerdbmgr)selfenvr-/usr/lib/python3/dist-packages/trac/db/api.py__init__,szDbContextManager.__init__cC4|}|||WdS1swYdS)z(Shortcut for directly executing a query.N)executerqueryparamsdbrrrr/ $zDbContextManager.executecCr)z7Shortcut for directly calling "executemany" on a query.N) executemanyrrrrr$6r#zDbContextManager.executemanyr) __name__ __module__ __qualname____doc__r"rr__call__r$rrrrr$s rc@ eZdZdZddZddZdS)TransactionContextManagerzTransactioned Database Context Manager for retrieving a `~trac.db.util.ConnectionWrapper`. The outermost such context manager will perform a commit upon normal exit or a rollback after an exception. cCsJ|jjj}|s#|jjj}|rt|j|j}n|j}||jj_|_|Sr) r_transaction_localwdbrdbrcnxlogget_connectionr"rr"rrr __enter__Ds   z#TransactionContextManager.__enter__cCsN|jr#d|jj_|dur|jn|j|jjjs%|jdSdSdSr)r"rr,r-commitrollbackr.closeretevtbrrr__exit__Os    z"TransactionContextManager.__exit__Nr%r&r'r(r3r;rrrrr+<s r+c@r*)QueryContextManagerz_Database Context Manager for retrieving a read-only `~trac.db.util.ConnectionWrapper`. cCsR|jjj}|s'|jjj}|rt|j|jdd}n|jjdd}||jj_|_|S)NTreadonly) rr,r.r-rr/r0r1r"r2rrrr3_s  zQueryContextManager.__enter__cCs0|jrd|jj_|jjjs|jdSdSdSr)r"rr,r.r-r6r7rrrr;js   zQueryContextManager.__exit__Nr<rrrrr=Zs r=c@seZdZdZeddZeddZeddZedd Zed d Z ed$d dZ eddZ eddZ eddZ eddZeddZeddZeddZeddZedd Zed$d!d"Zd#S)%ConnectionBasez4Abstract base class for database connection classes.cCdS)z,Returns a clause casting `column` as `type`.Nr)rcolumntyperrrcasttzConnectionBase.castcGrA)z3Returns a clause concatenating the sequence `args`.Nr)rargsrrrconcatyrEzConnectionBase.concatcCrA)z Drops the `column` from `table`.Nr)rtablerBrrr drop_column~rEzConnectionBase.drop_columncCrA)zDrops the `table`.NrrrHrrr drop_tablerEzConnectionBase.drop_tablecCrA)z0Returns the list of the column names in `table`.NrrJrrrget_column_namesrEzConnectionBase.get_column_namesidcCrA)zReturns the current value of the primary key sequence for `table`. The `column` of the primary key may be specified, which defaults to `id`.NrrcursorrHrBrrr get_last_idzConnectionBase.get_last_idcCrA)z%Returns a list of the sequence names.Nrrrrrget_sequence_namesrEz!ConnectionBase.get_sequence_namescCrA)z"Returns a list of the table names.NrrRrrrget_table_namesrEzConnectionBase.get_table_namescCrAz!Returns whether the table exists.NrrJrrr has_tablerEzConnectionBase.has_tablecCrA)z)Returns a case-insensitive `LIKE` clause.NrrRrrrlikerEzConnectionBase.likecCrA)z2Returns `text` escaped for use in a `LIKE` clause.Nr)rtextrrr like_escaperEzConnectionBase.like_escapecCrA)z1Return a case sensitive prefix-matching operator.NrrRrrr prefix_matchrEzConnectionBase.prefix_matchcCrA)z;Return a value for case sensitive prefix-matching operator.Nr)rprefixrrrprefix_match_valuerEz!ConnectionBase.prefix_match_valuecCrA)z Returns the quoted `identifier`.Nr)r identifierrrrquoterEzConnectionBase.quotecCrA)zDeletes all data from the tables and resets autoincrement indexes. :return: list of names of the tables that were reset. NrrRrrr reset_tablesszConnectionBase.reset_tablescCrA)zUpdates the current value of the primary key sequence for `table`. The `column` of the primary key may be specified, which defaults to `id`.NrrNrrrupdate_sequencerQzConnectionBase.update_sequenceN)rM)r%r&r'r(rrDrGrIrKrLrPrSrTrVrWrYrZr\r^r_r`rrrrr@qsD               r@) metaclassc@s`eZdZdZddZdddZddZdd d Zdd d Zdd dZ ddZ ddZ ddZ dS)IDatabaseConnectorzfExtension point interface for components that support the connection to relational databases. cCrA)alReturn the connection URL schemes supported by the connector, and their relative priorities as an iterable of `(scheme, priority)` tuples. If `priority` is a negative number, this is indicative of an error condition with the connector. An error message should be attached to the `error` attribute of the connector. Nrrrrrget_supported_schemesz(IDatabaseConnector.get_supported_schemesNcKrA)z(Create a new connection to the database.Nr)pathr0kwargsrrrr1rdz!IDatabaseConnector.get_connectioncCrA)zReturn an object (typically a module) containing all the backend-specific exception types as attributes, named according to the Python Database API (http://www.python.org/dev/peps/pep-0249/). Nrrrrrget_exceptionsrdz!IDatabaseConnector.get_exceptionscKrA)zInitialize the database.Nr)reschemar0rfrrrinit_dbrdzIDatabaseConnector.init_dbcKrA)zDestroy the database.Nrrrer0rfrrr destroy_dbrdzIDatabaseConnector.destroy_dbcKrA)z%Return `True` if the database exists.Nrrjrrr db_existsrdzIDatabaseConnector.db_existscCrA)z]Return the DDL statements necessary to create the specified table, including indices.Nr)rHrrrto_sqlrdzIDatabaseConnector.to_sqlcCrA)zDBackup the database to a location defined by trac.backup_dirNr)destrrrbackuprdzIDatabaseConnector.backupcCrA)zYield a sequence of `(name, version)` tuples describing the name and version information of external packages used by the connector. Nrrrrrget_system_infordz"IDatabaseConnector.get_system_infor)NN) r%r&r'r(rcr1rgrirkrlrmrorprrrrrbs     rbc@sHeZdZdZeeeeeZ e ddddZ e ddddZ e dd d d Zedd d dZddZddZddZddZddZddZddZddZdd Zd!d"Zd#d$ZdJd%d&ZdKd(d)Zd*d+Zd,d-Zd.d/Z d0d1Z!d2d3Z"dKd4d5Z#dKd6d7Z$dLd9d:Z%dMdd?Z'd@dAZ(dBdCZ)dDdEZ*dFdGZ+dHdIZ,d;S)NrzBComponent used to manage the `IDatabaseConnector` implementations.tracdatabasezsqlite:db/trac.dbzlDatabase connection [wiki:TracEnvironment#DatabaseConnectionStrings string] for this project backup_dirr"zDatabase backup locationtimeout20z]Timeout value for database connection, in seconds. Use '0' to specify ''no timeout''. debug_sqlFz>Show the SQL queries in the Trac log, at DEBUG level. cCsd|_tddd|_dS)N)r-r.) _cnx_poolrr,rRrrrrszDatabaseManager.__init__cCsF|\}}tj|d<|jdi|tj}||d||dS)Nrhinitial_database_versionr) get_connectorrrhri db_versionset_database_version)r connectorrFversionrrrris   zDatabaseManager.init_dbcC|tjdSr)insert_into_tablesrget_datarRrrrinsert_default_data z#DatabaseManager.insert_default_datacCs(|\}}||jdi|dSNr)ryshutdownrkrr|rFrrrrk#s zDatabaseManager.destroy_dbcCs|\}}|jdi|Sr)ryrlrrrrrl)s zDatabaseManager.db_existscCs\|d}|jj}|D]}||D]}||qq WddS1s'wYdS)zzCreate the specified tables. :param schema: an iterable of table objects. :since: version 1.0.2 rN)ryrdb_transactionrm)rrhr|r"rHsqlrrr create_tables-s   "zDatabaseManager.create_tablescCszt|tr|jn|}|jj%}||s |jjd|||D]}| ||q"WddS1s6wYdS)zMDrops the specified columns from table. :since: version 1.2 Table %s not foundN) isinstancer namerrrVdb_excOperationalErrorr^rI)rrHcolumns table_namer"colrrr drop_columns:s   "zDatabaseManager.drop_columnscCsV|jj}|D]}t|tr|jn|}||qWddS1s$wYdS)zDrop the specified tables. :param schema: an iterable of `Table` objects or table names. :since: version 1.0.2 N)rrrr rrK)rrhr"rHrrrr drop_tablesGs  "zDatabaseManager.drop_tablesc Cs|jj4}t|r ||n|}|D]\}}}|d||d|ddgt|f|qWddS1s;wYdS)aInsert data into existing tables. :param data_or_callable: Nested tuples of table names, column names and row data:: (table1, (column1, column2), ((row1col1, row1col2), (row2col1, row2col2)), table2, ...) or a callable that takes a single parameter `db` and returns the aforementioned nested tuple. :since: version 1.1.3 zINSERT INTO %s (%s) VALUES (%s),z%sN)rrcallabler$r^joinlen)rdata_or_callabler"datarHcolsvalsrrrrSs "z"DatabaseManager.insert_into_tablescC4|jj }|WdS1swYdS)zDeletes all data from the tables and resets autoincrement indexes. :return: list of names of the tables that were reset. :since: version 1.1.3 N)rrr_r2rrrr_ls $zDatabaseManager.reset_tablesc s.|jj}|D]y}|jd}||}|rPt||}dd|jD}||@}|rJdfdd|D} | d | |jf| |f| |f|r|r| d |j| | |f|jD]} | j r}||j| jqo| |fq Wd d S1swYd S) zUpgrade table schema to `new_schema`, preserving data in columns that exist in the current schema and `new_schema`. :param new_schema: tuple or list of `Table` objects :since: version 1.2 _oldcSsh|]}|jqSrr).0rrrr sz1DatabaseManager.upgrade_tables..rc3s|]}|VqdSr)r^)rrr"rr sz1DatabaseManager.upgrade_tables..zg CREATE TEMPORARY TABLE %s AS SELECT * FROM %s zW INSERT INTO %s (%s) SELECT %s FROM %s N)rrrOrrVsetrLrrrr^rrauto_incrementr`) r new_schemarO new_tabletemp_table_namerVold_column_namesnew_column_names column_names cols_to_copyrrrrupgrade_tablesvsH           "zDatabaseManager.upgrade_tablescCsL|js|\}}td|fi||_|j|jpd}|r$t|dd}|S)zGet a database connection from the pool. If `readonly` is `True`, the returned connection will purposely lack the `rollback` and `commit` methods. NTr>)rwryr get_cnxrtr)rr?r|rFr"rrrr1s  zDatabaseManager.get_connectiondatabase_versioncCsh|jj&}|d|d|fD]\}t|WdS WddS1s-wYdS)aPReturns the database version from the SYSTEM table as an int, or `False` if the entry is not found. :param name: The name of the entry that contains the database version in the SYSTEM table. Defaults to `database_version`, which contains the database version for Trac. zM SELECT value FROM {0} WHERE name=%s systemNF)rdb_queryformatr^int)rrr"valuerrrget_database_versions  $z$DatabaseManager.get_database_versioncCs|dSNr)ryrgrRrrrrgrzDatabaseManager.get_exceptionscCr)zEReturns a list of the sequence names. :since: 1.3.2 N)rrrSr2rrrrS $z"DatabaseManager.get_sequence_namescCr)zBReturns a list of the table names. :since: 1.1.6 N)rrrTr2rrrrTrzDatabaseManager.get_table_namescCslt|tr|jn|}|jj}||s |jjd||| |WdS1s/wYdS)zReturns a list of the column names for `table`. :param table: a `Table` object or table name. :since: 1.2 rN) rr rrrrVrrr^rLrrHrr"rrrrLs   $z DatabaseManager.get_column_namescCsJt|tr|jn|}|jj }||WdS1swYdSrU)rr rrrrVrrrrrVs $zDatabaseManager.has_tablecCs||}|dur-|jj}|d|d||fWddS1s&wYdS|||kr`|jj}|d|d||fWdn1sPwY|jd|||dSdS)aHSets the database version in the SYSTEM table. :param version: an integer database version. :param name: The name of the entry that contains the database version in the SYSTEM table. Defaults to `database_version`, which contains the database version for Trac. FzW INSERT INTO {0} (name, value) VALUES (%s, %s) rNzO UPDATE {0} SET value=%s WHERE name=%s zUpgraded %s from %d to %d)rrrrr^r0info)rr}rcurrent_database_versionr"rrrr{s"  " z$DatabaseManager.set_database_versioncCsD||}||kr dS||krttd|d|jd|||dS)akChecks the database version to determine if an upgrade is needed. :param version: the expected integer database version. :param name: the name of the entry in the SYSTEM table that contains the database version. Defaults to `database_version`, which contains the database version for Trac. :return: `True` if the stored version is less than the expected version, `False` if it is equal to the expected version. :raises TracError: if the stored version is greater than the expected version. FzNeed to downgrade %(name)s.rz Need to upgrade %s from %d to %dT)r TracErrorrr0r)rr}rdbverrrr needs_upgrades zDatabaseManager.needs_upgrade trac.upgradesc Cs||}t|d|dD]E}d||f}zt|}Wnty,ttd|dw|jj}| } | |j|| | ||Wdn1sNwYqdS)a(Invokes `do_upgrade(env, version, cursor)` in module `"%s/db%i.py" % (pkg, version)`, for each required version upgrade. :param version: the expected integer database version. :param name: the name of the entry in the SYSTEM table that contains the database version. Defaults to `database_version`, which contains the database version for Trac. :param pkg: the package containing the upgrade modules. :raises TracError: if the package or module doesn't exist. z%s.db%izNo upgrade module %(module)s.py)moduleN) rrange importlib import_module ImportErrorrrrrrO do_upgrader{) rr}rpkgrirupgraderr"rOrrrupgrade s"    zDatabaseManager.upgradeNcCs(|jr|j||sd|_dSdSdSr)rwr)rtidrrrr%s   zDatabaseManager.shutdownc Cs|\}}|s>|j}tj|stj|jj|}|jdd}| dd\}}d||jj t t f}tj||}ntj |}tj|sOt|||S)zSave a backup of the database. :param dest: base filename to write to. Returns the file actually written. rqrr:rz %s.%i.%d.bak)ryrsosreisabsrrconfiggetsplitrrtimedirnameexistsmakedirsro) rrnr|rFrsdb_strdb_namedb_path dest_namerrrro+s        zDatabaseManager.backupcst|j\}fdd|jD}|sttddt|\}}|dkr*t|jdkrM|ddkr5ntj |dsMtj |j j|d d |d<|j rU|j|d <||fS) Ncs.g|]}|D] \}}|kr||fqqSr)rc)rr|scheme_priorityschemerr Dsz1DatabaseManager.get_connector..z&Unsupported database type "%(scheme)s"rrsqliterez:memory:/r0)parse_connection_uriconnection_uri connectorsrrmaxerrorrrerrrlstriprvr0)rrF candidatesrr|rrrryBs*       zDatabaseManager.get_connectorcCsdSrrrRrrrenvironment_createdbsz#DatabaseManager.environment_createdcCs |tjSr)rrrzrRrrrenvironment_needs_upgradees z)DatabaseManager.environment_needs_upgradecCr~r)rrrzrRrrrupgrade_environmenthrz#DatabaseManager.upgrade_environmentccs&|d}|D]}|Vq dSr)ryrp)rr|rrrrrpms   zDatabaseManager.get_system_info)F)r)rrr)-r%r&r'r( implementsrrExtensionPointrbrr rrsr rtrrvrrirrkrlrrrrr_rr1rrgrSrTrLrVr{rrrroryrrrrprrrrrsX     %        rcCs|jr dd|jDSgS)z1Retrieve column names from a cursor, if possible.cSs0g|]}t|dtrt|ddn|dqS)rzutf-8)rbytesstr)rdrrrrus(z$get_column_names..) description)rOrrrrLss rLc Cs|stjdtdddd}ttdtd|tdz |d d \}}Wn ty0t |w| d sE|d krA|rAd }|}n9t || dsSd }|d d }n%| drad }|dd }n|dd }d |vrt|d d \}}n|}d}d }|rd|vr|dd \}}d |vr|d d \}}nd }|rt j |}|rtt j |}nd }}|rd |vr|d d \}}zt|}Wn tyt |wd }|sd |}tjdkrt|d kr|d dkrd|d|dd f}i} d|vr.|dd \}} | d} | D]$} z | dd \} } Wn ty!t |wt j | } | | | <q td|||||| f}|dd|DfS)aVParse the database connection string. The database connection string for an environment is specified through the `database` option in the `[trac]` section of trac.ini. :return: a tuple containing the scheme and a dictionary of attributes: `user`, `password`, `host`, `port`, `path`, `params`. :since: 1.1.3 z[trac]zTracIni documentationtrac-target-newz3https://trac.edgewall.org/wiki/TracIni#trac-sectiontitleclass_hrefzDatabase connection string is empty. Set the %(option)s configuration option in the %(section)s section of trac.ini. Please refer to the %(doc)s for help.rr)optionsectiondocrrrrNz//z///@nt|z%s:%sr?&=)userpasswordhostportrer!cSsi|] \}}|r||qSrr)rkeyrrrr sz(parse_connection_uri..)rarrrcode _doc_db_strr ValueError_invalid_db_str startswithurllibparseunquoterrrrrzip)rrrrestrrerrrr!qsparamrrrFrrrrys                  rcCsttdt|tdS)NzcInvalid format %(db_str)s for the database connection string. Please refer to the %(doc)s for help.)rr)rrrrr)rrrrr s  r cCstjtdtddddS)N documentationz)Database Connection Strings documentationrz@https://trac.edgewall.org/wiki/TracIni#DatabaseConnectionStringsr)rrrrrrrrs r)/rrr urllib.parser abcrrrqrtrac.apirr trac.configrrr r trac.core trac.db.poolr trac.db.schemar trac.db.utilrtrac.util.concurrencyrtrac.util.htmlrtrac.util.textrtrac.util.translationrrobjectrr+r=r@ Interfacerb ComponentrrLrr rrrrrs8       [1xa