31
31
32
32
import os
33
33
import pathlib
34
+ import re
34
35
import shutil
35
36
import sys
36
37
87
88
),
88
89
]
89
90
90
- LONG_DESCRIPTION = """
91
- MySQL driver written in Python which does not depend on MySQL C client
92
- libraries and implements the DB API v2.0 specification (PEP-249).
93
- """
94
-
95
91
96
92
def main () -> None :
97
93
setup (
98
94
name = "mysql-connector-python" ,
99
95
version = VERSION_TEXT ,
100
- description = "MySQL driver written in Python" ,
101
- long_description = LONG_DESCRIPTION ,
96
+ description = (
97
+ "A self-contained Python driver for communicating with MySQL "
98
+ "servers, using an API that is compliant with the Python "
99
+ "Database API Specification v2.0 (PEP 249)."
100
+ ),
101
+ long_description = get_long_description (),
102
+ long_description_content_type = "text/x-rst" ,
102
103
author = "Oracle and/or its affiliates" ,
103
104
author_email = "" ,
104
105
license = "GNU GPLv2 (with FOSS License Exception)" ,
105
- keywords = "mysql db" ,
106
- url = "http://dev.mysql.com/doc/connector-python/en/index.html" ,
107
- download_url = "http://dev.mysql.com/downloads/connector/python/" ,
106
+ keywords = [
107
+ "mysql" ,
108
+ "database" ,
109
+ "db" ,
110
+ "connector" ,
111
+ "driver" ,
112
+ ],
113
+ project_urls = {
114
+ "Homepage" : "https://dev.mysql.com/doc/connector-python/en/index.html" ,
115
+ "Documentation" : "https://dev.mysql.com/doc/connector-python/en/index.html" ,
116
+ "Downloads" : "https://dev.mysql.com/downloads/connector/python/" ,
117
+ "Release Notes" : "https://dev.mysql.com/doc/relnotes/connector-python/en/" ,
118
+ "Source Code" : "https://github.com/mysql/mysql-connector-python" ,
119
+ "Bug System" : "https://bugs.mysql.com/" ,
120
+ "Slack" : "https://mysqlcommunity.slack.com/messages/connectors" ,
121
+ "Forums" : "https://forums.mysql.com/list.php?50" ,
122
+ "Blog" : "https://blogs.oracle.com/mysql/" ,
123
+ },
108
124
package_dir = {"" : "lib" },
109
125
packages = find_packages (where = "lib" ),
110
126
classifiers = [
111
127
"Development Status :: 5 - Production/Stable" ,
112
- "Environment :: Other Environment" ,
113
128
"Intended Audience :: Developers" ,
114
129
"Intended Audience :: Education" ,
115
- "Intended Audience :: Information Technology" ,
116
- "Intended Audience :: System Administrators" ,
117
130
"License :: OSI Approved :: GNU General Public License (GPL)" ,
118
- "Operating System :: OS Independent" ,
131
+ "Operating System :: MacOS :: MacOS X" ,
132
+ "Operating System :: Microsoft :: Windows" ,
133
+ "Operating System :: POSIX :: Linux" ,
134
+ "Operating System :: Unix" ,
119
135
"Programming Language :: Python :: 3" ,
120
- "Programming Language :: Python :: 3.8" ,
121
136
"Programming Language :: Python :: 3.9" ,
122
137
"Programming Language :: Python :: 3.10" ,
123
138
"Programming Language :: Python :: 3.11" ,
124
139
"Programming Language :: Python :: 3.12" ,
140
+ "Programming Language :: Python :: 3.13" ,
125
141
"Topic :: Database" ,
126
142
"Topic :: Software Development" ,
127
- "Topic :: Software Development :: Libraries :: Application Frameworks" ,
128
143
"Topic :: Software Development :: Libraries :: Python Modules" ,
144
+ "Typing :: Typed" ,
129
145
],
130
146
ext_modules = EXTENSIONS ,
131
147
cmdclass = COMMAND_CLASSES ,
132
- python_requires = ">=3.8 " ,
148
+ python_requires = ">=3.9 " ,
133
149
extras_require = {
134
150
"dns-srv" : ["dnspython==2.6.1" ],
135
151
"gssapi" : ["gssapi>=1.6.9,<=1.8.2" ],
@@ -151,6 +167,42 @@ def copy_metadata_files() -> None:
151
167
shutil .copy (pathlib .Path (os .getcwd (), f"../{ filename } " ), pathlib .Path (f"./" ))
152
168
153
169
170
+ def get_long_description () -> str :
171
+ """Extracts a long description from the README.rst file that is suited for this specific package.
172
+ """
173
+ with open (pathlib .Path (os .getcwd (), "../README.rst" )) as file_handle :
174
+ # The README.rst text is meant to be shared by both mysql and mysqlx packages, so after getting it we need to
175
+ # parse it in order to remove the bits of text that are not meaningful for this package (mysql)
176
+ long_description = file_handle .read ()
177
+ block_matches = re .finditer (
178
+ pattern = (
179
+ r'(?P<module_start>\.{2}\s+={2,}\s+(?P<module_tag>\<(?P<module_name>mysql|mysqlx|both)\>)(?P<repls>\s+'
180
+ r'\[(?:(?:,\s*)?(?:repl(?:-mysql(?:x)?)?)\("(?:[^"]+)",\s*"(?:[^"]*)"\))+\])?\s+={2,})'
181
+ r'(?P<block_text>.+?(?=\.{2}\s+={2,}))(?P<module_end>\.{2}\s+={2,}\s+\</(?P=module_name)\>\s+={2,})'
182
+ ),
183
+ string = long_description ,
184
+ flags = re .DOTALL )
185
+ for block_match in block_matches :
186
+ if block_match .group ("module_name" ) == 'mysqlx' :
187
+ long_description = long_description .replace (block_match .group (), "" )
188
+ else :
189
+ block_text = block_match .group ("block_text" )
190
+ if block_match .group ("repls" ):
191
+ repl_matches = re .finditer (pattern = r'(?P<repl_name>repl(?:-mysql(?:x)?)?)\("'
192
+ r'(?P<repl_source>[^"]+)",\s*"(?P<repl_target>[^"]*)"\)+' ,
193
+ string = block_match .group ("repls" ))
194
+ for repl_match in repl_matches :
195
+ repl_name = repl_match .group ("repl_name" )
196
+ repl_source = repl_match .group ("repl_source" )
197
+ repl_target = repl_match .group ("repl_target" )
198
+ if repl_target is None :
199
+ repl_target = ""
200
+ if repl_name == "repl" or repl_name .endswith ("mysql" ):
201
+ block_text = block_text .replace (repl_source , repl_target )
202
+ long_description = long_description .replace (block_match .group (), block_text )
203
+ return long_description
204
+
205
+
154
206
def remove_metadata_files () -> None :
155
207
"""Remove files copied by `copy_metadata_files()`"""
156
208
for filename in METADATA_FILES :
0 commit comments