diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-01-06 01:14:26 -0500 |
---|---|---|
committer | mike bayer <mike_mp@zzzcomputing.com> | 2019-01-06 17:34:50 +0000 |
commit | 1e1a38e7801f410f244e4bbb44ec795ae152e04e (patch) | |
tree | 28e725c5c8188bd0cfd133d1e268dbca9b524978 /lib/sqlalchemy/dialects/mysql/reflection.py | |
parent | 404e69426b05a82d905cbb3ad33adafccddb00dd (diff) | |
download | sqlalchemy-1e1a38e7801f410f244e4bbb44ec795ae152e04e.tar.gz |
Run black -l 79 against all source files
This is a straight reformat run using black as is, with no edits
applied at all.
The black run will format code consistently, however in
some cases that are prevalent in SQLAlchemy code it produces
too-long lines. The too-long lines will be resolved in the
following commit that will resolve all remaining flake8 issues
including shadowed builtins, long lines, import order, unused
imports, duplicate imports, and docstring issues.
Change-Id: I7eda77fed3d8e73df84b3651fd6cfcfe858d4dc9
Diffstat (limited to 'lib/sqlalchemy/dialects/mysql/reflection.py')
-rw-r--r-- | lib/sqlalchemy/dialects/mysql/reflection.py | 342 |
1 files changed, 190 insertions, 152 deletions
diff --git a/lib/sqlalchemy/dialects/mysql/reflection.py b/lib/sqlalchemy/dialects/mysql/reflection.py index e88bc3f42..d0513eb4d 100644 --- a/lib/sqlalchemy/dialects/mysql/reflection.py +++ b/lib/sqlalchemy/dialects/mysql/reflection.py @@ -36,16 +36,16 @@ class MySQLTableDefinitionParser(object): def parse(self, show_create, charset): state = ReflectedState() state.charset = charset - for line in re.split(r'\r?\n', show_create): - if line.startswith(' ' + self.preparer.initial_quote): + for line in re.split(r"\r?\n", show_create): + if line.startswith(" " + self.preparer.initial_quote): self._parse_column(line, state) # a regular table options line - elif line.startswith(') '): + elif line.startswith(") "): self._parse_table_options(line, state) # an ANSI-mode table options line - elif line == ')': + elif line == ")": pass - elif line.startswith('CREATE '): + elif line.startswith("CREATE "): self._parse_table_name(line, state) # Not present in real reflection, but may be if # loading from a file. @@ -55,11 +55,11 @@ class MySQLTableDefinitionParser(object): type_, spec = self._parse_constraints(line) if type_ is None: util.warn("Unknown schema content: %r" % line) - elif type_ == 'key': + elif type_ == "key": state.keys.append(spec) - elif type_ == 'fk_constraint': + elif type_ == "fk_constraint": state.fk_constraints.append(spec) - elif type_ == 'ck_constraint': + elif type_ == "ck_constraint": state.ck_constraints.append(spec) else: pass @@ -78,39 +78,39 @@ class MySQLTableDefinitionParser(object): # convert columns into name, length pairs # NOTE: we may want to consider SHOW INDEX as the # format of indexes in MySQL becomes more complex - spec['columns'] = self._parse_keyexprs(spec['columns']) - if spec['version_sql']: - m2 = self._re_key_version_sql.match(spec['version_sql']) - if m2 and m2.groupdict()['parser']: - spec['parser'] = m2.groupdict()['parser'] - if spec['parser']: - spec['parser'] = self.preparer.unformat_identifiers( - spec['parser'])[0] - return 'key', spec + spec["columns"] = self._parse_keyexprs(spec["columns"]) + if spec["version_sql"]: + m2 = self._re_key_version_sql.match(spec["version_sql"]) + if m2 and m2.groupdict()["parser"]: + spec["parser"] = m2.groupdict()["parser"] + if spec["parser"]: + spec["parser"] = self.preparer.unformat_identifiers( + spec["parser"] + )[0] + return "key", spec # FOREIGN KEY CONSTRAINT m = self._re_fk_constraint.match(line) if m: spec = m.groupdict() - spec['table'] = \ - self.preparer.unformat_identifiers(spec['table']) - spec['local'] = [c[0] - for c in self._parse_keyexprs(spec['local'])] - spec['foreign'] = [c[0] - for c in self._parse_keyexprs(spec['foreign'])] - return 'fk_constraint', spec + spec["table"] = self.preparer.unformat_identifiers(spec["table"]) + spec["local"] = [c[0] for c in self._parse_keyexprs(spec["local"])] + spec["foreign"] = [ + c[0] for c in self._parse_keyexprs(spec["foreign"]) + ] + return "fk_constraint", spec # CHECK constraint m = self._re_ck_constraint.match(line) if m: spec = m.groupdict() - return 'ck_constraint', spec + return "ck_constraint", spec # PARTITION and SUBPARTITION m = self._re_partition.match(line) if m: # Punt! - return 'partition', line + return "partition", line # No match. return (None, line) @@ -124,7 +124,7 @@ class MySQLTableDefinitionParser(object): regex, cleanup = self._pr_name m = regex.match(line) if m: - state.table_name = cleanup(m.group('name')) + state.table_name = cleanup(m.group("name")) def _parse_table_options(self, line, state): """Build a dictionary of all reflected table-level options. @@ -134,7 +134,7 @@ class MySQLTableDefinitionParser(object): options = {} - if not line or line == ')': + if not line or line == ")": pass else: @@ -143,17 +143,17 @@ class MySQLTableDefinitionParser(object): m = regex.search(rest_of_line) if not m: continue - directive, value = m.group('directive'), m.group('val') + directive, value = m.group("directive"), m.group("val") if cleanup: value = cleanup(value) options[directive.lower()] = value - rest_of_line = regex.sub('', rest_of_line) + rest_of_line = regex.sub("", rest_of_line) - for nope in ('auto_increment', 'data directory', 'index directory'): + for nope in ("auto_increment", "data directory", "index directory"): options.pop(nope, None) for opt, val in options.items(): - state.table_options['%s_%s' % (self.dialect.name, opt)] = val + state.table_options["%s_%s" % (self.dialect.name, opt)] = val def _parse_column(self, line, state): """Extract column details. @@ -167,29 +167,30 @@ class MySQLTableDefinitionParser(object): m = self._re_column.match(line) if m: spec = m.groupdict() - spec['full'] = True + spec["full"] = True else: m = self._re_column_loose.match(line) if m: spec = m.groupdict() - spec['full'] = False + spec["full"] = False if not spec: util.warn("Unknown column definition %r" % line) return - if not spec['full']: + if not spec["full"]: util.warn("Incomplete reflection of column definition %r" % line) - name, type_, args = spec['name'], spec['coltype'], spec['arg'] + name, type_, args = spec["name"], spec["coltype"], spec["arg"] try: col_type = self.dialect.ischema_names[type_] except KeyError: - util.warn("Did not recognize type '%s' of column '%s'" % - (type_, name)) + util.warn( + "Did not recognize type '%s' of column '%s'" % (type_, name) + ) col_type = sqltypes.NullType # Column type positional arguments eg. varchar(32) - if args is None or args == '': + if args is None or args == "": type_args = [] elif args[0] == "'" and args[-1] == "'": type_args = self._re_csv_str.findall(args) @@ -201,50 +202,51 @@ class MySQLTableDefinitionParser(object): if issubclass(col_type, (DATETIME, TIME, TIMESTAMP)): if type_args: - type_kw['fsp'] = type_args.pop(0) + type_kw["fsp"] = type_args.pop(0) - for kw in ('unsigned', 'zerofill'): + for kw in ("unsigned", "zerofill"): if spec.get(kw, False): type_kw[kw] = True - for kw in ('charset', 'collate'): + for kw in ("charset", "collate"): if spec.get(kw, False): type_kw[kw] = spec[kw] if issubclass(col_type, _EnumeratedValues): type_args = _EnumeratedValues._strip_values(type_args) - if issubclass(col_type, SET) and '' in type_args: - type_kw['retrieve_as_bitwise'] = True + if issubclass(col_type, SET) and "" in type_args: + type_kw["retrieve_as_bitwise"] = True type_instance = col_type(*type_args, **type_kw) col_kw = {} # NOT NULL - col_kw['nullable'] = True + col_kw["nullable"] = True # this can be "NULL" in the case of TIMESTAMP - if spec.get('notnull', False) == 'NOT NULL': - col_kw['nullable'] = False + if spec.get("notnull", False) == "NOT NULL": + col_kw["nullable"] = False # AUTO_INCREMENT - if spec.get('autoincr', False): - col_kw['autoincrement'] = True + if spec.get("autoincr", False): + col_kw["autoincrement"] = True elif issubclass(col_type, sqltypes.Integer): - col_kw['autoincrement'] = False + col_kw["autoincrement"] = False # DEFAULT - default = spec.get('default', None) + default = spec.get("default", None) - if default == 'NULL': + if default == "NULL": # eliminates the need to deal with this later. default = None - comment = spec.get('comment', None) + comment = spec.get("comment", None) if comment is not None: comment = comment.replace("\\\\", "\\").replace("''", "'") - col_d = dict(name=name, type=type_instance, default=default, - comment=comment) + col_d = dict( + name=name, type=type_instance, default=default, comment=comment + ) col_d.update(col_kw) state.columns.append(col_d) @@ -262,36 +264,44 @@ class MySQLTableDefinitionParser(object): buffer = [] for row in columns: - (name, col_type, nullable, default, extra) = \ - [row[i] for i in (0, 1, 2, 4, 5)] + (name, col_type, nullable, default, extra) = [ + row[i] for i in (0, 1, 2, 4, 5) + ] - line = [' '] + line = [" "] line.append(self.preparer.quote_identifier(name)) line.append(col_type) if not nullable: - line.append('NOT NULL') + line.append("NOT NULL") if default: - if 'auto_increment' in default: + if "auto_increment" in default: pass - elif (col_type.startswith('timestamp') and - default.startswith('C')): - line.append('DEFAULT') + elif col_type.startswith("timestamp") and default.startswith( + "C" + ): + line.append("DEFAULT") line.append(default) - elif default == 'NULL': - line.append('DEFAULT') + elif default == "NULL": + line.append("DEFAULT") line.append(default) else: - line.append('DEFAULT') + line.append("DEFAULT") line.append("'%s'" % default.replace("'", "''")) if extra: line.append(extra) - buffer.append(' '.join(line)) - - return ''.join([('CREATE TABLE %s (\n' % - self.preparer.quote_identifier(table_name)), - ',\n'.join(buffer), - '\n) ']) + buffer.append(" ".join(line)) + + return "".join( + [ + ( + "CREATE TABLE %s (\n" + % self.preparer.quote_identifier(table_name) + ), + ",\n".join(buffer), + "\n) ", + ] + ) def _parse_keyexprs(self, identifiers): """Unpack '"col"(2),"col" ASC'-ish strings into components.""" @@ -306,29 +316,39 @@ class MySQLTableDefinitionParser(object): _final = self.preparer.final_quote - quotes = dict(zip(('iq', 'fq', 'esc_fq'), - [re.escape(s) for s in - (self.preparer.initial_quote, - _final, - self.preparer._escape_identifier(_final))])) + quotes = dict( + zip( + ("iq", "fq", "esc_fq"), + [ + re.escape(s) + for s in ( + self.preparer.initial_quote, + _final, + self.preparer._escape_identifier(_final), + ) + ], + ) + ) self._pr_name = _pr_compile( - r'^CREATE (?:\w+ +)?TABLE +' - r'%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s +\($' % quotes, - self.preparer._unescape_identifier) + r"^CREATE (?:\w+ +)?TABLE +" + r"%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s +\($" % quotes, + self.preparer._unescape_identifier, + ) # `col`,`col2`(32),`col3`(15) DESC # self._re_keyexprs = _re_compile( - r'(?:' - r'(?:%(iq)s((?:%(esc_fq)s|[^%(fq)s])+)%(fq)s)' - r'(?:\((\d+)\))?(?: +(ASC|DESC))?(?=\,|$))+' % quotes) + r"(?:" + r"(?:%(iq)s((?:%(esc_fq)s|[^%(fq)s])+)%(fq)s)" + r"(?:\((\d+)\))?(?: +(ASC|DESC))?(?=\,|$))+" % quotes + ) # 'foo' or 'foo','bar' or 'fo,o','ba''a''r' - self._re_csv_str = _re_compile(r'\x27(?:\x27\x27|[^\x27])*\x27') + self._re_csv_str = _re_compile(r"\x27(?:\x27\x27|[^\x27])*\x27") # 123 or 123,456 - self._re_csv_int = _re_compile(r'\d+') + self._re_csv_int = _re_compile(r"\d+") # `colname` <type> [type opts] # (NOT NULL | NULL) @@ -356,43 +376,39 @@ class MySQLTableDefinitionParser(object): r"(?: +COLUMN_FORMAT +(?P<colfmt>\w+))?" r"(?: +STORAGE +(?P<storage>\w+))?" r"(?: +(?P<extra>.*))?" - r",?$" - % quotes + r",?$" % quotes ) # Fallback, try to parse as little as possible self._re_column_loose = _re_compile( - r' ' - r'%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s +' - r'(?P<coltype>\w+)' - r'(?:\((?P<arg>(?:\d+|\d+,\d+|\x27(?:\x27\x27|[^\x27])+\x27))\))?' - r'.*?(?P<notnull>(?:NOT )NULL)?' - % quotes + r" " + r"%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s +" + r"(?P<coltype>\w+)" + r"(?:\((?P<arg>(?:\d+|\d+,\d+|\x27(?:\x27\x27|[^\x27])+\x27))\))?" + r".*?(?P<notnull>(?:NOT )NULL)?" % quotes ) # (PRIMARY|UNIQUE|FULLTEXT|SPATIAL) INDEX `name` (USING (BTREE|HASH))? # (`col` (ASC|DESC)?, `col` (ASC|DESC)?) # KEY_BLOCK_SIZE size | WITH PARSER name /*!50100 WITH PARSER name */ self._re_key = _re_compile( - r' ' - r'(?:(?P<type>\S+) )?KEY' - r'(?: +%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s)?' - r'(?: +USING +(?P<using_pre>\S+))?' - r' +\((?P<columns>.+?)\)' - r'(?: +USING +(?P<using_post>\S+))?' - r'(?: +KEY_BLOCK_SIZE *[ =]? *(?P<keyblock>\S+))?' - r'(?: +WITH PARSER +(?P<parser>\S+))?' - r'(?: +COMMENT +(?P<comment>(\x27\x27|\x27([^\x27])*?\x27)+))?' - r'(?: +/\*(?P<version_sql>.+)\*/ +)?' - r',?$' - % quotes + r" " + r"(?:(?P<type>\S+) )?KEY" + r"(?: +%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s)?" + r"(?: +USING +(?P<using_pre>\S+))?" + r" +\((?P<columns>.+?)\)" + r"(?: +USING +(?P<using_post>\S+))?" + r"(?: +KEY_BLOCK_SIZE *[ =]? *(?P<keyblock>\S+))?" + r"(?: +WITH PARSER +(?P<parser>\S+))?" + r"(?: +COMMENT +(?P<comment>(\x27\x27|\x27([^\x27])*?\x27)+))?" + r"(?: +/\*(?P<version_sql>.+)\*/ +)?" + r",?$" % quotes ) # https://forums.mysql.com/read.php?20,567102,567111#msg-567111 # It means if the MySQL version >= \d+, execute what's in the comment self._re_key_version_sql = _re_compile( - r'\!\d+ ' - r'(?: *WITH PARSER +(?P<parser>\S+) *)?' + r"\!\d+ " r"(?: *WITH PARSER +(?P<parser>\S+) *)?" ) # CONSTRAINT `name` FOREIGN KEY (`local_col`) @@ -402,20 +418,19 @@ class MySQLTableDefinitionParser(object): # # unique constraints come back as KEYs kw = quotes.copy() - kw['on'] = 'RESTRICT|CASCADE|SET NULL|NOACTION' + kw["on"] = "RESTRICT|CASCADE|SET NULL|NOACTION" self._re_fk_constraint = _re_compile( - r' ' - r'CONSTRAINT +' - r'%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s +' - r'FOREIGN KEY +' - r'\((?P<local>[^\)]+?)\) REFERENCES +' - r'(?P<table>%(iq)s[^%(fq)s]+%(fq)s' - r'(?:\.%(iq)s[^%(fq)s]+%(fq)s)?) +' - r'\((?P<foreign>[^\)]+?)\)' - r'(?: +(?P<match>MATCH \w+))?' - r'(?: +ON DELETE (?P<ondelete>%(on)s))?' - r'(?: +ON UPDATE (?P<onupdate>%(on)s))?' - % kw + r" " + r"CONSTRAINT +" + r"%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s +" + r"FOREIGN KEY +" + r"\((?P<local>[^\)]+?)\) REFERENCES +" + r"(?P<table>%(iq)s[^%(fq)s]+%(fq)s" + r"(?:\.%(iq)s[^%(fq)s]+%(fq)s)?) +" + r"\((?P<foreign>[^\)]+?)\)" + r"(?: +(?P<match>MATCH \w+))?" + r"(?: +ON DELETE (?P<ondelete>%(on)s))?" + r"(?: +ON UPDATE (?P<onupdate>%(on)s))?" % kw ) # CONSTRAINT `CONSTRAINT_1` CHECK (`x` > 5)' @@ -423,18 +438,17 @@ class MySQLTableDefinitionParser(object): # is returned on a line by itself, so to match without worrying # about parenthesis in the expresion we go to the end of the line self._re_ck_constraint = _re_compile( - r' ' - r'CONSTRAINT +' - r'%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s +' - r'CHECK +' - r'\((?P<sqltext>.+)\),?' - % kw + r" " + r"CONSTRAINT +" + r"%(iq)s(?P<name>(?:%(esc_fq)s|[^%(fq)s])+)%(fq)s +" + r"CHECK +" + r"\((?P<sqltext>.+)\),?" % kw ) # PARTITION # # punt! - self._re_partition = _re_compile(r'(?:.*)(?:SUB)?PARTITION(?:.*)') + self._re_partition = _re_compile(r"(?:.*)(?:SUB)?PARTITION(?:.*)") # Table-level options (COLLATE, ENGINE, etc.) # Do the string options first, since they have quoted @@ -442,44 +456,68 @@ class MySQLTableDefinitionParser(object): for option in _options_of_type_string: self._add_option_string(option) - for option in ('ENGINE', 'TYPE', 'AUTO_INCREMENT', - 'AVG_ROW_LENGTH', 'CHARACTER SET', - 'DEFAULT CHARSET', 'CHECKSUM', - 'COLLATE', 'DELAY_KEY_WRITE', 'INSERT_METHOD', - 'MAX_ROWS', 'MIN_ROWS', 'PACK_KEYS', 'ROW_FORMAT', - 'KEY_BLOCK_SIZE'): + for option in ( + "ENGINE", + "TYPE", + "AUTO_INCREMENT", + "AVG_ROW_LENGTH", + "CHARACTER SET", + "DEFAULT CHARSET", + "CHECKSUM", + "COLLATE", + "DELAY_KEY_WRITE", + "INSERT_METHOD", + "MAX_ROWS", + "MIN_ROWS", + "PACK_KEYS", + "ROW_FORMAT", + "KEY_BLOCK_SIZE", + ): self._add_option_word(option) - self._add_option_regex('UNION', r'\([^\)]+\)') - self._add_option_regex('TABLESPACE', r'.*? STORAGE DISK') + self._add_option_regex("UNION", r"\([^\)]+\)") + self._add_option_regex("TABLESPACE", r".*? STORAGE DISK") self._add_option_regex( - 'RAID_TYPE', - r'\w+\s+RAID_CHUNKS\s*\=\s*\w+RAID_CHUNKSIZE\s*=\s*\w+') + "RAID_TYPE", + r"\w+\s+RAID_CHUNKS\s*\=\s*\w+RAID_CHUNKSIZE\s*=\s*\w+", + ) - _optional_equals = r'(?:\s*(?:=\s*)|\s+)' + _optional_equals = r"(?:\s*(?:=\s*)|\s+)" def _add_option_string(self, directive): - regex = (r'(?P<directive>%s)%s' - r"'(?P<val>(?:[^']|'')*?)'(?!')" % - (re.escape(directive), self._optional_equals)) - self._pr_options.append(_pr_compile( - regex, lambda v: v.replace("\\\\", "\\").replace("''", "'") - )) + regex = r"(?P<directive>%s)%s" r"'(?P<val>(?:[^']|'')*?)'(?!')" % ( + re.escape(directive), + self._optional_equals, + ) + self._pr_options.append( + _pr_compile( + regex, lambda v: v.replace("\\\\", "\\").replace("''", "'") + ) + ) def _add_option_word(self, directive): - regex = (r'(?P<directive>%s)%s' - r'(?P<val>\w+)' % - (re.escape(directive), self._optional_equals)) + regex = r"(?P<directive>%s)%s" r"(?P<val>\w+)" % ( + re.escape(directive), + self._optional_equals, + ) self._pr_options.append(_pr_compile(regex)) def _add_option_regex(self, directive, regex): - regex = (r'(?P<directive>%s)%s' - r'(?P<val>%s)' % - (re.escape(directive), self._optional_equals, regex)) + regex = r"(?P<directive>%s)%s" r"(?P<val>%s)" % ( + re.escape(directive), + self._optional_equals, + regex, + ) self._pr_options.append(_pr_compile(regex)) -_options_of_type_string = ('COMMENT', 'DATA DIRECTORY', 'INDEX DIRECTORY', - 'PASSWORD', 'CONNECTION') + +_options_of_type_string = ( + "COMMENT", + "DATA DIRECTORY", + "INDEX DIRECTORY", + "PASSWORD", + "CONNECTION", +) def _pr_compile(regex, cleanup=None): |