U Yzf_Rz-@sdZddlZddlZddlZddlZddlmZddlmZm Z m Z m Z m Z m Z ddlmZmZddlmZmZmZmZmZmZddlmZmZmZmZdd lmZdd lmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)dd l*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2dd l3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;mZ>m?Z?m@Z@mAZAmBZBdd lCmDZCeEdZFeEdejGZHeEdejGZIeEdZJddddddgZKeKddddddddd d!d"d#d$d%gZLeMeNOePd&ZQd'ZRd(ZSd)d*d+d,gZd-ZTeUed.rejVrd/ZTd0d1ZWd2d3ZXd4d5ZYdod6d7ZZd8d9Z[d:d;Z\dd?Z^d@dAZ_dBdCZ`dDdEdCdAdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdng-ZadS)pz$MySQL X DevAPI Python implementationN) constants) INT_TYPES STRING_TYPESJSONDecodeErrorurlparseunquote parse_qsl)ClientSession)AuthLockContentionOPENSSL_CS_NAMESSSLMode TLS_VERSIONSTLS_CIPHER_SUITES)Schema CollectionTableView)DbDoc) ErrorInterfaceError DatabaseErrorNotSupportedError DataErrorIntegrityErrorProgrammingErrorOperationalError InternalError PoolError TimeoutError)ColumnRowResultBufferingResult RowResult SqlResult DocResult ColumnType) StatementFilterableStatement SqlStatement FindStatement AddStatementRemoveStatementModifyStatementSelectStatementInsertStatementDeleteStatementUpdateStatementCreateCollectionIndexStatementExpr ReadStatementWriteStatement) ExprParserz,(?![^\(\)]*\))z!^\(address=(.+),priority=(\d+)\)$z^\(address=(.+)[,]*\)$z"^([a-zA-Z][a-zA-Z0-9+\-.]+)://(.*)ssl-certssl-cassl-keyssl-crl tls-versionstls-ciphersuitesuserpasswordschemahostportrouterssocketssl-modeauthzuse-pureconnect-timeoutconnection-attributes compressiondns-srvzVThe '{list}' list must not contain repeated values, the value '{value}' is duplicated.zdThe given tls-version: '{}' is not recognized as a valid TLS protocol version (should be one of {}).zINo supported TLS protocol version found in the 'tls-versions' list '{}'. TLSv1zTLSv1.1zTLSv1.2TLSv1.3F HAS_TLSv1_3Tc Cs|dd}d|ko.|ddko.|ddk oD|doD|d}g}t|r^|ddn|}d }|D]}i}t|}|r|d}t |d |d <|d7}n t |}|r|d}d |d <t d |}|j std |z|j|j |jdWn4tk r4}ztd |dW5d}~XYnX||qld |kr^t|krlnn tdd|rzd|iS|d S)zParses a list of host, port pairs Args: path: String containing a list of routers or just router Returns: Returns a dict with parsed values of host, port and priority if specified.  ,:r[]rprioritydz//{0}zInvalid address: {0})rCrDzInvalid URI: {0}iNz\You must either assign no priority to any of the routers or give a priority for every routerirE)replacecount startswithendswith _SPLIT_REsplit _PRIORITY_REmatchgroupint _ROUTER_RErformathostnamerupdaterD ValueErrorrappendlen) patharrayrEZ address_listZpriority_countaddressrouterraerrrpg/private/var/folders/n9/53xbvtmd7sjg1q1l55xmpg58n4mgng/T/pip-unpacked-wheel-47tvuv7y/mysqlx/__init__.py_parse_address_listYsF       "  rrcCsddi}t|}|r|nd|f\}}|dkr@td||dkrPd|d<|d d d d \}}|d d d d \}}|d }||d ddkr|dkr|d d\}|d<| d}|r|rd|krtd|| dd\} } t | t | |d<|d<| dr(t ||d<n$| dr>tdn| t|d} t|dD]\} } | dd}|| krtd| ||krtd| |tkrt | d||<n8| }|d krd||<n|d!krd"||<n|||<qZ|S)#aParses the connection string and returns a dictionary with the connection settings. Args: uri: mysqlx URI scheme to connect to a MySQL server/farm. Returns: Returns a dict with parsed values of credentials and address of the MySQL server/farm. Raises: :class:`mysqlx.InterfaceError`: If contains a duplicate option or URI scheme is not valid. rBrQmysqlx)rs mysqlx+srvzScheme '{0}' is not validrtTrL@NrW?/)rVrrz()rSzMalformed URI '{0}'r@rA)rwz...rFz\.zWindows Pipe is not supported)r@rArL_-zInvalid option: '{0}'zDuplicate option: '{0}')1true)0falseF)_URI_SCHEME_REragroupsrre partitionrfindfindrsplitstripr_rr\rgrrr rZlower _SSL_OPTS)urisettingsraschemeuserinfotmprCZ query_strposr@rAZinvalid_optionskeyvaloptZval_strrprprq_parse_connection_urisL              rc s&tt}|r*tdd|dkrLdD]}t|dq:ndkr\tdkrz"dd<t dWn*t t fk rtddYnXdt j krtfdd tDrtd d krd krtd dkrdkrtdd kr<dt jt jfkrsz%_validate_settings..z)SSL options used with ssl-mode 'disabled'r=r;zCA Certificate not providedr<r:zClient Certificate not providedzCannot verify Server without CAz$Must verify Server if CA is providedrHzInvalid Auth '{0}'rK) preferredrequireddisabledzThe connection property 'compression' acceptable values are: 'preferred', 'required', or 'disabled'. The value '{0}' is not acceptablerJrIrzEThe connection timeout value must be a positive integer (including 0)rLz(The value of 'dns-srv' must be a booleanrFzr?N)setkeys difference _SESS_OPTSrrejoin_validate_hostsrrindexAttributeErrorrhZDISABLEDanyrgetZVERIFY_IDENTITYZ VERIFY_CAr rvalidate_connection_attributes isinstancerrcr TypeErrorboolvalidate_tls_versionsvalidate_tls_ciphersuites)rZ invalid_optsrnrKrprrq_validate_settingss                  rcCsd|kr|drz6t|d|d<|ddks:|ddkrDtddWnDtk rdtddYn(tk rtd|ddYnXd|kr|drzt|d|d<Wqtk rtd YqXnd |kr|r||d<d S) zValidate hosts. Args: settings (dict): Settings dictionary. default_port (int): Default connection port. Raises: :class:`mysqlx.InterfaceError`: If priority or port are invalid. rXrrYz1Invalid priority value, must be between 0 and 100izInvalid priorityzInvalid priority: {}rDz Invalid portrCN)rcr NameErrorrhrer)r default_portrprprqr0s*    rc Csi}d|krdS|d}t|tr|dkr6i|d<dS|drJ|dsb|dkrbtd|n|dkr|dkr|d |d<ni|d<dS|d d d }|D]X}|dkrq|d }|d}t|d kr|d nd}||krtd|q|||<qn"t|tr:|D]*}||}t|ts,t |}|||<q nt|t sP|dkrl|r`i|d<nd |d<dSt|t r|D]}d||<q|nt|t r|D]b}|dkrq|d }|d}t|d kr|d nd}||krtd|n|||<qnt|t std||r|D]}||}t|tsNtd|t|dkrjtd||drtd|t|tstd||t|dkr(td||q(||d<dS)zValidate connection-attributes. Args: settings (dict): Settings dictionary. Raises: :class:`mysqlx.InterfaceError`: If attribute name or value exceeds size. rJNrQrTrU)FalserTruer}z`The value of 'connection-attributes' must be a boolean or a list of key-value pairs, found: '{}')rrFrrVrR=rz0Duplicate key '{}' used in connection-attributes)rrzOconnection-attributes must be Boolean or a list of key-value pairs, found: '{}'z(Attribute name '{}' must be a stringtype z4Attribute name '{}' exceeds 32 characters limit sizerzzEKey names in connection-attributes cannot start with '_', found: '{}'z0Attribute '{}' value: '{}' must be a string typeiz=Attribute '{}' value: '{}' exceeds 1024 characters limit size) rrr\r]rrer_rjdictreprrrlist) r attributesZ conn_attrsZconn_attributesattrZ attr_name_val attr_nameZattr_val attr_valuerprprqrOs                 rcCsg}d|krdS|d}t|tr|dr6|dsFtd|nl|ddd}|D]T}|}|d krrq\|tkrtt |tq\||krtt jd |d | |q\nt|t r|std |D]F}|tkrtt |tq||kr tt jd |d q| |qnVt|t rZ|D],}|tkrJtt |tn | |q*ntd dt||s~td |dgkrtstt|t||d<dS)zValidate tls-versions. Args: settings (dict): Settings dictionary. Raises: :class:`mysqlx.InterfaceError`: If tls-versions name is not valid. r>NrTrUz(tls-versions must be a list, found: '{}'rrVrRrQ tls_versionsrvaluezKAt least one TLS protocol version must be specified in 'tls-versions' list.zMtls-versions should be a list with one or more of versions in {}. found: '{}'z, rN)rrr\r]rrer_rrTLS_VERSION_ERRORDUPLICATED_IN_LIST_ERRORrirrrTLS_V1_3_SUPPORTEDTLS_VER_NO_SUPPORTED)rrZtls_versions_settingsZtls_verstls_verZ tls_versionrprprqrsz        rc Csg}d|krdS|d}t|tr|dr6|dsFtd|q|ddd}|sdtd |D]}|}|rh| |qhnLt|t rd d |D}n2t|t r|D]}|r| |qntd || d ddkrt ddn|d dd}|jdd|d}g}i}g} t dt |dD]"} |t| | t| q8|D]p} d| kr| | kr| | nJ| |kr|| } | |krttjd| dn | | ntd| q`|std ||d<dS)zValidate tls-ciphersuites. Args: settings (dict): Settings dictionary. Raises: :class:`mysqlx.InterfaceError`: If tls-ciphersuites name is not valid. r?NrTrUz,tls-ciphersuites must be a list, found: '{}'rrVrRz;No valid cipher suite found in the 'tls-ciphersuites' list.cSsg|] }|r|qSrprp)rtls_csrprprq #sz-validate_tls_ciphersuites..zLtls-ciphersuites should be a list with one or more ciphersuites. Found: '{}'r>T)reverserr{tls_ciphersuitesrz;The value '{}' in cipher suites is not a valid cipher suite)rrr\r]rrer_rupperrirrrrsortrrgrextendrrr) rrZtls_ciphersuites_settingsZtls_cssrrZ newer_tls_verZtranslated_namesZiani_cipher_suites_namesZossl_cipher_suites_namesrnameZtranslated_namerprprqrsz            rcOsi}|rZt|dtr$t|d}qt|dtr|dD]\}}|||dd<q>n&|r|D]\}}|||dd<qf|stdt||S)aZParses the connection string and returns a dictionary with the connection settings. Args: *args: Variable length argument list with the connection data used to connect to the database. It can be a dictionary or a connection string. **kwargs: Arbitrary keyword arguments with connection data used to connect to the database. Returns: mysqlx.Session: Session object. Raises: TypeError: If connection timeout is not a positive integer. :class:`mysqlx.InterfaceError`: If settings not provided. rrzr{zSettings not provided)rrrritemsrZrr)argskwargsrrrrprprq_get_connection_settingsXsrcOst||}t|S)aCreates a Session instance using the provided connection data. Args: *args: Variable length argument list with the connection data used to connect to a MySQL server. It can be a dictionary or a connection string. **kwargs: Arbitrary keyword arguments with connection data used to connect to the database. Returns: mysqlx.Session: Session object. )rr )rrrrprprq get_session|s rcCsTt|ttfstdt|}t|ttfs4tdt|trlzt|}Wqtk rhtdYqXn&i}|D]\}}||| dd<qxt|tstdi}d|krJ| d}t|tstd| dd |d<| d d |d <| d d |d <| dd |d<t |d kr*td |t |d krJtd | t||S)a8Creates a Client instance with the provided connection data and settings. Args: connection_string: A string or a dict type object to indicate the connection data used to connect to a MySQL server. The string must have the following uri format:: cnx_str = 'mysqlx://{user}:{pwd}@{host}:{port}' cnx_str = ('mysqlx://{user}:{pwd}@[' ' (address={host}:{port}, priority=n),' ' (address={host}:{port}, priority=n), ...]' ' ?[option=value]') And the dictionary:: cnx_dict = { 'host': 'The host where the MySQL product is running', 'port': '(int) the port number configured for X protocol', 'user': 'The user name account', 'password': 'The password for the given user account', 'ssl-mode': 'The flags for ssl mode in mysqlx.SSLMode.FLAG', 'ssl-ca': 'The path to the ca.cert' "connect-timeout": '(int) milliseconds to wait on timeout' } options_string: A string in the form of a document or a dictionary type with configuration for the client. Current options include:: options = { 'pooling': { 'enabled': (bool), # [True | False], True by default 'max_size': (int), # Maximum connections per pool "max_idle_time": (int), # milliseconds that a # connection will remain active while not in use. # By default 0, means infinite. "queue_timeout": (int), # milliseconds a request will # wait for a connection to become available. # By default 0, means infinite. } } Returns: mysqlx.Client: Client object. .. versionadded:: 8.0.13 z(connection_data must be a string or dictz+connection_options must be a string or dictzA'pooling' options must be given in the form of a document or dictr{rzZpoolingz<'pooling' options must be given in the form document or dictZenabledTmax_sizeZ max_idle_timerZ queue_timeoutz Unrecognized pooling options: {}z#Unrecognized connection options: {})rrrrrjsonloadsrrrZpoprjrerr )Zconnection_stringZoptions_stringZ settings_dictZ options_dictrrZpooling_options_dictZpooling_optionsrprprq get_clientsF2       rr r exprr r rrrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)rr*r+r,r-r.r/r0r1r2r3r4r5r6)N)b__doc__rerloggingsslrQrcompatrrrrrr connectionr r r r rrrrZcrudrrrrZdbdocrerrorsrrrrrrrrrr r!resultr"r#r$r%r&r'r(r)Z statementr*r+r,r-r.r/r0r1r2r3r4r5r6r7r8rr9compiler^VERBOSEr`rdrrr getLogger__name__ addHandler NullHandlerrrrrhasattrrOrrrrrrrrrrr__all__rprprprqs    4(D      3Bb mIS$d