diff --git a/setup.py b/setup.py index 1ad6e57..185da02 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ from distutils.cmd import Command from distutils.dir_util import remove_tree from distutils import log -import os, os.path, re, hashlib, urllib2, cStringIO, zipfile +import os, os.path, re, hashlib, urllib.request, urllib.error, urllib.parse, io, zipfile def get_version(): @@ -111,7 +111,7 @@ def run(self): if os.path.exists(target): continue log.info("downloading vendor package '%s'" % url) - stream = urllib2.urlopen(url) + stream = urllib.request.urlopen(url) data = stream.read() stream.close() assert hashlib.md5(data).hexdigest() == md5_hash @@ -121,7 +121,7 @@ def run(self): remove_tree(build_dir) os.makedirs(build_dir) if url.endswith('.zip'): - archive = zipfile.ZipFile(cStringIO.StringIO(data)) + archive = zipfile.ZipFile(io.StringIO(data)) entries = archive.infolist() assert entries common = entries[0].filename diff --git a/src/htsql/core/__init__.py b/src/htsql/core/__init__.py index 2673d88..1f514a6 100644 --- a/src/htsql/core/__init__.py +++ b/src/htsql/core/__init__.py @@ -72,12 +72,12 @@ def validate(self): raise ValueError("database address is not specified") try: connect().release() - except Error, exc: + except Error as exc: raise ValueError("failed to establish database connection: %s" % exc) try: introspect() - except Error, exc: + except Error as exc: raise ValueError("failed to introspect the database: %s" % exc) diff --git a/src/htsql/core/adapter.py b/src/htsql/core/adapter.py index 79332bd..1ec80b1 100644 --- a/src/htsql/core/adapter.py +++ b/src/htsql/core/adapter.py @@ -41,12 +41,12 @@ class __metaclass__(type): def __new__(mcls, name, bases, content): # Iterate over all values in the class namespace. - for value in content.values(): + for value in list(content.values()): # Ignore non-function attributes. if not isinstance(value, types.FunctionType): continue # Update the code name and regenerate the code object. - code = value.func_code + code = value.__code__ code_name = code.co_name if '.' in code_name: continue @@ -59,7 +59,7 @@ def __new__(mcls, name, bases, content): code.co_firstlineno, code.co_lnotab, code.co_freevars, code.co_cellvars) # Patch the function object. - value.func_code = code + value.__code__ = code # Create the class. return type.__new__(mcls, name, bases, content) @@ -161,7 +161,7 @@ def __realize__(interface, dispatch_key): # Now we need to order the implementations unambiguously. try: implementations = toposort(implementations, order, is_total=True) - except RuntimeError, exc: + except RuntimeError as exc: # We intercept exceptions to provide a nicer error message. # `message` is an explanation we discard; `conflict` is a list # of implementations which either form a domination loop or diff --git a/src/htsql/core/application.py b/src/htsql/core/application.py index 6a56ca6..b37af10 100644 --- a/src/htsql/core/application.py +++ b/src/htsql/core/application.py @@ -154,7 +154,7 @@ def __init__(self, db, *extensions): value = configuration[addon_name][parameter.attribute] try: value = parameter.validator(value) - except ValueError, exc: + except ValueError as exc: raise ImportError("invalid parameter %r" " of addon %r: %s" % (parameter.attribute, @@ -181,7 +181,7 @@ def __init__(self, db, *extensions): for addon in self.addons: try: addon.validate() - except ValueError, exc: + except ValueError as exc: raise ImportError("failed to initialize %r: %s" % (addon.name, exc)) diff --git a/src/htsql/core/classify.py b/src/htsql/core/classify.py index b01dae8..4c37843 100644 --- a/src/htsql/core/classify.py +++ b/src/htsql/core/classify.py @@ -197,7 +197,7 @@ def __call__(self): table = self.arc.table yield table.name, table.schema.priority if table.schema.name: - name = u"%s %s" % (table.schema.name, table.name) + name = "%s %s" % (table.schema.name, table.name) yield name, -1 @@ -213,7 +213,7 @@ class CallChain(Call): adapt(ChainArc) - path_word = u"via" + path_word = "via" def __call__(self): is_primary = True @@ -238,7 +238,7 @@ def __call__(self): origin_name = foreign_key.origin_columns[-1].name target_name = foreign_key.target_columns[-1].name if origin_name.endswith(target_name): - prefix = origin_name[:-len(target_name)].rstrip(u' _-') + prefix = origin_name[:-len(target_name)].rstrip(' _-') if not prefix: prefix = target column = origin_name @@ -250,10 +250,10 @@ def __call__(self): else: yield target, 3 if not is_direct and prefix: - name = u"%s %s %s" % (target, self.path_word, prefix) + name = "%s %s %s" % (target, self.path_word, prefix) yield name, 2 if not is_direct and column: - name = u"%s %s %s" % (target, self.path_word, column) + name = "%s %s %s" % (target, self.path_word, column) yield name, 1 diff --git a/src/htsql/core/cmd/act.py b/src/htsql/core/cmd/act.py index 00ab6f1..e7238f7 100644 --- a/src/htsql/core/cmd/act.py +++ b/src/htsql/core/cmd/act.py @@ -113,7 +113,7 @@ def __call__(self): def act(command, action): - assert isinstance(command, (Command, Syntax, unicode, str)) + assert isinstance(command, (Command, Syntax, str)) assert isinstance(action, Action) if not isinstance(command, Command): command = recognize(command) diff --git a/src/htsql/core/cmd/command.py b/src/htsql/core/cmd/command.py index d0590c7..05515b9 100644 --- a/src/htsql/core/cmd/command.py +++ b/src/htsql/core/cmd/command.py @@ -15,7 +15,7 @@ class Command(object): class UniversalCmd(Command): def __init__(self, query): - assert isinstance(query, (str, unicode)) + assert isinstance(query, str) self.query = query diff --git a/src/htsql/core/cmd/embed.py b/src/htsql/core/cmd/embed.py index e1df8bb..be771e5 100644 --- a/src/htsql/core/cmd/embed.py +++ b/src/htsql/core/cmd/embed.py @@ -35,7 +35,7 @@ def __call__(self): class EmbedUntyped(Embed): - adapt_many(str, unicode) + adapt_many(str, str) def __call__(self): data = self.data @@ -45,7 +45,7 @@ def __call__(self): except UnicodeDecodeError: raise TypeError("a string is expected to be encoded in UTF-8:" " %s" % repr(data)) - if u"\0" in data: + if "\0" in data: raise TypeError("a string should not contain a NIL character:" " %s" % repr(data)) return Value(UntypedDomain(), data) @@ -53,7 +53,7 @@ def __call__(self): class EmbedNull(Embed): - adapt(types.NoneType) + adapt(type(None)) def __call__(self): return Value(UntypedDomain(), None) @@ -69,7 +69,7 @@ def __call__(self): class EmbedInteger(Embed): - adapt_many(int, long) + adapt_many(int, int) def __call__(self): return Value(IntegerDomain(), self.data) diff --git a/src/htsql/core/cmd/summon.py b/src/htsql/core/cmd/summon.py index 8b826dd..3fcc74c 100644 --- a/src/htsql/core/cmd/summon.py +++ b/src/htsql/core/cmd/summon.py @@ -167,7 +167,7 @@ def __call__(self): def recognize(syntax): - assert isinstance(syntax, (Syntax, unicode, str)) + assert isinstance(syntax, (Syntax, str)) if not isinstance(syntax, Syntax): syntax = parse(syntax) command = Recognize.__invoke__(syntax) diff --git a/src/htsql/core/connect.py b/src/htsql/core/connect.py index 3489586..f98e49f 100644 --- a/src/htsql/core/connect.py +++ b/src/htsql/core/connect.py @@ -175,7 +175,7 @@ def execute(self, statement, *parameters): try: with self.guard: return self.cursor.execute(statement, *parameters) - except Error, exc: + except Error as exc: exc.wrap("While executing SQL", statement) if parameters: parameters = parameters[0] @@ -194,7 +194,7 @@ def executemany(self, statement, parameters_set): try: with self.guard: return self.cursor.executemany(statement, parameters_set) - except Error, exc: + except Error as exc: exc.wrap("While executing SQL", statement) if not parameters_set: exc.wrap("With no parameters") @@ -245,7 +245,7 @@ def __iter__(self): while True: with self.guard: try: - row = iterator.next() + row = next(iterator) except StopIteration: row = None if row is None: diff --git a/src/htsql/core/domain.py b/src/htsql/core/domain.py index 87de07f..ffda73c 100644 --- a/src/htsql/core/domain.py +++ b/src/htsql/core/domain.py @@ -65,7 +65,7 @@ def parse(text): *Returns* A native Python object representing the same value. """ - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` values are passed through. if text is None: @@ -92,7 +92,7 @@ def dump(data): def __unicode__(self): # The class name with `Domain` suffix stripped, in lower case. - return unicode(self.__class__) + return str(self.__class__) # @@ -147,7 +147,7 @@ def __getitem__(self, key): raise TypeError("not a list value") return self.data[key] - def __nonzero__(self): + def __bool__(self): return bool(self.data) @@ -171,7 +171,7 @@ def __init__(self, domain, **attributes): self.attributes = attributes def __unicode__(self): - return unicode(self.domain) + return str(self.domain) class Product(Value): @@ -253,14 +253,14 @@ class UntypedDomain(Domain): @staticmethod def parse(text): # Sanity check on the argument. - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # No conversion is required. return text @staticmethod def dump(data): # Sanity check on the argument. - assert isinstance(data, maybe(unicode)) + assert isinstance(data, maybe(str)) # No conversion is required. return data @@ -278,14 +278,14 @@ class BooleanDomain(Domain): @staticmethod def parse(text): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` -> `None`, `'true'` -> `True`, `'false'` -> `False`. if text is None: return None - if text == u'true': + if text == 'true': return True - if text == u'false': + if text == 'false': return False raise ValueError("invalid Boolean literal: expected 'true' or 'false';" " got %r" % text.encode('utf-8')) @@ -298,9 +298,9 @@ def dump(data): if data is None: return None if data is True: - return u'true' + return 'true' if data is False: - return u'false' + return 'false' class NumberDomain(Domain): @@ -350,7 +350,7 @@ def __basis__(self): @staticmethod def parse(text): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `null` is represented by `None` in both forms. if text is None: return None @@ -364,12 +364,12 @@ def parse(text): return data def dump(self, data): - assert isinstance(data, maybe(oneof(int, long))) + assert isinstance(data, maybe(oneof(int, int))) # `null` is represented by `None` in both forms. if data is None: return None # Represent the value as a decimal number. - return unicode(data) + return str(data) class FloatDomain(NumberDomain): @@ -398,7 +398,7 @@ def __basis__(self): @staticmethod def parse(text): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` represents `null` both in literal and native formats. if text is None: return None @@ -421,7 +421,7 @@ def dump(self, data): # Check that we got a real number. assert isfinite(data) # Use `repr` to avoid loss of precision. - return unicode(repr(data)) + return str(repr(data)) class DecimalDomain(NumberDomain): @@ -456,7 +456,7 @@ def __basis__(self): @staticmethod def parse(text): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` represents `NULL` both in literal and native format. if text is None: return None @@ -481,7 +481,7 @@ def dump(data): # Check that we got a real number. assert isfinite(data) # Produce a decimal representation of the number. - return unicode(data) + return str(data) class TextDomain(Domain): @@ -512,7 +512,7 @@ def __basis__(self): @staticmethod def parse(text): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` represents `null` both in literal and native format. if text is None: return None @@ -521,9 +521,9 @@ def parse(text): @staticmethod def dump(data): - assert isinstance(data, maybe(unicode)) + assert isinstance(data, maybe(str)) if data is not None: - assert u'\0' not in data + assert '\0' not in data # `None` represents `null` both in literal and native format. if data is None: return None @@ -549,14 +549,14 @@ class EnumDomain(Domain): # would have the same set of labels. def __init__(self, labels): - assert isinstance(labels, listof(unicode)) + assert isinstance(labels, listof(str)) self.labels = labels def __basis__(self): return (tuple(self.labels),) def parse(self, text): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` represents `null` both in literal and native format. if text is None: return None @@ -570,7 +570,7 @@ def parse(self, text): return text def dump(self, data): - assert isinstance(data, maybe(unicode)) + assert isinstance(data, maybe(str)) if data is not None: assert data in self.labels # `None` represents `NULL` both in literal and native format. @@ -581,8 +581,8 @@ def dump(self, data): def __unicode__(self): # enum('label', ...) - return u"%s(%s)" % (self.__class__, - u", ".join(to_literal(label) + return "%s(%s)" % (self.__class__, + ", ".join(to_literal(label) for label in self.labels)) @@ -650,7 +650,7 @@ class DateDomain(Domain): @staticmethod def parse(text, regexp=regexp): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` represents `null` both in literal and native format. if text is None: return None @@ -666,7 +666,7 @@ def parse(text, regexp=regexp): # Generate a `datetime.date` value; may fail if the date is not valid. try: data = datetime.date(year, month, day) - except ValueError, exc: + except ValueError as exc: raise ValueError("invalid date literal: %s" % exc.args[0]) return data @@ -677,7 +677,7 @@ def dump(data): if data is None: return None # `unicode` on `datetime.date` gives us the date in YYYY-MM-DD format. - return unicode(data) + return str(data) class TimeDomain(Domain): @@ -703,7 +703,7 @@ class TimeDomain(Domain): @staticmethod def parse(text, regexp=regexp): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` represents `null` both in literal and native format. if text is None: return None @@ -731,7 +731,7 @@ def parse(text, regexp=regexp): # Generate a `datetime.time` value; may fail if the time is not valid. try: data = datetime.time(hour, minute, second, microsecond) - except ValueError, exc: + except ValueError as exc: raise ValueError("invalid time literal: %s" % exc.args[0]) return data @@ -743,7 +743,7 @@ def dump(data): return None # `unicode` on `datetime.date` gives us the date in HH:MM:SS.SSSSSS # format. - return unicode(data) + return str(data) class DateTimeDomain(Domain): @@ -785,7 +785,7 @@ class DateTimeDomain(Domain): @staticmethod def parse(text, regexp=regexp): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` represents `null` both in literal and native format. if text is None: return None @@ -832,7 +832,7 @@ def parse(text, regexp=regexp): try: data = datetime.datetime(year, month, day, hour, minute, second, microsecond, tz) - except ValueError, exc: + except ValueError as exc: raise ValueError("invalid datetime literal: %s" % exc.args[0]) return data @@ -843,7 +843,7 @@ def dump(data): if data is None: return None # `unicode` on `datetime.datetime` gives us the value in ISO format. - return unicode(data) + return str(data) class OpaqueDomain(Domain): @@ -861,7 +861,7 @@ class OpaqueDomain(Domain): @staticmethod def parse(text): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # We do not know what to do with the input, so pass it through and # hope for the best. return text @@ -875,11 +875,11 @@ def dump(data, regexp=re.compile(r"[\0-\x1F\x7F]")): # it could be given back to the database. if isinstance(data, str): text = data.decode('utf-8', 'replace') - elif isinstance(data, unicode): + elif isinstance(data, str): text = data else: try: - text = unicode(data) + text = str(data) except UnicodeDecodeError: text = str(data).decode('utf-8', 'replace') # Make sure the output is printable. @@ -923,8 +923,8 @@ def make(cls, name, fields, _cache=weakref.WeakValueDictionary()): *Returns*: subclass of :class:`Record` The generated class. """ - assert isinstance(name, maybe(oneof(str, unicode))) - assert isinstance(fields, listof(maybe(oneof(str, unicode)))) + assert isinstance(name, maybe(oneof(str, str))) + assert isinstance(fields, listof(maybe(oneof(str, str)))) # Check if the type has been generated already. cache_key = (name, tuple(fields)) @@ -933,7 +933,7 @@ def make(cls, name, fields, _cache=weakref.WeakValueDictionary()): except KeyError: pass # Process the class name; must be a regular string. - if isinstance(name, unicode): + if isinstance(name, str): name = name.encode('utf-8') # Check if the name is a valid identifier. if name is not None and not re.match(r'\A(?!\d)\w+\Z', name): @@ -952,7 +952,7 @@ def make(cls, name, fields, _cache=weakref.WeakValueDictionary()): if field is None: continue # An attribute name must be a regular string. - if isinstance(field, unicode): + if isinstance(field, str): field = field.encode('utf-8') # Only permit valid identifiers. if not re.match(r'\A(?!\d)\w+\Z', field): @@ -1040,7 +1040,7 @@ def pull_entries(self, left, right): else: # Otherwise, must be a nested container. chunks = self.pull_chunks() - entries.append(u"".join(chunks)) + entries.append("".join(chunks)) # Skip whitespace. self.pull(r"[\s]+") # Skip trailing whitespace. @@ -1075,9 +1075,9 @@ def pull_chunks(self): elif self.peek(r"[({\["): chunks.extend(self.pull_chunks()) # Pull the right bracket. - if left == u"(": + if left == "(": right = self.pull(r"[)]") - elif left == u"{": + elif left == "{": right = self.pull(r"[}]") elif left == r"[": right = self.pull(r"[\]]") @@ -1105,27 +1105,27 @@ def parse_entry(text, domain): # Unquotes and parses a container entry. # Unquote a quoted literal. - if text[0] == text[-1] == u"'": - text = text[1:-1].replace(u"''", u"'") + if text[0] == text[-1] == "'": + text = text[1:-1].replace("''", "'") # Verify that nested container entries are indeed containers. - elif text[0] == u"(" and text[-1] == u")": + elif text[0] == "(" and text[-1] == ")": if not isinstance(domain, (ListDomain, UntypedDomain)): raise ValueError("list entry for %s: %s" % (domain, text)) - elif text[0] == u"{" and text[-1] == u"}": + elif text[0] == "{" and text[-1] == "}": if not isinstance(domain, (RecordDomain, UntypedDomain)): raise ValueError("record entry for %s: %s" % (domain, text)) - elif text[0] == u"[" and text[-1] == u"]": + elif text[0] == "[" and text[-1] == "]": if not isinstance(domain, (IdentityDomain, UntypedDomain)): raise ValueError("identity entry for %s: %s" % (domain, text)) # Validate unquoted values. - elif text == u"true" or text == u"false": + elif text == "true" or text == "false": if not isinstance(domain, (BooleanDomain, UntypedDomain)): raise ValueError("boolean entry for %s: %s" % (domain, text)) - elif text == u"null": + elif text == "null": text = None else: # Must be an unquoted number. @@ -1144,7 +1144,7 @@ def dump_entry(data, domain): if text is None: # Using unquoted `null` string is safe here because a regular text # value will be quoted. - return u"null" + return "null" elif isinstance(domain, (BooleanDomain, NumberDomain, ListDomain, RecordDomain)): # Boolean and numeric literals are safe because they @@ -1154,10 +1154,10 @@ def dump_entry(data, domain): elif isinstance(domain, IdentityDomain): # Identity values are wrapped with `[]`; the outer # brackets will be stripped by `IdentityDomain.parse()`. - return u"[%s]" % text + return "[%s]" % text else: # All the others are wrapped in single quotes. - return u"'%s'" % text.replace(u"'", u"''") + return "'%s'" % text.replace("'", "''") class ListDomain(ContainerDomain): @@ -1184,10 +1184,10 @@ def __basis__(self): def __unicode__(self): # list(item) - return u"%s(%s)" % (self.__class__, self.item_domain) + return "%s(%s)" % (self.__class__, self.item_domain) def parse(self, text): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` means `null` both in literal and native forms. if text is None: return None @@ -1204,8 +1204,8 @@ def dump(self, data): return None # Serialize individual entries and wrap with `()`. if len(data) == 1: - return u"(%s,)" % self.dump_entry(data[0], self.item_domain) - return u"(%s)" % u", ".join(self.dump_entry(entry, self.item_domain) + return "(%s,)" % self.dump_entry(data[0], self.item_domain) + return "(%s)" % ", ".join(self.dump_entry(entry, self.item_domain) for entry in data) @@ -1232,12 +1232,12 @@ def __basis__(self): def __unicode__(self): # record(field, ...) - return u"%s(%s)" % (self.__class__, - ", ".join(unicode(field) + return "%s(%s)" % (self.__class__, + ", ".join(str(field) for field in self.fields)) def parse(self, text): - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` means `null` both in literal and native forms. if text is None: return None @@ -1265,7 +1265,7 @@ def dump(self, data): if data is None: return None # Serialize individual fields and wrap with `{}`. - return u"{%s}" % u", ".join(self.dump_entry(entry, field.domain) + return "{%s}" % ", ".join(self.dump_entry(entry, field.domain) for entry, field in zip(data, self.fields)) @@ -1343,13 +1343,13 @@ def __init__(self, iterable): def __unicode__(self): # Serialize back to the literal form. - return u".".join(u"(%s)" % item if isinstance(item, LabelGroup) else - unicode(item) if re.match(r"(?u)\A[\w-]+\Z", item) else - u"'%s'" % item.replace("'", "''") + return ".".join("(%s)" % item if isinstance(item, LabelGroup) else + str(item) if re.match(r"(?u)\A[\w-]+\Z", item) else + "'%s'" % item.replace("'", "''") for item in self) def __str__(self): - return unicode(self).encode('utf-8') + return str(self).encode('utf-8') class LabelBuffer(TextBuffer): @@ -1382,17 +1382,17 @@ def pull_label(self): if block is None: raise self.fail() # Composite labels. - if block == u"[": + if block == "[": label = self.pull_label_group() if self.pull(r"\]") is None: raise self.fail() - elif block == u"(": + elif block == "(": label = self.pull_label_group() if self.pull(r"\)") is None: raise self.fail() # Quoted labels. - elif block[0] == block[-1] == u"'": - label = block[1:-1].replace(u"''", u"'") + elif block[0] == block[-1] == "'": + label = block[1:-1].replace("''", "'") # Unquoted labels. else: label = block @@ -1444,13 +1444,13 @@ def __basis__(self): def __unicode__(self): # identity(label, ...) - return u"%s(%s)" % (self.__class__, - u", ".join(unicode(label) + return "%s(%s)" % (self.__class__, + ", ".join(str(label) for label in self.labels)) def parse(self, text): # Sanity check on the arguments. - assert isinstance(text, maybe(unicode)) + assert isinstance(text, maybe(str)) # `None` represents `NULL` both in literal and native format. if text is None: return None @@ -1535,14 +1535,14 @@ def dump(self, data, regexp=re.compile(r'\A [\w-]+ \Z', re.X|re.U)): is_flattened = (is_simple or len(label.labels) == 1) chunk = label.dump(entry) if not is_flattened: - chunk = u"(%s)" % chunk + chunk = "(%s)" % chunk else: # Leaf labels are converted to literal form and quoted # if the literal contains a non-alphanumeric character. chunk = label.dump(entry) if regexp.match(chunk) is None: - chunk = u"'%s'" % chunk.replace("'", "''") + chunk = "'%s'" % chunk.replace("'", "''") chunks.append(chunk) - return u".".join(chunks) + return ".".join(chunks) diff --git a/src/htsql/core/entity.py b/src/htsql/core/entity.py index 3a7ab77..8346122 100644 --- a/src/htsql/core/entity.py +++ b/src/htsql/core/entity.py @@ -31,10 +31,10 @@ def freeze(self): pass def __unicode__(self): - return u"[%s]" % id(self) + return "[%s]" % id(self) def __str__(self): - return unicode(self).encode('utf-8') + return str(self).encode('utf-8') class MutableEntity(Entity): @@ -56,7 +56,7 @@ class NamedEntity(Entity): __slots__ = ('name',) def __init__(self, owner, name): - assert isinstance(name, unicode) + assert isinstance(name, str) super(NamedEntity, self).__init__(owner) self.name = name @@ -64,7 +64,7 @@ def __unicode__(self): if self.name: return self.name else: - return u"" + return "" class EntitySet(Printable): @@ -106,10 +106,10 @@ def items(self): return [(entity.name, entity) for entity in self.entities] def __unicode__(self): - return u"[%s]" % u", ".join(entity.name for entity in self.entities) + return "[%s]" % ", ".join(entity.name for entity in self.entities) def __str__(self): - return unicode(self).encode('utf-8') + return str(self).encode('utf-8') class MutableEntitySet(EntitySet): @@ -250,7 +250,7 @@ def schema(self): def __unicode__(self): if not self.schema.name: return self.name - return u"%s.%s" % (self.schema, self.name) + return "%s.%s" % (self.schema, self.name) def __contains__(self, name): return (name in self.columns) @@ -347,7 +347,7 @@ def referring_foreign_keys(self): if self in foreign_key.target_columns] def __unicode__(self): - return u"%s.%s" % (self.table, self.name) + return "%s.%s" % (self.table, self.name) class MutableColumnEntity(ColumnEntity, MutableEntity): @@ -407,8 +407,8 @@ def origin(self): return self.owner() def __unicode__(self): - return u"%s(%s)" % (self.origin, - u",".join(column.name + return "%s(%s)" % (self.origin, + ",".join(column.name for column in self.origin_columns)) def __contains__(self, column): @@ -493,14 +493,14 @@ def target(self): return self.coowner() def __unicode__(self): - return (u"%s(%s) -> %s(%s)" + return ("%s(%s) -> %s(%s)" % (self.origin, - u",".join(column.name for column in self.origin_columns), + ",".join(column.name for column in self.origin_columns), self.target, - u",".join(column.name for column in self.target_columns))) + ",".join(column.name for column in self.target_columns))) def __contains__(self, column_pair): - return (column_pair in zip(self.origin_columns, self.target_columns)) + return (column_pair in list(zip(self.origin_columns, self.target_columns))) def __getitem__(self, index): return (self.origin_columns[index], self.target_columns[index]) @@ -616,17 +616,17 @@ def reverse(self): def __unicode__(self): # Generate a string of the form: # schema.table(column,...) -> schema.table(column,...) - return u"%s(%s) -> %s(%s)" % \ + return "%s(%s) -> %s(%s)" % \ (self.origin, - u",".join(column.name for column in self.origin_columns), + ",".join(column.name for column in self.origin_columns), self.target, - u",".join(column.name for column in self.target_columns)) + ",".join(column.name for column in self.target_columns)) def __str__(self): - return unicode(self).encode('utf-8') + return str(self).encode('utf-8') def __contains__(self, column_pair): - return (column_pair in zip(self.origin_columns, self.target_columns)) + return (column_pair in list(zip(self.origin_columns, self.target_columns))) def __getitem__(self, index): return (self.origin_columns[index], self.target_columns[index]) diff --git a/src/htsql/core/error.py b/src/htsql/core/error.py index 2a07504..15a3805 100644 --- a/src/htsql/core/error.py +++ b/src/htsql/core/error.py @@ -87,7 +87,7 @@ class NotImplementedError(HTTPError): class Paragraph(Printable): def __init__(self, message, quote): - assert isinstance(message, (str, unicode)) + assert isinstance(message, str) if isinstance(message, str): message = message.decode('utf-8', 'replace') if isinstance(quote, str): @@ -98,9 +98,9 @@ def __init__(self, message, quote): def __unicode__(self): if not self.quote: return self.message - lines = unicode(self.quote).splitlines() - block = "\n".join(u" "+line for line in lines) - return u"%s:\n%s" % (self.message, block) + lines = str(self.quote).splitlines() + block = "\n".join(" "+line for line in lines) + return "%s:\n%s" % (self.message, block) def __repr__(self): return "<%s %r>" % (self.__class__.__name__, self.message) @@ -123,10 +123,10 @@ def wrap(self, message, quote): self.paragraphs.append(paragraph) def __unicode__(self): - return u"\n".join(unicode(paragraph) for paragraph in self.paragraphs) + return "\n".join(str(paragraph) for paragraph in self.paragraphs) def __str__(self): - return unicode(self).encode('utf-8') + return str(self).encode('utf-8') def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, @@ -195,7 +195,7 @@ def union(cls, *nodes): def __init__(self, text, start, end): # Sanity check on the arguments. - assert isinstance(text, unicode) + assert isinstance(text, str) assert isinstance(start, int) assert isinstance(end, int) assert 0 <= start <= end <= len(text) @@ -212,8 +212,8 @@ def excerpt(self): if not self.text: return [] # Find the line that contains the mark. - excerpt_start = self.text.rfind(u'\n', 0, self.start)+1 - excerpt_end = self.text.find(u'\n', excerpt_start) + excerpt_start = self.text.rfind('\n', 0, self.start)+1 + excerpt_end = self.text.find('\n', excerpt_start) if excerpt_end == -1: excerpt_end = len(self.text) @@ -229,17 +229,17 @@ def excerpt(self): # Generate the exerpt and the pointer lines. lines = [] lines.append(self.text[excerpt_start:excerpt_end]) - lines.append(u' '*pointer_indent + u'^'*max(pointer_length, 1)) + lines.append(' '*pointer_indent + '^'*max(pointer_length, 1)) return lines def __unicode__(self): - return u"\n".join(self.excerpt()) + return "\n".join(self.excerpt()) def __repr__(self): chunk = self.text[self.start:self.end] return "<%s %r>" % (self.__class__.__name__, chunk.encode('utf-8')) - def __nonzero__(self): + def __bool__(self): return bool(self.text) diff --git a/src/htsql/core/fmt/emit.py b/src/htsql/core/fmt/emit.py index b7ab564..a0ec890 100644 --- a/src/htsql/core/fmt/emit.py +++ b/src/htsql/core/fmt/emit.py @@ -74,17 +74,17 @@ def __call__(self): def emit_headers(format, product): - if isinstance(format, (str, unicode)): + if isinstance(format, str): format = Accept.__invoke__(format) assert not isinstance(format, DefaultFormat), "unknown format" return list(EmitHeaders.__invoke__(format, product)) def emit(format, product): - if isinstance(format, (str, unicode)): + if isinstance(format, str): format = Accept.__invoke__(format) assert not isinstance(format, DefaultFormat), "unknown format" - tail = (line.encode('utf-8') if isinstance(line, unicode) else line + tail = (line.encode('utf-8') if isinstance(line, str) else line for line in Emit.__invoke__(format, product)) head = [] for chunk in tail: diff --git a/src/htsql/core/fmt/html.py b/src/htsql/core/fmt/html.py index 6ccb895..0039233 100644 --- a/src/htsql/core/fmt/html.py +++ b/src/htsql/core/fmt/html.py @@ -36,7 +36,7 @@ def __init__(self, mark): class TextBlock(Block): def __init__(self, text, mark): - assert isinstance(text, unicode) + assert isinstance(text, str) super(TextBlock, self).__init__(mark) self.text = text @@ -85,7 +85,7 @@ class Case(Printable): class TextCase(Case): def __init__(self, text): - assert isinstance(text, unicode) + assert isinstance(text, str) self.text = text def __str__(self): @@ -180,14 +180,14 @@ def __init__(self, stream): self.case = case def scan(self, stream): - if isinstance(stream, (str, unicode)): + if isinstance(stream, str): input = stream else: input = stream.read() if isinstance(input, str): try: input = input.decode('utf-8') - except UnicodeDecodeError, exc: + except UnicodeDecodeError as exc: mark = Mark(input.decode('utf-8', 'replace'), exc.start, exc.end) raise TemplateError("invalid UTF-8 character (%s)" @@ -292,7 +292,7 @@ def emit(self, case, context): value = context[case.name] if value is not None: assert not isinstance(value, str) - if isinstance(value, unicode): + if isinstance(value, str): yield value else: for chunk in value: @@ -303,7 +303,7 @@ def emit(self, case, context): if name not in context: raise TemplateError("undefined context variable", mark) value = context[case.name] - if value is None or value == u"": + if value is None or value == "": continue for chunk in self.emit(case, context): yield chunk @@ -333,7 +333,7 @@ def __call__(self): if self.meta.header: title = cgi.escape(self.meta.header, True) else: - title = u"" + title = "" content = None if headers_height or cells_height: content = self.table(product_to_html, @@ -344,50 +344,50 @@ def __call__(self): return template(title=title, content=content) def table(self, product_to_html, headers_height, cells_height, title): - yield u"\n" % title + yield "
\n" % title if headers_height > 0: - yield u"\n" + yield "\n" for row in product_to_html.headers(headers_height): line = [] for content, colspan, rowspan, classes in row: attributes = [] if colspan != 1: - attributes.append(u" colspan=\"%s\"" % colspan) + attributes.append(" colspan=\"%s\"" % colspan) if rowspan != 1: - attributes.append(u" rowspan=\"%s\"" % rowspan) + attributes.append(" rowspan=\"%s\"" % rowspan) if classes: - attributes.append(u" class=\"%s\"" - % u" ".join(classes)) - line.append(u"%s" % (u"".join(attributes), + attributes.append(" class=\"%s\"" + % " ".join(classes)) + line.append("%s" % ("".join(attributes), cgi.escape(content))) - yield u"%s\n" % u"".join(line) - yield u"\n" + yield "%s\n" % "".join(line) + yield "\n" if cells_height > 0: - yield u"\n" + yield "\n" index = 0 for row in product_to_html.cells(self.data, cells_height): line = [] for content, colspan, rowspan, classes in row: attributes = [] if colspan != 1: - attributes.append(u" colspan=\"%s\"" % colspan) + attributes.append(" colspan=\"%s\"" % colspan) if rowspan != 1: - attributes.append(u" rowspan=\"%s\"" % rowspan) + attributes.append(" rowspan=\"%s\"" % rowspan) if classes: - attributes.append(u" class=\"%s\"" - % u" ".join(classes)) - line.append(u"%s" % (u"".join(attributes), + attributes.append(" class=\"%s\"" + % " ".join(classes)) + line.append("%s" % ("".join(attributes), cgi.escape(content))) index += 1 attributes = [] if index % 2: - attributes.append(u" class=\"htsql-odd-row\"") + attributes.append(" class=\"htsql-odd-row\"") else: - attributes.append(u" class=\"htsql-even-row\"") - yield u"%s\n" % (u"".join(attributes), - u"".join(line)) - yield u"\n" - yield u"
\n" + attributes.append(" class=\"htsql-even-row\"") + yield "%s\n" % ("".join(attributes), + "".join(line)) + yield "\n" + yield "\n" class ToHTML(Adapter): @@ -405,7 +405,7 @@ def __call__(self): def headers(self, height): if height > 0: - yield [(u"", self.width, height, [u"htsql-empty-header"])] + yield [("", self.width, height, ["htsql-empty-header"])] def headers_height(self): return 0 @@ -413,13 +413,13 @@ def headers_height(self): def cells(self, value, height): assert height > 0 classes = [] - classes.append(u"htsql-%s-type" % self.domain.__class__) + classes.append("htsql-%s-type" % self.domain.__class__) content = self.dump(value) if content is None: - content = u"" - classes.append(u"htsql-null-value") + content = "" + classes.append("htsql-null-value") elif not content: - classes.append(u"htsql-empty-value") + classes.append("htsql-empty-value") classes.extend(self.classes(value)) yield [(content, self.width, height, classes)] @@ -485,7 +485,7 @@ def cells(self, value, height): if not self.width or not height: return if value is None: - yield [(u"", 1, height, [u"htsql-null-record-value"])]*self.width + yield [("", 1, height, ["htsql-null-record-value"])]*self.width else: streams = [field_to_html.cells(item, height) for item, field_to_html in zip(value, @@ -523,7 +523,7 @@ def headers(self, height): if height > 0: item_stream = self.item_to_html.headers(height) first_row = next(item_stream) - first_row.insert(0, (u"", 1, height, [u"htsql-empty-header"])) + first_row.insert(0, ("", 1, height, ["htsql-empty-header"])) yield first_row for row in item_stream: yield row @@ -536,10 +536,10 @@ def cells(self, value, height): return if not value: row = [] - row.append((u"", 1, height, - [u"htsql-index", u"htsql-null-record-value"])) - row.extend([(u"", 1, height, - [u"htsql-null-record-value"])]*(self.width-1)) + row.append(("", 1, height, + ["htsql-index", "htsql-null-record-value"])) + row.extend([("", 1, height, + ["htsql-null-record-value"])]*(self.width-1)) yield row return items = iter(value) @@ -559,13 +559,13 @@ def cells(self, value, height): total_height -= item_height item_stream = self.item_to_html.cells(item, item_height) first_row = next(item_stream, []) - first_row.insert(0, (unicode(index), 1, item_height, - [u"htsql-index"])) + first_row.insert(0, (str(index), 1, item_height, + ["htsql-index"])) if not self.item_to_html.is_bounded: first_row = [ (content, colspan, rowspan, - [u"htsql-section"]+classes - if u"htsql-section" not in classes else classes) + ["htsql-section"]+classes + if "htsql-section" not in classes else classes) for content, colspan, rowspan, classes in first_row] yield first_row for row in item_stream: @@ -599,7 +599,7 @@ class NativeStringToHTML(ToHTML): def dump(self, value): if value is None: return None - return unicode(value) + return str(value) class DecimalToHTML(ToHTML): @@ -611,13 +611,13 @@ def dump(self, value): return value sign, digits, exp = value.as_tuple() if not digits: - return unicode(value) + return str(value) if exp < -6 and value == value.normalize(): value = value.normalize() sign, digits, exp = value.as_tuple() if exp > 0: value = value.quantize(decimal.Decimal(1)) - return unicode(value) + return str(value) class BooleanToHTML(ToHTML): @@ -626,18 +626,18 @@ class BooleanToHTML(ToHTML): def classes(self, value): if value is True: - return [u"htsql-true-value"] + return ["htsql-true-value"] if value is False: - return [u"htsql-false-value"] + return ["htsql-false-value"] return [] def dump(self, value): if value is None: return None elif value is True: - return u"true" + return "true" elif value is False: - return u"false" + return "false" class DateTimeToHTML(ToHTML): @@ -648,9 +648,9 @@ def dump(self, value): if value is None: return None elif not value.time(): - return unicode(value.date()) + return str(value.date()) else: - return unicode(value) + return str(value) class OpaqueToHTML(ToHTML): @@ -660,11 +660,11 @@ class OpaqueToHTML(ToHTML): def dump(self, value): if value is None: return None - if not isinstance(value, unicode): + if not isinstance(value, str): try: value = str(value).decode('utf-8') except UnicodeDecodeError: - value = unicode(repr(value)) + value = str(repr(value)) return value @@ -688,7 +688,7 @@ def headers(self, height): content = self.profile.header classes = [] if not content: - classes.append(u"htsql-empty-header") + classes.append("htsql-empty-header") yield [(content, self.width, (height if self.header_level == 1 else 1), classes)] if self.header_level > 1: diff --git a/src/htsql/core/fmt/json.py b/src/htsql/core/fmt/json.py index b9137b9..510157c 100644 --- a/src/htsql/core/fmt/json.py +++ b/src/htsql/core/fmt/json.py @@ -52,7 +52,7 @@ def purge_null_keys(iterator): context = states.pop() token = next(iterator, JS_DONE) if context is JS_MAP: - while isinstance(token, unicode): + while isinstance(token, str): key = token token = next(iterator, JS_DONE) if token is None: @@ -78,75 +78,75 @@ def replace(match): def dump_json(iterator): states = [] context = None - prefix = u"" + prefix = "" next_token = next(iterator, JS_DONE) while True: token = next_token next_token = next(iterator, JS_DONE) if token is None: - line = u"null" + line = "null" elif token is True: - line = u"true" + line = "true" elif token is False: - line = u"false" - elif isinstance(token, unicode): - line = u"\"%s\"" % escape_json(token) - elif isinstance(token, (int, long)): - line = unicode(token) + line = "false" + elif isinstance(token, str): + line = "\"%s\"" % escape_json(token) + elif isinstance(token, int): + line = str(token) elif isinstance(token, float): if math.isinf(token) or math.isnan(token): - line = u"null" + line = "null" else: - line = unicode(token) + line = str(token) elif isinstance(token, decimal.Decimal): if not token.is_finite(): - line = u"null" + line = "null" else: - line = unicode(token) + line = str(token) elif token is JS_SEQ: if next_token is JS_END: - line = u"[]" + line = "[]" next_token = next(iterator, JS_DONE) else: - yield prefix+u"[\n" + yield prefix+"[\n" states.append(context) context = token - prefix = u" "*len(states) + prefix = " "*len(states) continue elif token is JS_MAP: if next_token is JS_END: - line = u"{}" + line = "{}" next_token = next(iterator, JS_DONE) else: - assert isinstance(next_token, unicode), repr(next_token) - yield prefix+u"{\n" + assert isinstance(next_token, str), repr(next_token) + yield prefix+"{\n" states.append(context) context = token - prefix = u" "*len(states) + \ - u"\"%s\": " % escape_json(next_token) + prefix = " "*len(states) + \ + "\"%s\": " % escape_json(next_token) next_token = next(iterator, JS_DONE) continue else: assert False, repr(token) if next_token is not JS_END and next_token is not JS_DONE: - yield prefix+line+u",\n" + yield prefix+line+",\n" else: - yield prefix+line+u"\n" + yield prefix+line+"\n" while next_token is JS_END and states: next_token = next(iterator, JS_DONE) if context is JS_SEQ: - line = u"]" + line = "]" elif context is JS_MAP: - line = u"}" + line = "}" context = states.pop() - prefix = u" "*len(states) + prefix = " "*len(states) if next_token is not JS_END and next_token is not JS_DONE: - yield prefix+line+u",\n" + yield prefix+line+",\n" else: - yield prefix+line+u"\n" + yield prefix+line+"\n" if context is JS_MAP: - assert isinstance(next_token, unicode), repr(next_token) - prefix = u" "*len(states) + u"\"%s\": " % escape_json(next_token) + assert isinstance(next_token, str), repr(next_token) + prefix = " "*len(states) + "\"%s\": " % escape_json(next_token) next_token = next(iterator, JS_DONE) if context is None: assert next_token is JS_DONE, repr(next_token) @@ -186,10 +186,10 @@ def emit(self): meta = list(profile_to_raw(self.meta)) data = to_raw(self.meta.domain)(self.data) yield JS_MAP - yield u"meta" + yield "meta" for token in meta: yield token - yield u"data" + yield "data" for token in data: yield token yield JS_END @@ -210,7 +210,7 @@ def emit(self): if self.meta.tag: key = self.meta.tag else: - key = unicode(0) + key = str(0) yield JS_MAP yield key for token in product_to_json(self.data): @@ -299,7 +299,7 @@ def scatter(value): if value is None: yield None else: - yield unicode(value) + yield str(value) class DateTimeToRaw(ToRaw): @@ -311,9 +311,9 @@ def scatter(value): if value is None: yield None elif not value.time(): - yield unicode(value.date()) + yield str(value.date()) else: - yield unicode(value) + yield str(value) class OpaqueToRaw(ToRaw): @@ -325,11 +325,11 @@ def scatter(value): if value is None: yield None return - if not isinstance(value, unicode): + if not isinstance(value, str): try: value = str(value).decode('utf-8') except UnicodeDecodeError: - value = unicode(repr(value)) + value = str(repr(value)) yield value @@ -361,7 +361,7 @@ def __call__(self): if self.profile.syntax is None: yield None else: - yield unicode(self.profile.syntax) + yield str(self.profile.syntax) class TagMetaToRaw(MetaToRaw): @@ -400,7 +400,7 @@ def __call__(self): yield None return names.append(labels[0].name) - yield u".".join(names) + yield ".".join(names) class DomainToRaw(Adapter): @@ -413,8 +413,8 @@ def __init__(self, domain): def __call__(self): yield JS_MAP - yield u"type" - yield unicode(self.domain.__class__) + yield "type" + yield str(self.domain.__class__) yield JS_END @@ -432,11 +432,11 @@ class ListDomainToRaw(DomainToRaw): def __call__(self): yield JS_MAP - yield u"type" - yield unicode(self.domain.__class__) - yield u"item" + yield "type" + yield str(self.domain.__class__) + yield "item" yield JS_MAP - yield u"domain" + yield "domain" for token in domain_to_raw(self.domain.item_domain): yield token yield JS_END @@ -449,9 +449,9 @@ class RecordDomainToRaw(DomainToRaw): def __call__(self): yield JS_MAP - yield u"type" - yield unicode(self.domain.__class__) - yield u"fields" + yield "type" + yield str(self.domain.__class__) + yield "fields" yield JS_SEQ for field in self.domain.fields: for token in profile_to_raw(field): @@ -466,8 +466,8 @@ class IdentityDomainToRaw(DomainToRaw): def __call__(self): yield JS_MAP - yield u"type" - yield unicode(self.domain.__class__) + yield "type" + yield str(self.domain.__class__) #yield u"fields" #yield JS_SEQ #for field in self.domain.fields: @@ -506,7 +506,7 @@ def __init__(self, domain): key = field.tag used.add(key) else: - key = unicode(idx) + key = str(idx) self.field_keys.append(key) def __call__(self): @@ -552,7 +552,7 @@ def scatter(self, value): def profile_to_raw(profile): yield JS_MAP for name in MetaToRaw.__catalogue__(): - yield unicode(name) + yield str(name) for token in MetaToRaw.__invoke__(name, profile): yield token yield JS_END diff --git a/src/htsql/core/fmt/tabular.py b/src/htsql/core/fmt/tabular.py index 36a1600..9a2a3bd 100644 --- a/src/htsql/core/fmt/tabular.py +++ b/src/htsql/core/fmt/tabular.py @@ -20,7 +20,7 @@ DateTimeDomain, ListDomain, RecordDomain, UntypedDomain, VoidDomain, OpaqueDomain, Profile) import csv -import cStringIO +import io import math @@ -62,7 +62,7 @@ def __call__(self): headers = product_to_csv.headers() to_cells = product_to_csv.cells assert len(headers) == product_to_csv.width - output = cStringIO.StringIO() + output = io.StringIO() writer = csv.writer(output, dialect=self.format.dialect) writer.writerow([header.encode('utf-8') if header is not None else "" for header in headers]) @@ -188,9 +188,9 @@ def cells(self, value): if value is None: yield [None] elif value is True: - yield [u"1"] + yield ["1"] elif value is False: - yield [u"0"] + yield ["0"] class NumberToCSV(ToCSV): @@ -201,7 +201,7 @@ def cells(self, value): if value is None: yield [None] else: - yield [unicode(value)] + yield [str(value)] class FloatToCSV(ToCSV): @@ -212,7 +212,7 @@ def cells(self, value): if value is None or math.isinf(value) or math.isnan(value): yield [None] else: - yield [unicode(value)] + yield [str(value)] class DecimalToCSV(ToCSV): @@ -223,7 +223,7 @@ def cells(self, value): if value is None or not value.is_finite(): yield [None] else: - yield [unicode(value)] + yield [str(value)] class TextToCSV(ToCSV): @@ -244,7 +244,7 @@ def cells(self, value): if value is None: yield [None] else: - yield [unicode(value)] + yield [str(value)] class TimeToCSV(ToCSV): @@ -255,7 +255,7 @@ def cells(self, value): if value is None: yield [None] else: - yield [unicode(value)] + yield [str(value)] class DateTimeToCSV(ToCSV): @@ -266,9 +266,9 @@ def cells(self, value): if value is None: yield [None] elif not value.time(): - yield [unicode(value.date())] + yield [str(value.date())] else: - yield [unicode(value)] + yield [str(value)] class OpaqueToCSV(ToCSV): @@ -279,11 +279,11 @@ def cells(self, value): if value is None: yield [None] return - if not isinstance(value, unicode): + if not isinstance(value, str): try: value = str(value).decode('utf-8') except UnicodeDecodeError: - value = unicode(repr(value)) + value = str(repr(value)) yield [value] diff --git a/src/htsql/core/fmt/text.py b/src/htsql/core/fmt/text.py index c1f20d5..0b7bb56 100644 --- a/src/htsql/core/fmt/text.py +++ b/src/htsql/core/fmt/text.py @@ -65,7 +65,7 @@ def __call__(self): bar.append((None, rowspan-1)) assert not row if row_idx > 0: - line = [u" "] + line = [" "] for idx in range(0, size+1): is_horiz = False is_vert = False @@ -87,21 +87,21 @@ def __call__(self): else: is_vert = True if is_horiz and is_vert: - line.append(u"+") + line.append("+") elif is_horiz: - line.append(u"-") + line.append("-") elif is_vert: - line.append(u"|") + line.append("|") else: - line.append(u" ") + line.append(" ") if idx < size: text, tail = last_bar[idx] if tail == 0: - line.append(u"-"*(widths[idx]+2)) + line.append("-"*(widths[idx]+2)) else: - line.append(u" "*(widths[idx]+2)) + line.append(" "*(widths[idx]+2)) else: - line.append(u"\n") + line.append("\n") yield "".join(line) extent = 0 line = [] @@ -109,10 +109,10 @@ def __call__(self): text, tail = bar[idx] if text is not None: assert extent == 0, extent - line.append(u" | ") + line.append(" | ") else: if extent < 3: - line.append(u" "*(3-extent)) + line.append(" "*(3-extent)) extent = 0 else: extent -= 3 @@ -121,48 +121,48 @@ def __call__(self): line.append(text) extent = len(text) if extent < width: - line.append(u" "*(width-extent)) + line.append(" "*(width-extent)) extent = 0 else: extent -= width assert extent == 0 - line.append(u" |\n") + line.append(" |\n") yield "".join(line) - line = [u"-+-"] + line = ["-+-"] for width in widths: - line.append(u"-"*width) - line.append(u"-+-") - line.append(u"\n") - yield u"".join(line) + line.append("-"*width) + line.append("-+-") + line.append("\n") + yield "".join(line) body = product_to_text.body(self.data, widths) for row in body: line = [] is_last_solid = False for chunk, is_solid in row: if is_last_solid or is_solid: - line.append(u" | ") + line.append(" | ") else: - line.append(u" : ") + line.append(" : ") line.append(chunk) is_last_solid = is_solid if is_last_solid: - line.append(u" |\n") + line.append(" |\n") else: - line.append(u" :\n") - yield u"".join(line) - yield u"\n" + line.append(" :\n") + yield "".join(line) + yield "\n" if addon.debug and (self.meta.syntax or hasattr(self.product, 'sql')): - yield u" ----\n" + yield " ----\n" if self.meta.syntax: - yield u" %s\n" % self.meta.syntax + yield " %s\n" % self.meta.syntax if hasattr(self.product, 'sql'): - sql = re.sub(ur'[\0-\x09\x0b-\x1f\x7f]', u'\ufffd', + sql = re.sub(r'[\0-\x09\x0b-\x1f\x7f]', '\ufffd', self.product.sql) for line in sql.splitlines(): if line: - yield u" %s\n" % line + yield " %s\n" % line else: - yield u"\n" + yield "\n" class ToText(Adapter): @@ -182,19 +182,19 @@ def head_depth(self): def head(self, depth): if not self.size or not depth: return - yield [(u"", depth, self.size)] + yield [("", depth, self.size)] def body(self, data, widths): [width] = widths cell = self.dump(data) - yield [(u"%*s" % (-width, cell), True)] + yield [("%*s" % (-width, cell), True)] def widths(self, data): return [len(self.dump(data))] def dump(self, value): if value is None: - return u"" + return "" return self.domain.dump(value) @@ -206,43 +206,43 @@ class TextToText(ToText): threshold = 32 - boundary_pattern = u"""(?<=\S) (?=\S)""" + boundary_pattern = """(?<=\S) (?=\S)""" boundary_regexp = re.compile(boundary_pattern) - unescaped_pattern = ur"""\A(?=[^ "])[^\x00-\x1F]+(?<=[^ "])\Z""" + unescaped_pattern = r"""\A(?=[^ "])[^\x00-\x1F]+(?<=[^ "])\Z""" unescaped_regexp = re.compile(unescaped_pattern) - escape_pattern = ur"""[\x00-\x1F"\\]""" + escape_pattern = r"""[\x00-\x1F"\\]""" escape_regexp = re.compile(escape_pattern) escape_table = { - u'\\': u'\\\\', - u'"': u'\\"', - u'\b': u'\\b', - u'\f': u'\\f', - u'\n': u'\\n', - u'\r': u'\\r', - u'\t': u'\\t', + '\\': '\\\\', + '"': '\\"', + '\b': '\\b', + '\f': '\\f', + '\n': '\\n', + '\r': '\\r', + '\t': '\\t', } def escape_replace(self, match): char = match.group() if char in self.escape_table: return self.escape_table[char] - return u"\\u%04x" % ord(char) + return "\\u%04x" % ord(char) def escape(self, value): if self.unescaped_regexp.match(value): return value - return u'"%s"' % self.escape_regexp.sub(self.escape_replace, value) + return '"%s"' % self.escape_regexp.sub(self.escape_replace, value) def body(self, data, widths): [width] = widths if data is None: - yield [(u" "*width, True)] + yield [(" "*width, True)] return value = self.escape(data) if len(value) <= width: - yield [(u"%*s" % (-width, value), True)] + yield [("%*s" % (-width, value), True)] return chunks = self.boundary_regexp.split(value) best_badnesses = [] @@ -276,9 +276,9 @@ def body(self, data, widths): idx = len(chunks) while idx > 0: size = best_sizes[idx-1] - group = u" ".join(chunks[idx-size:idx]) + group = " ".join(chunks[idx-size:idx]) assert len(group) <= width - line = u"%*s" % (-width, group) + line = "%*s" % (-width, group) lines.insert(0, line) idx -= size is_first = True @@ -322,8 +322,8 @@ class NativeStringToText(ToText): def dump(self, value): if value is None: - return u"" - return unicode(value) + return "" + return str(value) class NumberToText(NativeStringToText): @@ -333,7 +333,7 @@ class NumberToText(NativeStringToText): def body(self, data, widths): [width] = widths cell = self.dump(data) - yield [(u"%*s" % (width, cell), True)] + yield [("%*s" % (width, cell), True)] class DecimalToText(ToText): @@ -342,10 +342,10 @@ class DecimalToText(ToText): def dump(self, value): if value is None: - return u"" + return "" sign, digits, exp = value.as_tuple() if not digits: - return unicode(value) + return str(value) if exp < -6 and value == value.normalize(): value = value.normalize() sign, digits, exp = value.as_tuple() @@ -354,7 +354,7 @@ def dump(self, value): # quantize result has too many digits for current context if exp+len(digits) < 28: value = value.quantize(decimal.Decimal(1)) - return unicode(value) + return str(value) class DateTimeToText(ToText): @@ -363,11 +363,11 @@ class DateTimeToText(ToText): def dump(self, value): if value is None: - return u"" + return "" elif not value.time(): - return unicode(value.date()) + return str(value.date()) else: - return unicode(value) + return str(value) class OpaqueToText(ToText): @@ -376,12 +376,12 @@ class OpaqueToText(ToText): def dump(self, value): if value is None: - return u"" - if not isinstance(value, unicode): + return "" + if not isinstance(value, str): try: value = str(value).decode('utf-8') except UnicodeDecodeError: - value = unicode(repr(value)) + value = str(repr(value)) return value @@ -431,7 +431,7 @@ def head(self, depth): def body(self, data, widths): if not self.size: return - dummies = [(u" "*width, False) for width in widths] + dummies = [(" "*width, False) for width in widths] if data is None: yield dummies return diff --git a/src/htsql/core/fmt/xml.py b/src/htsql/core/fmt/xml.py index d7194ef..86982da 100644 --- a/src/htsql/core/fmt/xml.py +++ b/src/htsql/core/fmt/xml.py @@ -27,8 +27,8 @@ class XML_START(XML_SIGNAL): is_start = True def __init__(self, tag, attributes=[]): - assert isinstance(tag, unicode) - assert isinstance(attributes, listof(tupleof(unicode, unicode))) + assert isinstance(tag, str) + assert isinstance(attributes, listof(tupleof(str, str))) self.tag = tag self.attributes = attributes @@ -53,7 +53,7 @@ class XML_TEXT(XML_SIGNAL): is_text = True def __init__(self, data): - assert isinstance(data, unicode) + assert isinstance(data, str) self.data = data def __str__(self): @@ -83,7 +83,7 @@ def pull(): return signal[0](*signal[1:]) elif isinstance(signal, type): return signal() - elif isinstance(signal, unicode): + elif isinstance(signal, str): return XML_TEXT(signal) return signal except StopIteration: @@ -91,24 +91,24 @@ def pull(): tags = [] is_newline = True next_signal = pull() - yield u"\n" + yield "\n" while next_signal is not None: signal = next_signal next_signal = pull() chunks = [] if signal.is_start: if not is_newline: - chunks.append(u"\n") - chunks.append(u" "*len(tags)) - chunks.append(u"<") + chunks.append("\n") + chunks.append(" "*len(tags)) + chunks.append("<") chunks.append(signal.tag) for attribute, value in signal.attributes: - chunks.append(u" %s=\"%s\"" % (attribute, + chunks.append(" %s=\"%s\"" % (attribute, escape_xml(value))) if next_signal.is_end: - chunks.append(u" />\n") + chunks.append(" />\n") else: - chunks.append(u">") + chunks.append(">") if next_signal.is_end: signal = next_signal next_signal = pull() @@ -120,22 +120,22 @@ def pull(): tag = tags.pop() chunks = [] if is_newline: - chunks.append(u" "*len(tags)) - chunks.append(u"\n") + chunks.append(">\n") is_newline = True elif signal.is_text: chunks = [] if not next_signal.is_end and not is_newline: - chunks.append(u"\n") + chunks.append("\n") is_newline = True if is_newline: - chunks.append(u" "*len(tags)) + chunks.append(" "*len(tags)) chunks.append(escape_xml(signal.data)) if is_newline: - chunks.append(u"\n") - yield u"".join(chunks) + chunks.append("\n") + yield "".join(chunks) class EmitXMLHeaders(EmitHeaders): @@ -165,10 +165,10 @@ def emit(self): not re.match(r"""^[Xx][Mm][Ll]|^_\d*$""", self.meta.tag)): tag = self.meta.tag else: - tag = u"_" + tag = "_" product_to_xml = to_xml(self.meta.domain, tag) - yield XML_START, u"htsql:result", [(u"xmlns:htsql", - u"http://htsql.org/2010/xml")] + yield XML_START, "htsql:result", [("xmlns:htsql", + "http://htsql.org/2010/xml")] for signal in product_to_xml(self.data): yield signal yield XML_END @@ -180,7 +180,7 @@ class ToXML(Adapter): def __init__(self, domain, tag): assert isinstance(domain, Domain) - assert isinstance(tag, unicode) + assert isinstance(tag, str) self.domain = domain self.tag = tag @@ -208,7 +208,7 @@ def __init__(self, domain, tag): tag = field.tag used.add(tag) else: - tag = u"_%s" % (idx+1) + tag = "_%s" % (idx+1) field_to_xml = to_xml(field.domain, tag) self.fields_to_xml.append(field_to_xml) @@ -248,7 +248,7 @@ class NativeToXML(ToXML): def scatter(self, value): if value is not None: yield XML_START, self.tag - yield unicode(value) + yield str(value) yield XML_END @@ -261,14 +261,14 @@ def scatter(self, value): return sign, digits, exp = value.as_tuple() if not digits: - value = unicode(value) + value = str(value) else: if exp < -6 and value == value.normalize(): value = value.normalize() sign, digits, exp = value.as_tuple() if exp > 0: value = value.quantize(decimal.Decimal(1)) - value = unicode(value) + value = str(value) yield XML_START, self.tag yield value yield XML_END @@ -283,9 +283,9 @@ def dump(self, value): return yield XML_START, self.tag if not value.time(): - yield unicode(value.date()) + yield str(value.date()) else: - yield unicode(value) + yield str(value) yield XML_END @@ -297,11 +297,11 @@ def dump(self, value): if value is None: return yield XML_START, self.tag - if not isinstance(value, unicode): + if not isinstance(value, str): try: value = str(value).decode('utf-8') except UnicodeDecodeError: - value = unicode(repr(value)) + value = str(repr(value)) yield value yield XML_END diff --git a/src/htsql/core/model.py b/src/htsql/core/model.py index 777bac3..304a712 100644 --- a/src/htsql/core/model.py +++ b/src/htsql/core/model.py @@ -48,7 +48,7 @@ class Label(Clonable, Printable): 'is_expanding', 'is_contracting', 'is_public') def __init__(self, name, arc, is_public): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(arc, Arc) assert isinstance(is_public, bool) assert arc.arity is None or not is_public @@ -214,7 +214,7 @@ class SyntaxArc(Arc): __slots__ = ('parameters', 'syntax') def __init__(self, origin, parameters, syntax): - assert isinstance(parameters, maybe(listof(tupleof(unicode, bool)))) + assert isinstance(parameters, maybe(listof(tupleof(str, bool)))) assert isinstance(syntax, Syntax) super(SyntaxArc, self).__init__( origin=origin, diff --git a/src/htsql/core/syn/decode.py b/src/htsql/core/syn/decode.py index ab48e71..7588a53 100644 --- a/src/htsql/core/syn/decode.py +++ b/src/htsql/core/syn/decode.py @@ -5,7 +5,7 @@ from ..error import Error, Mark, parse_guard import re -import urllib2 +import urllib.request, urllib.error, urllib.parse _escape_regexp = re.compile(r"""%(?P[0-9A-Fa-f]{2})?""") @@ -39,11 +39,11 @@ def decode(text): ``%``-encoded octets are decoded; the input text is converted to Unicode. """ - assert isinstance(text, (str, unicode)) + assert isinstance(text, str) # We accept both 8-bit and Unicode strings, but we need to decode %-escaped # UTF-8 octets before translating the query to Unicode. - if isinstance(text, unicode): + if isinstance(text, str): text = text.encode('utf-8') # Decode %-encoded UTF-8 octets. @@ -52,14 +52,14 @@ def decode(text): # Convert the query to Unicode. try: text = text.decode('utf-8') - except UnicodeDecodeError, exc: + except UnicodeDecodeError as exc: # Prepare the error message. start = len(text[:exc.start].decode('utf-8', 'ignore')) end = len(text[:exc.end].decode('utf-8', 'ignore')) mark = Mark(text.decode('utf-8', 'replace'), start, end) with parse_guard(mark): raise Error("Cannot convert a byte sequence %s to UTF-8: %s" - % (urllib2.quote(exc.object[exc.start:exc.end]), + % (urllib.parse.quote(exc.object[exc.start:exc.end]), exc.reason)) return text diff --git a/src/htsql/core/syn/grammar.py b/src/htsql/core/syn/grammar.py index bcc7955..d004f4d 100644 --- a/src/htsql/core/syn/grammar.py +++ b/src/htsql/core/syn/grammar.py @@ -148,7 +148,7 @@ def __init__(self, arms): self.arms = arms def __unicode__(self): - return u"(%s)" % u" | ".join(unicode(arm) for arm in self.arms) + return "(%s)" % " | ".join(str(arm) for arm in self.arms) def encode(self, nfa, src, dst): # Encode: @@ -167,7 +167,7 @@ def __init__(self, arms): self.arms = arms def __unicode__(self): - return u"(%s)" % u" ".join(unicode(arm) for arm in self.arms) + return "(%s)" % " ".join(str(arm) for arm in self.arms) def encode(self, nfa, src, dst): # Encode: @@ -194,7 +194,7 @@ def __init__(self, arm, modifier): self.modifier = modifier def __unicode__(self): - return u"%s%s" % (self.arm, self.modifier) + return "%s%s" % (self.arm, self.modifier) def encode(self, nfa, src, dst): # Encode `?`: @@ -230,7 +230,7 @@ def __init__(self, symbol): self.symbol = symbol def __unicode__(self): - return unicode(self.symbol) + return str(self.symbol) def encode(self, nfa, src, dst): # Encode: @@ -242,7 +242,7 @@ class EpsPat(Pattern): # Zero pattern. def __unicode__(self): - return u"()" + return "()" def encode(self, nfa, src, dst): # Encode: @@ -357,10 +357,10 @@ def __unicode__(self): # Dump textual representation of the grammar. chunks = [] for rule in self.rules: - chunks.append(unicode(rule)) + chunks.append(str(rule)) for signal in self.signals: - chunks.append(unicode(signal)) - return u"\n\n".join(chunks) + chunks.append(str(signal)) + return "\n\n".join(chunks) def __call__(self): # Generates a scanner. At least one tokenizer rule must exist. @@ -375,12 +375,12 @@ def __call__(self): for token in rule.tokens: assert token.push is None or token.push in self.rules pattern = str(token.pattern) - pattern = u"(?P<%s> %s )" % (token.name, pattern) + pattern = "(?P<%s> %s )" % (token.name, pattern) patterns.append(pattern) group = ScanTableGroup(token.name, token.error, token.is_junk, token.is_symbol, token.unquote, token.pop, token.push) groups.append(group) - pattern = u" | ".join(patterns) + pattern = " | ".join(patterns) regexp = re.compile(pattern, re.U|re.X) table = ScanTable(rule.name, regexp, groups) tables[table.name] = table @@ -392,7 +392,7 @@ def __call__(self): treatments.append(treatment) # Textual grammar representation. - doc = unicode(self) + doc = str(self) return Scanner(tables, treatments, doc) @@ -403,7 +403,7 @@ class LexicalRule(Printable): """ def __init__(self, name): - assert isinstance(name, unicode) + assert isinstance(name, str) self.name = name self.tokens = omap() @@ -469,10 +469,10 @@ def add_token(self, descriptor, error=None, is_junk=False, is_symbol=False, def __unicode__(self): chunks = [] - chunks.append(u"[%s]" % self.name) + chunks.append("[%s]" % self.name) for token in self.tokens: - chunks.append(unicode(token)) - return u"\n".join(chunks) + chunks.append(str(token)) + return "\n".join(chunks) class LexicalToken(Printable): @@ -480,14 +480,14 @@ class LexicalToken(Printable): def __init__(self, name, pattern, error, is_junk, is_symbol, unquote, pop, push, doc): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(pattern, Pattern) assert isinstance(error, maybe(str)) assert isinstance(is_junk, bool) assert isinstance(is_symbol, bool) assert isinstance(pop, maybe(int)) - assert isinstance(push, maybe(unicode)) - assert isinstance(doc, unicode) + assert isinstance(push, maybe(str)) + assert isinstance(doc, str) self.name = name self.pattern = pattern self.error = error @@ -501,24 +501,24 @@ def __init__(self, name, pattern, error, is_junk, is_symbol, def __unicode__(self): chunks = [self.doc] if self.pop or self.push: - chunks.append(u" {") + chunks.append(" {") if self.pop: - chunks.append(u"pop: %s" % self.pop) + chunks.append("pop: %s" % self.pop) if self.pop and self.push: - chunks.append(u"; ") + chunks.append("; ") if self.push: - chunks.append(u"push: %s" % self.push) - chunks.append(u"}") - return u"".join(chunks) + chunks.append("push: %s" % self.push) + chunks.append("}") + return "".join(chunks) class LexicalSignal(Printable): # A matching rule for a signal token. def __init__(self, name, pattern, doc): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(pattern, Pattern) - assert isinstance(doc, unicode) + assert isinstance(doc, str) self.name = name self.pattern = pattern self.doc = doc @@ -531,7 +531,7 @@ class ScanTable(object): # Tokenizer context. def __init__(self, name, regexp, groups): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(regexp, re._pattern_type) assert isinstance(groups, listof(ScanTableGroup)) self.name = name @@ -543,12 +543,12 @@ class ScanTableGroup(object): # Matching rule for tokenizer context. def __init__(self, name, error, is_junk, is_symbol, unquote, pop, push): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(error, maybe(str)) assert isinstance(is_junk, bool) assert isinstance(is_symbol, bool) assert isinstance(pop, maybe(int)) - assert isinstance(push, maybe(unicode)) + assert isinstance(push, maybe(str)) self.name = name self.error = error self.is_junk = is_junk @@ -562,7 +562,7 @@ class ScanTreatment(object): # Post-process treatment rule. def __init__(self, name, dfa): - assert isinstance(name, unicode) + assert isinstance(name, str) self.name = name self.dfa = dfa @@ -574,7 +574,7 @@ def __init__(self, tables, treatments, doc): assert isinstance(tables, omapof(ScanTable)) assert len(tables) > 0 assert isinstance(treatments, listof(ScanTreatment)) - assert isinstance(doc, unicode) + assert isinstance(doc, str) self.start = next(iter(tables)).name self.tables = tables @@ -582,7 +582,7 @@ def __init__(self, tables, treatments, doc): self.doc = doc def __call__(self, text, start=None): - assert isinstance(text, unicode) + assert isinstance(text, str) assert start is None or start in self.tables # The name of the initial tokenizer context. if start is None: @@ -659,7 +659,7 @@ def __call__(self, text, start=None): break token = tokens[end] if None in dfa[state]: - token = Token(treatment.name, u"") + token = Token(treatment.name, "") point(token, tokens[start]) tokens.insert(start, token) start = end+1 @@ -729,7 +729,7 @@ def add_rule(self, descriptor, match=None, fail=None): return rule def __unicode__(self): - return u"\n".join(unicode(rule) for rule in self.rules) + return "\n".join(str(rule) for rule in self.rules) def __call__(self): # Generates a parser. @@ -827,15 +827,15 @@ def __call__(self): table = ParseTable(rule.name, machine, rule.match, rule.fail) tables[table.name] = table - return Parser(tables, unicode(self)) + return Parser(tables, str(self)) class SyntaxRule(Printable): # A production rule. def __init__(self, name, dfa, match, fail, doc): - assert isinstance(name, unicode) - assert isinstance(doc, unicode) + assert isinstance(name, str) + assert isinstance(doc, str) self.name = name self.dfa = dfa self.match = match @@ -858,7 +858,7 @@ class ParseTable(object): # A production rule compiled into a state machine. def __init__(self, name, machine, match, fail): - assert isinstance(name, unicode) + assert isinstance(name, str) self.name = name self.machine = machine self.match = match @@ -907,7 +907,7 @@ def mark(self, node): point(node, mark) return node - def __nonzero__(self): + def __bool__(self): return (self.index < len(self.nodes)) def __len__(self): @@ -919,7 +919,7 @@ class Parser(Printable): def __init__(self, tables, doc): assert isinstance(tables, omapof(ParseTable)) and len(tables) > 0 - assert isinstance(doc, unicode) + assert isinstance(doc, str) self.start = next(iter(tables)).name self.tables = tables self.doc = doc diff --git a/src/htsql/core/syn/parse.py b/src/htsql/core/syn/parse.py index a4facc5..9dc6d7e 100644 --- a/src/htsql/core/syn/parse.py +++ b/src/htsql/core/syn/parse.py @@ -74,15 +74,15 @@ def match_specifier(stream): larms = [] larm = stream.pull() # parameter larms.append(larm) - while stream.peek(u'.'): + while stream.peek('.'): stream.pull() # `.` larm = stream.pull() # parameter larms.append(larm) rarms = None - if stream.peek(u'('): + if stream.peek('('): rarms = [] stream.pull() # `(` - while not stream.peek(u')'): + while not stream.peek(')'): rarm = stream.pull() # parameter rarms.append(rarm) stream.pull() # `)` @@ -136,11 +136,11 @@ def match_pipe(stream): identifier = stream.pull() # identifier rarms = [] is_open = True - if stream and not (stream.peek(u'/') or stream.peek(PIPESIG)): - if stream.peek(u'('): + if stream and not (stream.peek('/') or stream.peek(PIPESIG)): + if stream.peek('('): is_open = False stream.pull() # `(` - while not stream.peek(u')'): + while not stream.peek(')'): arm = stream.pull() # assignment rarms.append(arm) stream.pull() # `)` @@ -170,7 +170,7 @@ def match_flow_pipe(stream): while stream: if stream.peek(DIRSIG): stream.pull() # %DIRSIG - if stream.peek(u'+') or stream.peek(u'-'): + if stream.peek('+') or stream.peek('-'): direction = stream.pull() # `+` | `-` syntax = DirectSyntax(direction.text, syntax) stream.mark(syntax) @@ -180,15 +180,15 @@ def match_flow_pipe(stream): identifier = stream.pull() # identifier rarms = [] is_open = True - if stream and not stream.peek(u':'): - if stream.peek(u'('): + if stream and not stream.peek(':'): + if stream.peek('('): is_open = False stream.pull() # `(` - while not stream.peek(u')'): + while not stream.peek(')'): rarm = stream.pull() # assignment rarms.append(rarm) stream.pull() # `)` - elif not (stream.peek(u'+') or stream.peek(u'-')): + elif not (stream.peek('+') or stream.peek('-')): rarm = stream.pull() # flow_assignment rarms.append(rarm) is_flow = True @@ -210,13 +210,13 @@ def match_flow_pipe(stream): def match_flow(stream): syntax = stream.pull() # disjunction while stream: - if stream.peek(u'?'): + if stream.peek('?'): larm = syntax stream.pull() # `?` rarm = stream.pull() # disjunction syntax = FilterSyntax(larm, rarm) stream.mark(syntax) - elif stream.peek(u'^'): + elif stream.peek('^'): larm = syntax stream.pull() # `^` rarm = stream.pull() # disjunction @@ -227,7 +227,7 @@ def match_flow(stream): rarm = stream.pull() # record syntax = SelectSyntax(larm, rarm) stream.mark(syntax) - while stream.peek(u'.'): + while stream.peek('.'): stream.pull() # `.` larm = syntax rarm = stream.pull() # location @@ -267,7 +267,7 @@ def match_operator(stream): @negation.set_match def match_negation(stream): - if stream.peek(u'!'): + if stream.peek('!'): operator = stream.pull() # `!` arm = stream.pull() # negation syntax = PrefixSyntax(operator.text, arm) @@ -308,7 +308,7 @@ def match_negation(stream): @factor.set_match def match_factor(stream): - if stream.peek(u'+') or stream.peek(u'-'): + if stream.peek('+') or stream.peek('-'): prefix = stream.pull() # `+` | `-` arm = stream.pull() # factor syntax = PrefixSyntax(prefix.text, arm) @@ -326,7 +326,7 @@ def match_factor(stream): @linking.set_match def match_linking(stream): syntax = stream.pull() # composition - if stream.peek(u'->'): + if stream.peek('->'): larm = syntax stream.pull() # `->` rarm = stream.pull() # flow @@ -435,7 +435,7 @@ def match_unpacking(stream): index = None is_open = True if stream: - if stream.peek(u'('): + if stream.peek('('): is_open = False stream.pull() # `(` index = stream.pull() # %INTEGER @@ -474,7 +474,7 @@ def match_function(stream): identifier = syntax stream.pull() # `(` arms = [] - while not stream.peek(u')'): + while not stream.peek(')'): arm = stream.pull() # assignment arms.append(arm) stream.pull() # `)` @@ -516,7 +516,7 @@ def match_lift(stream): def match_record(stream): stream.pull() # `{` arms = [] - while not stream.peek(u'}'): + while not stream.peek('}'): arm = stream.pull() # assignment arms.append(arm) stream.pull() # `}` @@ -532,19 +532,19 @@ def match_record(stream): @list_.set_match def match_list(stream): stream.pull() # `(` - if stream.peek(u')'): + if stream.peek(')'): stream.pull() # `)` syntax = ListSyntax([]) stream.mark(syntax) else: arm = stream.pull() # assignment - if stream.peek(u')'): + if stream.peek(')'): stream.pull() # `)` syntax = GroupSyntax(arm) else: arms = [arm] stream.pull() # `,` - while not stream.peek(u')'): + while not stream.peek(')'): arm = stream.pull() # assignment arms.append(arm) stream.pull() # `)` @@ -565,10 +565,10 @@ def match_list(stream): ''') def match_identity(stream): - is_hard = stream.peek(u'[') + is_hard = stream.peek('[') stream.pull() # `[` | `(` arms = [] - while not (stream.peek(u']') or stream.peek(u')')): + while not (stream.peek(']') or stream.peek(')')): arm = stream.pull() # label arms.append(arm) stream.pull() # `]` | `)` diff --git a/src/htsql/core/syn/syntax.py b/src/htsql/core/syn/syntax.py index f580a56..cbc6694 100644 --- a/src/htsql/core/syn/syntax.py +++ b/src/htsql/core/syn/syntax.py @@ -31,7 +31,7 @@ def __basis__(self): return () def __unicode__(self): - return u"" + return "" class SkipSyntax(Syntax): @@ -47,7 +47,7 @@ def __basis__(self): return () def __unicode__(self): - return u"/" + return "/" class AssignSyntax(Syntax): @@ -75,7 +75,7 @@ def __basis__(self): return (self.larm, self.rarm) def __unicode__(self): - return u"%s:=%s" % (self.larm, self.rarm) + return "%s:=%s" % (self.larm, self.rarm) def __yaml__(self): yield ('larm', self.larm) @@ -130,12 +130,12 @@ def __basis__(self): def __unicode__(self): chunks = [] - chunks.append(u".".join(unicode(arm) for arm in self.larms)) + chunks.append(".".join(str(arm) for arm in self.larms)) if self.rarms is not None: - chunks.append(u"(") - chunks.append(u",".join(unicode(arm) for arm in self.rarms)) - chunks.append(u")") - return u"".join(chunks) + chunks.append("(") + chunks.append(",".join(str(arm) for arm in self.rarms)) + chunks.append(")") + return "".join(chunks) def __yaml__(self): yield ('larms', self.larms) @@ -158,7 +158,7 @@ class ApplySyntax(Syntax): """ def __init__(self, name, arguments): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(arguments, listof(Syntax)) self.name = name self.arguments = arguments @@ -190,8 +190,8 @@ def __basis__(self): return (self.identifier, tuple(self.arms)) def __unicode__(self): - return u"%s(%s)" % (self.identifier, - u",".join(unicode(arm) for arm in self.arms)) + return "%s(%s)" % (self.identifier, + ",".join(str(arm) for arm in self.arms)) def __yaml__(self): yield ('identifier', self.identifier) @@ -245,20 +245,20 @@ def __basis__(self): def __unicode__(self): chunks = [] - chunks.append(unicode(self.larm)) + chunks.append(str(self.larm)) if self.is_flow: - chunks.append(u" :") + chunks.append(" :") else: - chunks.append(u"/:") - chunks.append(unicode(self.identifier)) + chunks.append("/:") + chunks.append(str(self.identifier)) if not self.is_open: - chunks.append(u"(") + chunks.append("(") elif self.rarms: - chunks.append(u" ") - chunks.append(u",".join(unicode(arm) for arm in self.rarms)) + chunks.append(" ") + chunks.append(",".join(str(arm) for arm in self.rarms)) if not self.is_open: - chunks.append(u")") - return u"".join(chunks) + chunks.append(")") + return "".join(chunks) def __yaml__(self): yield ('is_flow', self.is_flow) @@ -288,7 +288,7 @@ class OperatorSyntax(ApplySyntax): """ def __init__(self, symbol, larm, rarm): - assert isinstance(symbol, unicode) + assert isinstance(symbol, str) assert isinstance(larm, Syntax) assert isinstance(rarm, Syntax) super(OperatorSyntax, self).__init__(symbol, [larm, rarm]) @@ -300,7 +300,7 @@ def __basis__(self): return (self.symbol, self.larm, self.rarm) def __unicode__(self): - return u"%s%s%s" % (self.larm, self.symbol, self.rarm) + return "%s%s%s" % (self.larm, self.symbol, self.rarm) def __yaml__(self): yield ('symbol', self.symbol) @@ -324,7 +324,7 @@ class PrefixSyntax(ApplySyntax): """ def __init__(self, symbol, arm): - assert isinstance(symbol, unicode) + assert isinstance(symbol, str) assert isinstance(arm, Syntax) super(PrefixSyntax, self).__init__(symbol, [arm]) self.symbol = symbol @@ -334,7 +334,7 @@ def __basis__(self): return (self.symbol, self.arm) def __unicode__(self): - return u"%s%s" % (self.symbol, self.arm) + return "%s%s" % (self.symbol, self.arm) def __yaml__(self): yield ('symbol', self.symbol) @@ -351,7 +351,7 @@ class FilterSyntax(OperatorSyntax): """ def __init__(self, larm, rarm): - super(FilterSyntax, self).__init__(u'?', larm, rarm) + super(FilterSyntax, self).__init__('?', larm, rarm) def __yaml__(self): yield ('larm', self.larm) @@ -368,7 +368,7 @@ class ProjectSyntax(OperatorSyntax): """ def __init__(self, larm, rarm): - super(ProjectSyntax, self).__init__(u'^', larm, rarm) + super(ProjectSyntax, self).__init__('^', larm, rarm) def __yaml__(self): yield ('larm', self.larm) @@ -385,7 +385,7 @@ class LinkSyntax(OperatorSyntax): """ def __init__(self, larm, rarm): - super(LinkSyntax, self).__init__(u'->', larm, rarm) + super(LinkSyntax, self).__init__('->', larm, rarm) def __yaml__(self): yield ('larm', self.larm) @@ -402,7 +402,7 @@ class AttachSyntax(OperatorSyntax): """ def __init__(self, larm, rarm): - super(AttachSyntax, self).__init__(u'@', larm, rarm) + super(AttachSyntax, self).__init__('@', larm, rarm) def __yaml__(self): yield ('larm', self.larm) @@ -419,7 +419,7 @@ class DetachSyntax(PrefixSyntax): """ def __init__(self, arm): - super(DetachSyntax, self).__init__(u'@', arm) + super(DetachSyntax, self).__init__('@', arm) def __yaml__(self): yield ('arm', self.arm) @@ -435,7 +435,7 @@ class CollectSyntax(PrefixSyntax): """ def __init__(self, arm): - super(CollectSyntax, self).__init__(u'/', arm) + super(CollectSyntax, self).__init__('/', arm) def __yaml__(self): yield ('arm', self.arm) @@ -458,7 +458,7 @@ class DirectSyntax(Syntax): """ def __init__(self, symbol, arm): - assert isinstance(symbol, unicode) and symbol in [u'+', u'-'] + assert isinstance(symbol, str) and symbol in ['+', '-'] assert isinstance(arm, Syntax) self.symbol = symbol self.arm = arm @@ -467,7 +467,7 @@ def __basis__(self): return (self.symbol, self.arm) def __unicode__(self): - return u"%s%s" % (self.arm, self.symbol) + return "%s%s" % (self.arm, self.symbol) def __yaml__(self): yield ('symbol', self.symbol) @@ -502,14 +502,14 @@ def __basis__(self): def __unicode__(self): chunks = [] - chunk = unicode(self.larm) + chunk = str(self.larm) chunks.append(chunk) # Make sure we do not accidentally make a decimal literal. if self.endswithint_regexp.search(chunk): - chunks.append(u" ") - chunks.append(u".") - chunks.append(unicode(self.rarm)) - return u"".join(chunks) + chunks.append(" ") + chunks.append(".") + chunks.append(str(self.rarm)) + return "".join(chunks) def __yaml__(self): yield ('larm', self.larm) @@ -534,7 +534,7 @@ class UnpackSyntax(Syntax): """ def __init__(self, index, is_open): - assert index is None or (isinstance(index, (int, long)) and index >= 0) + assert index is None or (isinstance(index, int) and index >= 0) assert isinstance(is_open, bool) self.index = index self.is_open = is_open @@ -544,14 +544,14 @@ def __basis__(self): def __unicode__(self): chunks = [] - chunks.append(u"*") + chunks.append("*") if not self.is_open: - chunks.append(u"(") + chunks.append("(") if self.index is not None: - chunks.append(unicode(self.index)) + chunks.append(str(self.index)) if not self.is_open: - chunks.append(u")") - return u"".join(chunks) + chunks.append(")") + return "".join(chunks) def __yaml__(self): if self.index is not None: @@ -572,7 +572,7 @@ def __basis__(self): return () def __unicode__(self): - return u"^" + return "^" class GroupSyntax(Syntax): @@ -595,7 +595,7 @@ def __basis__(self): return (self.arm,) def __unicode__(self): - return u"(%s)" % self.arm + return "(%s)" % self.arm def __yaml__(self): yield ('arm', self.arm) @@ -626,7 +626,7 @@ def __basis__(self): return (self.larm, self.rarm) def __unicode__(self): - return u"%s%s" % (self.larm, self.rarm) + return "%s%s" % (self.larm, self.rarm) def __yaml__(self): yield ('larm', self.larm) @@ -658,7 +658,7 @@ def __basis__(self): return (self.larm, self.rarm) def __unicode__(self): - return u"%s%s" % (self.larm, self.rarm) + return "%s%s" % (self.larm, self.rarm) def __yaml__(self): yield ('larm', self.larm) @@ -685,7 +685,7 @@ def __basis__(self): return (tuple(self.arms),) def __unicode__(self): - return u"{%s}" % u",".join(unicode(arm) for arm in self.arms) + return "{%s}" % ",".join(str(arm) for arm in self.arms) def __yaml__(self): yield ('arms', self.arms) @@ -712,12 +712,12 @@ def __basis__(self): def __unicode__(self): chunks = [] - chunks.append(u"(") - chunks.append(u"".join(unicode(arm) for arm in self.arms)) + chunks.append("(") + chunks.append("".join(str(arm) for arm in self.arms)) if len(self.arms) == 1: - chunks.append(u",") - chunks.append(u")") - return u"".join(chunks) + chunks.append(",") + chunks.append(")") + return "".join(chunks) def __yaml__(self): yield ('arms', self.arms) @@ -752,15 +752,15 @@ def __basis__(self): def __unicode__(self): chunks = [] if self.is_hard: - chunks.append(u"[") + chunks.append("[") else: - chunks.append(u"(") - chunks.append(u".".join(unicode(arm) for arm in self.arms)) + chunks.append("(") + chunks.append(".".join(str(arm) for arm in self.arms)) if self.is_hard: - chunks.append(u"]") + chunks.append("]") else: - chunks.append(u")") - return u"".join(chunks) + chunks.append(")") + return "".join(chunks) def __yaml__(self): yield ('is_hard', self.is_hard) @@ -791,7 +791,7 @@ def __basis__(self): return (self.identifier,) def __unicode__(self): - return u"$%s" % self.identifier + return "$%s" % self.identifier def __yaml__(self): yield ('identifier', self.identifier) @@ -813,7 +813,7 @@ class IdentifierSyntax(Syntax): """ def __init__(self, text): - assert isinstance(text, unicode) + assert isinstance(text, str) self.text = text self.name = to_name(text) @@ -841,7 +841,7 @@ class LiteralSyntax(Syntax): """ def __init__(self, text): - assert isinstance(text, unicode) + assert isinstance(text, str) self.text = text def __basis__(self): diff --git a/src/htsql/core/syn/token.py b/src/htsql/core/syn/token.py index 3c035bc..a3f4c22 100644 --- a/src/htsql/core/syn/token.py +++ b/src/htsql/core/syn/token.py @@ -4,7 +4,7 @@ from ..util import Clonable, Hashable, Printable, YAMLable -import urllib +import urllib.request, urllib.parse, urllib.error class Token(Clonable, Hashable, Printable, YAMLable): @@ -21,15 +21,15 @@ class Token(Clonable, Hashable, Printable, YAMLable): """ def __init__(self, code, text): - assert isinstance(code, unicode) - assert isinstance(text, unicode) + assert isinstance(code, str) + assert isinstance(text, str) self.code = code self.text = text def __basis__(self): return (self.code, self.text) - def __nonzero__(self): + def __bool__(self): # `False` for EOF token; `True` otherwise. return bool(self.code) @@ -37,18 +37,18 @@ def __unicode__(self): # '$', '``:' or '%:' chunks = [] if not self.code: - chunks.append(u"$") + chunks.append("$") elif self.code.isalpha(): - chunks.append(u"%"+self.code) + chunks.append("%"+self.code) else: - chunks.append(u"`%s`" % self.code.replace(u"`", u"``")) + chunks.append("`%s`" % self.code.replace("`", "``")) if self.text: - chunks.append(u":") + chunks.append(":") text = self.text.encode('utf-8') - text = urllib.quote(text, safe='') + text = urllib.parse.quote(text, safe='') text = text.decode('utf-8') chunks.append(text) - return u"".join(chunks) + return "".join(chunks) def __yaml__(self): yield ('code', self.code) @@ -61,54 +61,54 @@ def __yaml__(self): # # The query end. -END = u'' +END = '' # A sequence of alphanumeric characters that does not start with a digit. -NAME = u'NAME' +NAME = 'NAME' # A sequence of characters enclosed in single quotes. -STRING = u'STRING' +STRING = 'STRING' # An unsigned integer number. -INTEGER = u'INTEGER' +INTEGER = 'INTEGER' # An unsigned decimal number. -DECIMAL = u'DECIMAL' +DECIMAL = 'DECIMAL' # An unsigned number in exponentional notation. -FLOAT = u'FLOAT' +FLOAT = 'FLOAT' # A sequence of alphanumeric characters (including `-`) in an identity literal. -LABEL = u'LABEL' +LABEL = 'LABEL' # Various operator and punctuation symbols. SYMBOLS = [ # comparison operators - u'=', u'!=', u'==', u'!==', u'~', u'!~', u'<', u'<=', u'>', u'>=', + '=', '!=', '==', '!==', '~', '!~', '<', '<=', '>', '>=', # logical operators - u'!', u'&', u'|', + '!', '&', '|', # arithmetic operators - u'+', u'-', u'*', u'/', + '+', '-', '*', '/', # flow operators - u'^', u'?', u'->', u'@', + '^', '?', '->', '@', # assignment operator - u':=', + ':=', # punctuation - u'(', u')', u'[', u']', u'{', u'}', u'.', u',', u':', u';', u'$', + '(', ')', '[', ']', '{', '}', '.', ',', ':', ';', '$', ] # A signalling token for `+` and `-` direction indicators. -DIRSIG = u'DIRSIG' +DIRSIG = 'DIRSIG' # A signalling token for `/` `:` sequence starting a pipe notation. -PIPESIG = u'PIPESIG' +PIPESIG = 'PIPESIG' # A signalling token for the LHS of assignment operator (`:=`). -LHSSIG = u'LHSSIG' +LHSSIG = 'LHSSIG' diff --git a/src/htsql/core/tr/assemble.py b/src/htsql/core/tr/assemble.py index e7b1397..3987679 100644 --- a/src/htsql/core/tr/assemble.py +++ b/src/htsql/core/tr/assemble.py @@ -1072,7 +1072,7 @@ def assemble_dependents(self): dependent = self.state.assemble(subterm) index_by_term[subterm] = len(dependents) dependents.append(dependent) - for subterm in index_by_term.keys(): + for subterm in list(index_by_term.keys()): index_by_term[subterm] -= len(dependents) return dependents, index_by_term diff --git a/src/htsql/core/tr/bind.py b/src/htsql/core/tr/bind.py index 11ab85d..bab8653 100644 --- a/src/htsql/core/tr/bind.py +++ b/src/htsql/core/tr/bind.py @@ -212,7 +212,7 @@ def __call__(self): def hint_choices(choices): # Generate a hint from a list of choices. - assert isinstance(choices, listof(unicode)) + assert isinstance(choices, listof(str)) if not choices: return None chunks = ["did you mean:"] @@ -767,7 +767,7 @@ class BindDirect(Bind): def __call__(self): base = self.state.bind(self.syntax.arm) - direction = {u'+': +1, u'-': -1}[self.syntax.symbol] + direction = {'+': +1, '-': -1}[self.syntax.symbol] return DirectionBinding(base, direction, self.syntax) @@ -782,7 +782,7 @@ def __call__(self): if recipe is None: model = self.syntax.identifier.name.lower() names = lookup_reference_set(self.state.scope) - choices = [u"$"+name for name in sorted(names) + choices = ["$"+name for name in sorted(names) if similar(model, name)] with choices_guard(choices): raise Error("Found unknown reference", self.syntax) @@ -908,7 +908,7 @@ def __dominates__(component, other): def __matches__(component, dispatch_key): # Check if the component matches the given function name # and the number of arguments. - assert isinstance(dispatch_key, tupleof(unicode, maybe(int))) + assert isinstance(dispatch_key, tupleof(str, maybe(int))) # The name and the number of arguments of the call node. key_name, key_arity = dispatch_key diff --git a/src/htsql/core/tr/binding.py b/src/htsql/core/tr/binding.py index 4196957..38c85a4 100644 --- a/src/htsql/core/tr/binding.py +++ b/src/htsql/core/tr/binding.py @@ -49,7 +49,7 @@ def __init__(self, base, domain, syntax): point(self, syntax) def __unicode__(self): - return unicode(self.syntax) + return str(self.syntax) class Recipe(Hashable): @@ -339,7 +339,7 @@ class DefineBinding(DecorateBinding): """ def __init__(self, base, name, arity, recipe, syntax): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(arity, maybe(int)) assert isinstance(recipe, Recipe) super(DefineBinding, self).__init__(base, syntax) @@ -360,7 +360,7 @@ class DefineReferenceBinding(DecorateBinding): """ def __init__(self, base, name, recipe, syntax): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(recipe, Recipe) super(DefineReferenceBinding, self).__init__(base, syntax) self.name = name @@ -373,7 +373,7 @@ class DefineCollectionBinding(DecorateBinding): """ def __init__(self, base, collection, is_reference, syntax): - assert isinstance(collection, dictof(unicode, Recipe)) + assert isinstance(collection, dictof(str, Recipe)) assert isinstance(is_reference, bool) super(DefineCollectionBinding, self).__init__(base, syntax) self.collection = collection @@ -556,9 +556,9 @@ class AssignmentBinding(Binding): """ def __init__(self, base, terms, parameters, body, syntax): - assert isinstance(terms, listof(tupleof(unicode, bool))) + assert isinstance(terms, listof(tupleof(str, bool))) assert len(terms) > 0 - assert isinstance(parameters, maybe(listof(tupleof(unicode, bool)))) + assert isinstance(parameters, maybe(listof(tupleof(str, bool)))) assert isinstance(body, Syntax) super(AssignmentBinding, self).__init__(base, VoidDomain(), syntax) self.terms = terms @@ -657,7 +657,7 @@ class FormatBinding(WrappingBinding): # FIXME: currently unused. def __init__(self, base, format, syntax): - assert isinstance(format, unicode) + assert isinstance(format, str) super(FormatBinding, self).__init__(base, syntax) self.format = format @@ -910,8 +910,8 @@ class SubstitutionRecipe(Recipe): def __init__(self, base, terms, parameters, body): assert isinstance(base, Binding) - assert isinstance(terms, listof(tupleof(unicode, bool))) - assert isinstance(parameters, maybe(listof(tupleof(unicode, bool)))) + assert isinstance(terms, listof(tupleof(str, bool))) + assert isinstance(parameters, maybe(listof(tupleof(str, bool)))) assert isinstance(body, Syntax) self.base = base self.terms = terms @@ -1034,7 +1034,7 @@ class AmbiguousRecipe(InvalidRecipe): """ def __init__(self, alternatives=None): - assert isinstance(alternatives, maybe(listof(unicode))) + assert isinstance(alternatives, maybe(listof(str))) super(AmbiguousRecipe, self).__init__() self.alternatives = alternatives diff --git a/src/htsql/core/tr/dump.py b/src/htsql/core/tr/dump.py index 550fa22..e4e1077 100644 --- a/src/htsql/core/tr/dump.py +++ b/src/htsql/core/tr/dump.py @@ -29,12 +29,12 @@ from .pipe import (SQLPipe, BatchSQLPipe, RecordPipe, ComposePipe, ProducePipe, MixPipe) from ..connect import unscramble -import StringIO +import io import re import math -class Stream(StringIO.StringIO, object): +class Stream(io.StringIO, object): """ Implements a writable file-like object. @@ -66,13 +66,13 @@ def write(self, data): Writes a string to the stream. """ # Expect a Unicode string. - assert isinstance(data, unicode) + assert isinstance(data, str) # Call `StringIO.write`, which performs the action. super(Stream, self).write(data) # Update the cursor position. Note that we count # Unicode codepoints rather than bytes. - if u"\n" in data: - self.column = len(data)-data.rindex(u"\n")-1 + if "\n" in data: + self.column = len(data)-data.rindex("\n")-1 else: self.column += len(data) @@ -81,9 +81,9 @@ def newline(self): Sets the cursor to the current indentation level. """ if self.column <= self.indentation: - self.write(u" "*(self.indentation-self.column)) + self.write(" "*(self.indentation-self.column)) else: - self.write(u"\n"+u" "*self.indentation) + self.write("\n"+" "*self.indentation) def indent(self): """ @@ -433,8 +433,8 @@ def names_to_aliases(self, names, taken_aliases): alias = name[:self.max_alias_length] number = 1 else: - cut = self.max_alias_length - len(unicode(number)) - 1 - alias = u"%s_%s" % (name[:cut], number) + cut = self.max_alias_length - len(str(number)) - 1 + alias = "%s_%s" % (name[:cut], number) number += 1 next_number_by_name[name] = number # Check if the alias is already reserved. @@ -527,7 +527,7 @@ def format(self, template, *namespaces, **keywords): `namespaces`, `keywords` (dictionaries) Dictionaries containing substitution variables. """ - assert isinstance(template, (str, unicode)) + assert isinstance(template, str) if isinstance(template, str): template = template.decode() # Aggregate variables from the given namespaces. A namespace is @@ -554,7 +554,7 @@ def format(self, template, *namespaces, **keywords): # }} -> } chunk = match.group('chunk') if chunk is not None: - chunk = chunk.replace(u"{{", u"{").replace(u"}}", u"}") + chunk = chunk.replace("{{", "{").replace("}}", "}") self.stream.write(chunk) # It must be variable substitution then. Extract the value # of the variable and realize a `Format` instance to perform @@ -679,10 +679,10 @@ class FormatUnion(Format): def __init__(self, kind, value, modifier, state): assert isinstance(value, listof(Clause)) and len(value) > 0 - assert isinstance(modifier, maybe(unicode)) + assert isinstance(modifier, maybe(str)) # The default separator is `', '`. if modifier is None: - modifier = u", " + modifier = ", " super(FormatUnion, self).__init__(kind, value, modifier, state) def __call__(self): @@ -709,11 +709,11 @@ class FormatName(Format): call('name') def __init__(self, kind, value, modifier, state): - assert isinstance(value, unicode) + assert isinstance(value, str) assert modifier is None # This is the last place where we could prevent an injection attack, # so check that the string is well-formed. - assert u"\0" not in value + assert "\0" not in value assert len(value) > 0 super(FormatName, self).__init__(kind, value, modifier, state) @@ -722,7 +722,7 @@ def __call__(self): # - an identifier is enclosed by `"`; # - any `"` character must be replaced with `""`. # A backend with non-standard quoting rules must override this method. - self.stream.write(u"\"%s\"" % self.value.replace(u"\"", u"\"\"")) + self.stream.write("\"%s\"" % self.value.replace("\"", "\"\"")) class FormatLiteral(Format): @@ -739,11 +739,11 @@ class FormatLiteral(Format): call('literal') def __init__(self, kind, value, modifier, state): - assert isinstance(value, unicode) + assert isinstance(value, str) assert modifier is None # This is the last place where we could prevent an injection attack, # so check that the string is well-formed. - assert u"\0" not in value + assert "\0" not in value super(FormatLiteral, self).__init__(kind, value, modifier, state) def __call__(self): @@ -752,7 +752,7 @@ def __call__(self): # - any `'` character must be replaced with `''`. # We also assume the backend accepts UTF-8 encoded strings. # A backend with non-standard quoting rules must override this method. - self.stream.write(u"'%s'" % self.value.replace(u"'", u"''")) + self.stream.write("'%s'" % self.value.replace("'", "''")) class FormatNot(Format): @@ -781,7 +781,7 @@ def __call__(self): # polarity=+1 => "" # polarity=-1 => "NOT " if self.value < 0: - self.stream.write(u"NOT ") + self.stream.write("NOT ") class FormatSwitch(Format): @@ -802,14 +802,14 @@ class FormatSwitch(Format): def __init__(self, kind, value, modifier, state): assert value in [+1, -1] - assert isinstance(modifier, unicode) and modifier.count(u"|") + assert isinstance(modifier, str) and modifier.count("|") super(FormatSwitch, self).__init__(kind, value, modifier, state) def __call__(self): # For `{polarity:switch{P|N}}`, dump # polarity=+1 => P # polarity=-1 => N - positive, negative = self.modifier.split(u"|") + positive, negative = self.modifier.split("|") if self.value > 0: self.stream.write(positive) else: @@ -830,15 +830,15 @@ class FormatPlaceholder(Format): call('placeholder') def __init__(self, kind, value, modifier, state): - assert isinstance(value, maybe(unicode)) + assert isinstance(value, maybe(str)) assert modifier is None super(FormatPlaceholder, self).__init__(kind, value, modifier, state) def __call__(self): if self.value is None: - self.stream.write(u"?") + self.stream.write("?") else: - self.stream.write(u":"+self.value) + self.stream.write(":"+self.value) class FormatPass(Format): @@ -855,7 +855,7 @@ class FormatPass(Format): call('pass') def __init__(self, kind, value, modifier, state): - assert isinstance(value, unicode) + assert isinstance(value, str) assert modifier is None super(FormatPass, self).__init__(kind, value, modifier, state) @@ -886,7 +886,7 @@ def __init__(self, clause, state): def __call__(self): # The adapter must never fail, so the default implementation # provides a valid, though meaningless, alias name. - return u"!" + return "!" class Dump(DumpBase): @@ -1051,7 +1051,7 @@ def dump_select(self): aliases = self.state.select_aliases_by_tag[self.frame.tag] # Write `SELECT` and set the indentation level to the position # after `SELECT`. - self.write(u"SELECT ") + self.write("SELECT ") self.indent() # Serialize the selection phrases. for index, phrase in enumerate(self.frame.select): @@ -1085,7 +1085,7 @@ def dump_select(self): selection=phrase) # Write the trailing comma. if index < len(self.frame.select)-1: - self.write(u",") + self.write(",") self.newline() # Restore the original indentation level. self.dedent() @@ -1101,7 +1101,7 @@ def dump_include(self): return # Write `FROM` and set the indentation level to the next position. self.newline() - self.write(u"FROM ") + self.write("FROM ") self.indent() # Serialize the subframes. for index, anchor in enumerate(self.frame.include): @@ -1123,13 +1123,13 @@ def dump_where(self): self.newline() # Handle the case when the condition is an `AND` operator. if isformula(self.frame.where, AndSig): - self.write(u"WHERE ") + self.write("WHERE ") self.indent() for index, op in enumerate(self.frame.where.ops): self.format("{op}", op=op) if index < len(self.frame.where.ops)-1: self.newline() - self.write(u"AND ") + self.write("AND ") self.dedent() # Handle the regular case. else: @@ -1144,13 +1144,13 @@ def dump_group(self): if not self.frame.group: return self.newline() - self.write(u"GROUP BY ") + self.write("GROUP BY ") # Write the `GROUP BY` items. for index, phrase in enumerate(self.frame.group): - self.format(u"{kernel}", kernel=phrase) + self.format("{kernel}", kernel=phrase) # Dump the trailing comma. if index < len(self.frame.group)-1: - self.write(u", ") + self.write(", ") def dump_having(self): # Serialize a `HAVING` clause. Dump: @@ -1169,13 +1169,13 @@ def dump_having(self): self.newline() # Handle the case when the condition is an `AND` operator. if isformula(self.frame.having, AndSig): - self.write(u"HAVING ") + self.write("HAVING ") self.indent() for index, op in enumerate(self.frame.having.ops): self.format("{op}", op=op) if index < len(self.frame.having.ops)-1: self.newline() - self.write(u"AND ") + self.write("AND ") self.dedent() # Handle the regular case. else: @@ -1190,13 +1190,13 @@ def dump_order(self): if not self.frame.order: return self.newline() - self.write(u"ORDER BY ") + self.write("ORDER BY ") # Write the `GROUP BY` items. for index, phrase in enumerate(self.frame.order): self.format("{kernel}", kernel=phrase) # Write the trailing comma. if index < len(self.frame.order)-1: - self.write(u", ") + self.write(", ") def dump_limit(self): # Serialize `LIMIT` and `OFFSET` clauses. Dump: @@ -1212,11 +1212,11 @@ def dump_limit(self): # Dump a `LIMIT` clause. if self.frame.limit is not None: self.newline() - self.write(u"LIMIT "+unicode(self.frame.limit)) + self.write("LIMIT "+str(self.frame.limit)) # Dump an `OFFSET` clause. if self.frame.offset is not None: self.newline() - self.write(u"OFFSET "+unicode(self.frame.offset)) + self.write("OFFSET "+str(self.frame.offset)) class DumpNested(Dump): @@ -1230,11 +1230,11 @@ def __call__(self): # Dump: # (SELECT ... # ...) - self.write(u"(") + self.write("(") self.indent() super(DumpNested, self).__call__() self.dedent() - self.write(u")") + self.write(")") class DumpSegment(Dump): @@ -1297,15 +1297,15 @@ def __call__(self): # Dump the `JOIN` clause. self.newline() if self.clause.is_cross: - self.write(u"CROSS JOIN ") + self.write("CROSS JOIN ") elif self.clause.is_inner: - self.write(u"INNER JOIN ") + self.write("INNER JOIN ") elif self.clause.is_left and not self.clause.is_right: - self.write(u"LEFT OUTER JOIN ") + self.write("LEFT OUTER JOIN ") elif self.clause.is_right and not self.clause.is_left: - self.write(u"RIGHT OUTER JOIN ") + self.write("RIGHT OUTER JOIN ") else: - self.write(u"FULL OUTER JOIN ") + self.write("FULL OUTER JOIN ") self.indent() self.state.push_hook(with_aliases=True) if alias is not None: @@ -1435,7 +1435,7 @@ def __call__(self): # `NULL` in every implementation of `DumpByDomain`. # FIXME: This assumes that we never need to add an explicit type # specifier to a `NULL` value. - self.write(u"NULL") + self.write("NULL") class DumpByDomain(DumpBase): @@ -1489,9 +1489,9 @@ def __call__(self): # Use the SQL standard constants: `TRUE` and `FALSE`. # Backends not supporting those must override this implementation. if self.value is True: - self.write(u"TRUE") + self.write("TRUE") if self.value is False: - self.write(u"FALSE") + self.write("FALSE") class DumpInteger(DumpByDomain): @@ -1511,9 +1511,9 @@ def __call__(self): raise Error("Found integer value is out of range") # Write the number; use `(...)` around a negative number. if self.value >= 0: - self.write(unicode(self.value)) + self.write(str(self.value)) else: - self.write(u"(%s)" % self.value) + self.write("(%s)" % self.value) class DumpFloat(DumpByDomain): @@ -1534,9 +1534,9 @@ def __call__(self): # the database could figure out its type from the context; use `(...)` # around a negative number. if self.value >= 0.0: - self.write(u"%r" % self.value) + self.write("%r" % self.value) else: - self.write(u"(%r)" % self.value) + self.write("(%r)" % self.value) class DumpDecimal(DumpByDomain): @@ -1557,9 +1557,9 @@ def __call__(self): # the database could figure out its type from the context; use `(...)` # around a negative number. if not self.value.is_signed(): - self.write(unicode(self.value)) + self.write(str(self.value)) else: - self.write(u"(%s)" % self.value) + self.write("(%s)" % self.value) class DumpText(DumpByDomain): @@ -1599,7 +1599,7 @@ def __call__(self): # DATE 'YYYY-MM-DD' # A backend with a different (or no) date represetation may need # to override this implementation. - self.format("DATE {value:literal}", value=unicode(self.value)) + self.format("DATE {value:literal}", value=str(self.value)) class DumpTime(DumpByDomain): @@ -1610,7 +1610,7 @@ class DumpTime(DumpByDomain): adapt(TimeDomain) def __call__(self): - self.format("TIME {value:literal}", value=unicode(self.value)) + self.format("TIME {value:literal}", value=str(self.value)) class DumpDateTime(DumpByDomain): @@ -1622,10 +1622,10 @@ class DumpDateTime(DumpByDomain): def __call__(self): if self.value.tzinfo is None: - self.format("TIMESTAMP {value:literal}", value=unicode(self.value)) + self.format("TIMESTAMP {value:literal}", value=str(self.value)) else: self.format("TIMESTAMP WITH TIME ZONE {value:literal}", - value=unicode(self.value)) + value=str(self.value)) class DumpCast(Dump): @@ -1983,7 +1983,7 @@ def __call__(self): # Dump: # ( (<|<=|>|>=) ) self.format("({lop} {relation:pass} {rop})", - self.arguments, relation=unicode(self.signature.relation)) + self.arguments, relation=str(self.signature.relation)) class DumpSortDirection(DumpBySignature): @@ -2004,14 +2004,14 @@ class DumpRowNumber(DumpBySignature): adapt(RowNumberSig) def __call__(self): - self.write(u"ROW_NUMBER() OVER (") + self.write("ROW_NUMBER() OVER (") if self.phrase.partition: self.format("PARTITION BY {partition:union{, }}", self.arguments) if self.phrase.order: - self.write(u" ") + self.write(" ") if self.phrase.order: self.format("ORDER BY {order:union{, }}", self.arguments) - self.write(u")") + self.write(")") class DumpToPredicate(DumpBySignature): @@ -2037,7 +2037,7 @@ class DumpPlaceholder(DumpBySignature): def __call__(self): self.state.add_placeholder(self.signature.index, self.domain) self.format("{index:placeholder}", - index=unicode(self.signature.index+1)) + index=str(self.signature.index+1)) def serialize(clause, batch=None): diff --git a/src/htsql/core/tr/encode.py b/src/htsql/core/tr/encode.py index e40f72e..1422c98 100644 --- a/src/htsql/core/tr/encode.py +++ b/src/htsql/core/tr/encode.py @@ -591,7 +591,7 @@ def __call__(self): # a `ValueError` if the literal is not in a valid format. try: value = self.domain.parse(base.value) - except ValueError, exc: + except ValueError as exc: # FIXME: `domain.parse()` should raise `Error`? raise Error(str(exc)) # Generate a new literal node with the converted value and @@ -659,7 +659,7 @@ def __call__(self): # Encode the operand of the cast. code = self.state.encode(self.base) # An empty string. - empty_literal = LiteralCode(u'', self.base.domain, self.flow) + empty_literal = LiteralCode('', self.base.domain, self.flow) # Construct: `null_if(base,'')`. code = FormulaCode(NullIfSig(), self.base.domain, self.flow, lop=code, rop=empty_literal) diff --git a/src/htsql/core/tr/fn/bind.py b/src/htsql/core/tr/fn/bind.py index 2adb6b0..a157a8f 100644 --- a/src/htsql/core/tr/fn/bind.py +++ b/src/htsql/core/tr/fn/bind.py @@ -1039,7 +1039,7 @@ def pair(self, lop, rop): if isinstance(rop.domain, UntypedDomain): try: value = lop.domain.parse(rop.value) - except ValueError, exc: + except ValueError as exc: raise Error("Cannot coerce [%s] to %s" % (rop.value, lop.domain), exc) rop = LiteralBinding(rop.base, value, lop.domain, rop.syntax) diff --git a/src/htsql/core/tr/fn/dump.py b/src/htsql/core/tr/fn/dump.py index 8e9a2ac..b548276 100644 --- a/src/htsql/core/tr/fn/dump.py +++ b/src/htsql/core/tr/fn/dump.py @@ -175,7 +175,7 @@ class DumpLike(DumpFunction): def __call__(self): self.format("({lop} {polarity:not}LIKE {rop} ESCAPE {escape:literal})", - self.arguments, self.signature, escape=u"\\") + self.arguments, self.signature, escape="\\") class DumpReplace(DumpFunction): diff --git a/src/htsql/core/tr/fn/encode.py b/src/htsql/core/tr/fn/encode.py index c180b45..e6ad0d7 100644 --- a/src/htsql/core/tr/fn/encode.py +++ b/src/htsql/core/tr/fn/encode.py @@ -50,17 +50,17 @@ def __call__(self): rop = self.state.encode(self.flow.rop) if isinstance(rop, LiteralCode): if rop.value is not None: - value = (u"%" + rop.value.replace(u"\\", u"\\\\") - .replace(u"%", u"\\%") - .replace(u"_", u"\\_") + u"%") + value = ("%" + rop.value.replace("\\", "\\\\") + .replace("%", "\\%") + .replace("_", "\\_") + "%") rop = rop.clone(value=value) else: - backslash_literal = LiteralCode(u"\\", rop.domain, self.flow) - xbackslash_literal = LiteralCode(u"\\\\", rop.domain, self.flow) - percent_literal = LiteralCode(u"%", rop.domain, self.flow) - xpercent_literal = LiteralCode(u"\\%", rop.domain, self.flow) - underscore_literal = LiteralCode(u"_", rop.domain, self.flow) - xunderscore_literal = LiteralCode(u"\\_", rop.domain, self.flow) + backslash_literal = LiteralCode("\\", rop.domain, self.flow) + xbackslash_literal = LiteralCode("\\\\", rop.domain, self.flow) + percent_literal = LiteralCode("%", rop.domain, self.flow) + xpercent_literal = LiteralCode("\\%", rop.domain, self.flow) + underscore_literal = LiteralCode("_", rop.domain, self.flow) + xunderscore_literal = LiteralCode("\\_", rop.domain, self.flow) rop = FormulaCode(ReplaceSig(), rop.domain, self.flow, op=rop, old=backslash_literal, new=xbackslash_literal) @@ -330,7 +330,7 @@ def __call__(self): op = self.state.encode(self.flow.op) old = self.state.encode(self.flow.old) new = self.state.encode(self.flow.new) - empty = LiteralCode(u'', old.domain, self.flow) + empty = LiteralCode('', old.domain, self.flow) old = FormulaCode(IfNullSig(), old.domain, self.flow, lop=old, rop=empty) new = FormulaCode(IfNullSig(), old.domain, self.flow, @@ -428,7 +428,7 @@ class WrapCountSum(WrapAggregate): def __call__(self): root = RootFlow(self.unit.binding) - zero_literal = LiteralFlow(root, u'0', UntypedDomain(), + zero_literal = LiteralFlow(root, '0', UntypedDomain(), self.unit.binding) zero_literal = CastFlow(zero_literal, self.unit.domain, self.unit.binding) diff --git a/src/htsql/core/tr/fn/reduce.py b/src/htsql/core/tr/fn/reduce.py index 2b2a2b9..f03466f 100644 --- a/src/htsql/core/tr/fn/reduce.py +++ b/src/htsql/core/tr/fn/reduce.py @@ -42,7 +42,7 @@ class ReduceConcatenate(ReduceBySignature): adapt(ConcatenateSig) def __call__(self): - empty = LiteralPhrase(u'', self.phrase.domain, self.phrase.expression) + empty = LiteralPhrase('', self.phrase.domain, self.phrase.expression) lop = self.phrase.lop if lop.is_nullable: lop = FormulaPhrase(IfNullSig(), lop.domain, False, diff --git a/src/htsql/core/tr/lookup.py b/src/htsql/core/tr/lookup.py index ca29a60..de6873e 100644 --- a/src/htsql/core/tr/lookup.py +++ b/src/htsql/core/tr/lookup.py @@ -66,7 +66,7 @@ class AttributeProbe(Probe): """ def __init__(self, name, arity): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(arity, maybe(int)) assert arity is None or arity >= 0 self.name = name @@ -108,7 +108,7 @@ class ReferenceProbe(Probe): """ def __init__(self, name): - assert isinstance(name, unicode) + assert isinstance(name, str) self.name = name self.key = normalize(name) @@ -334,7 +334,7 @@ class GuessHeader(Lookup): adapt(Binding, GuessHeaderProbe) def __call__(self): - value = unicode(self.binding.syntax) + value = str(self.binding.syntax) if value: return value return None @@ -800,9 +800,9 @@ def __call__(self): return super(GuessHeaderFromQuotient, self).__call__() if len(kernel_headers) == 1: [kernel_header] = kernel_headers - return u"%s^%s" % (seed_header, kernel_header) + return "%s^%s" % (seed_header, kernel_header) else: - return u"%s^{%s}" % (seed_header, u",".join(kernel_headers)) + return "%s^{%s}" % (seed_header, ",".join(kernel_headers)) class LookupAttributeInComplement(Lookup): @@ -1158,7 +1158,7 @@ class GuessHeaderFromAlias(Lookup): adapt(AliasBinding, GuessHeaderProbe) def __call__(self): - return unicode(self.binding.syntax) + return str(self.binding.syntax) def prescribe(arc, binding): diff --git a/src/htsql/core/tr/pipe.py b/src/htsql/core/tr/pipe.py index e890530..75c7210 100644 --- a/src/htsql/core/tr/pipe.py +++ b/src/htsql/core/tr/pipe.py @@ -10,7 +10,7 @@ from ..error import PermissionError import operator import tempfile -import cPickle +import pickle class Pipe(Clonable, YAMLable): @@ -74,10 +74,10 @@ def run_sql(input, sql=self.sql.encode('utf-8'), def __yaml__(self): yield ('sql', self.sql+'\n') if self.input_domains: - yield ('input', [unicode(domain) + yield ('input', [str(domain) for domain in self.input_domains]) if self.output_domains: - yield ('output', [unicode(domain) + yield ('output', [str(domain) for domain in self.output_domains]) @@ -122,14 +122,14 @@ def run_sql(input, sql=self.sql.encode('utf-8'), size = 0 while chunk: size += 1 - cPickle.dump(chunk, stream, 2) + pickle.dump(chunk, stream, 2) chunk = cursor.fetchmany(batch) chunk = [tuple([convert(item) for item, convert in zip(row, unscrambles)]) for row in chunk] stream.seek(0) - def iterate(stream=stream, size=size, load=cPickle.load): - for k in xrange(size): + def iterate(stream=stream, size=size, load=pickle.load): + for k in range(size): for row in load(stream): yield row return iterate(stream, size) @@ -138,10 +138,10 @@ def iterate(stream=stream, size=size, load=cPickle.load): def __yaml__(self): yield ('sql', self.sql+'\n') if self.input_domains: - yield ('input', [unicode(domain) + yield ('input', [str(domain) for domain in self.input_domains]) if self.output_domains: - yield ('output', [unicode(domain) + yield ('output', [str(domain) for domain in self.output_domains]) yield ('batch', self.batch) @@ -231,7 +231,7 @@ def __init__(self, value_pipe): def __call__(self): def iterate(input, make_value=self.value_pipe()): if isinstance(input, list): - return map(make_value, input) + return list(map(make_value, input)) else: return (make_value(item) for item in input) return iterate @@ -272,7 +272,7 @@ def mix(input, make_parent_key=make_keys[0], make_kid_keys=make_keys[1:]): parent = input[0] kids = input[1:] - kids_range = range(len(kids)) + kids_range = list(range(len(kids))) tops = [0]*len(kids) output = [] for parent_row in parent: diff --git a/src/htsql/core/tr/translate.py b/src/htsql/core/tr/translate.py index eced04e..d92e1f0 100644 --- a/src/htsql/core/tr/translate.py +++ b/src/htsql/core/tr/translate.py @@ -21,8 +21,8 @@ def translate(syntax, environment=None, limit=None, offset=None, batch=None): - assert isinstance(syntax, (Syntax, Binding, unicode, str)) - if isinstance(syntax, (str, unicode)): + assert isinstance(syntax, (Syntax, Binding, str)) + if isinstance(syntax, str): syntax = parse(syntax) if not isinstance(syntax, Binding): binding = bind(syntax, environment=environment) @@ -59,9 +59,9 @@ def get_sql(pipe): if sqls: merged_sqls = [sqls[0]] for sql in sqls[1:]: - merged_sqls.append(u"\n".join(u" "+line if line else u"" + merged_sqls.append("\n".join(" "+line if line else "" for line in sql.splitlines())) - return u"\n\n".join(merged_sqls) + return "\n\n".join(merged_sqls) def safe_patch(segment, limit, offset): diff --git a/src/htsql/core/util.py b/src/htsql/core/util.py index aa48aea..f78bfb9 100644 --- a/src/htsql/core/util.py +++ b/src/htsql/core/util.py @@ -7,7 +7,7 @@ import sys import math import decimal -import urllib +import urllib.request, urllib.parse, urllib.error import pkgutil import datetime, time import collections @@ -199,7 +199,7 @@ def isfinite(value): """ Verifies that the given value is a finite number. """ - return (isinstance(value, (int, long)) or + return (isinstance(value, int) or (isinstance(value, float) and not math.isinf(value) and not math.isnan(value)) or (isinstance(value, decimal.Decimal) and value.is_finite())) @@ -218,7 +218,7 @@ def trim_doc(doc): `doc`: ``str`` or ``None`` A docstring. """ - assert isinstance(doc, maybe(oneof(str, unicode))) + assert isinstance(doc, maybe(oneof(str, str))) # Pass `None` through. if doc is None: @@ -258,13 +258,13 @@ def to_name(text): - preceded with an underscore if it starts with a digit; - an empty string is replaced with ``'_'``. """ - assert isinstance(text, (str, unicode)) + assert isinstance(text, str) if isinstance(text, str): text = text.decode('utf-8', 'replace') if not text: - text = u"_" + text = "_" text = unicodedata.normalize('NFC', text).lower() - text = re.sub(ur"(?u)^(?=\d)|\W", u"_", text) + text = re.sub(r"(?u)^(?=\d)|\W", "_", text) return text @@ -272,9 +272,9 @@ def urlquote(text, reserved=";/?:@&=+$,"): """ Replaces non-printable and reserved characters with ``%XX`` sequences. """ - assert isinstance(text, unicode) + assert isinstance(text, str) text = re.sub(r"[\x00-\x1F%%\x7F%s]" % reserved, - (lambda m: u"%%%02X" % ord(m.group())), + (lambda m: "%%%02X" % ord(m.group())), text) return text @@ -286,8 +286,8 @@ def to_literal(text): This function escapes all non-printable characters and wraps the text value in single quotes. """ - assert isinstance(text, unicode) - text = u"'%s'" % urlquote(text, "").replace(u"'", u"''") + assert isinstance(text, str) + text = "'%s'" % urlquote(text, "").replace("'", "''") return text @@ -308,8 +308,8 @@ def similar(model, sample): Use for error reporting to suggest alternatives for an unknown `model` identifier. """ - assert isinstance(model, unicode) - assert isinstance(sample, unicode) + assert isinstance(model, str) + assert isinstance(sample, str) # Skip empty strings. if not model or not sample: @@ -370,7 +370,7 @@ class TextBuffer(object): skip_regexp = re.compile(r"(?: \s+ | [#] [^\r\n]* )+", re.X|re.U) def __init__(self, text): - assert isinstance(text, (str, unicode)) + assert isinstance(text, str) # The input text. self.text = text # The head of the buffer. @@ -378,7 +378,7 @@ def __init__(self, text): # Advance over whitespace and comments. self.skip() - def __nonzero__(self): + def __bool__(self): return (self.index < len(self.text)) def reset(self): @@ -459,8 +459,8 @@ def fail(self, message): excerpt = excerpt.decode('utf-8', 'replace') index = len(excerpt[:index].decode('utf-8', 'replace')) # Extract the line around the head position. - start = excerpt.rfind(u"\n", 0, index)+1 - end = excerpt.find(u"\n", start) + start = excerpt.rfind("\n", 0, index)+1 + end = excerpt.find("\n", start) if end == -1: end = len(self.text) excerpt = excerpt[start:end].encode('utf-8') @@ -627,7 +627,7 @@ def __init__(self, iterable=None): self._value_by_key = {} # Initialize the mapping with elements from `iterable`. if isinstance(iterable, collections.Mapping): - iterable = iterable.iteritems() + iterable = iter(iterable.items()) if iterable is not None: for key, value in iterable: if key not in self._value_by_key: @@ -728,7 +728,7 @@ def clear(self): def update(self, iterable): if isinstance(iterable, collections.Mapping): - iterable = iterable.iteritems() + iterable = iter(iterable.items()) for key, value in iterable: if key not in self._value_by_key: self._keys.append(key) @@ -806,7 +806,7 @@ def clone_to(self, clone_type, **replacements): """ # Get the list of constructor arguments. We expect that for each # constructor argument, the object has an attribute with the same name. - init_code = self.__init__.im_func.func_code + init_code = self.__init__.__func__.__code__ # Fetch the names of regular arguments, but skip `self`. names = list(init_code.co_varnames[1:init_code.co_argcount]) # Check for * and ** arguments. We cannot properly support @@ -943,11 +943,11 @@ class Printable(object): def __unicode__(self): # Override in subclasses. - return u"-" + return "-" def __str__(self): # Reuse implementation of `__unicode__`. - return unicode(self).encode('utf-8') + return str(self).encode('utf-8') def __repr__(self): return "<%s %s>" % (self.__class__.__name__, self) @@ -987,7 +987,7 @@ class YAMLableDumper(yaml.Dumper): def represent_str(self, data): # Represent both `str` and `unicode` objects as YAML strings. # Use block style for multiline strings. - if isinstance(data, unicode): + if isinstance(data, str): data = data.encode('utf-8') tag = None style = None @@ -995,20 +995,20 @@ def represent_str(self, data): style = '|' try: data = data.decode('utf-8') - tag = u'tag:yaml.org,2002:str' + tag = 'tag:yaml.org,2002:str' except UnicodeDecodeError: data = data.encode('base64') - tag = u'tag:yaml.org,2002:binary' + tag = 'tag:yaml.org,2002:binary' style = '|' return self.represent_scalar(tag, data, style=style) def represent_yamlable(self, data): # Represent `YAMLable` objects. - tag = unicode('!'+data.__class__.__name__) + tag = str('!'+data.__class__.__name__) mapping = list(data.__yaml__()) # Use block style if any field value is a multiline string. flow_style = None - if any(isinstance(item, (str, unicode)) and '\n' in item + if any(isinstance(item, str) and '\n' in item for key, item in mapping): flow_style = False return self.represent_mapping(tag, mapping, flow_style=flow_style) @@ -1016,23 +1016,23 @@ def represent_yamlable(self, data): def generate_anchor(self, node): # Use the class name for anchor names. if not isinstance(self.last_anchor_id, dict): - self.last_anchor_id = { u'': 1 } - if node.tag.startswith(u'!'): + self.last_anchor_id = { '': 1 } + if node.tag.startswith('!'): text = node.tag[1:] else: - text = u'' + text = '' self.last_anchor_id.setdefault(text, 1) index = self.last_anchor_id[text] self.last_anchor_id[text] += 1 if text: - text += u'-%s' % index + text += '-%s' % index else: - text = unicode(index) + text = str(index) return text YAMLableDumper.add_representer(str, YAMLableDumper.represent_str) -YAMLableDumper.add_representer(unicode, YAMLableDumper.represent_str) +YAMLableDumper.add_representer(str, YAMLableDumper.represent_str) YAMLableDumper.add_multi_representer(YAMLable, YAMLableDumper.represent_yamlable) @@ -1162,7 +1162,7 @@ def parse(cls, value): # - a dictionary with the keys: # 'engine', 'database', 'username', 'password', 'host', 'port', # 'database', 'options'. - if not isinstance(value, (cls, str, unicode, dict)): + if not isinstance(value, (cls, str, dict)): raise ValueError("a connection URI is expected; got %r" % value) # Instances of `DB` are returned as is. @@ -1171,7 +1171,7 @@ def parse(cls, value): # We expect a connection URI to be a regular string, but we allow # Unicode strings too. - if isinstance(value, unicode): + if isinstance(value, str): value = value.encode('utf-8') # If a string is given, assume it is a connection URI and parse it. @@ -1191,23 +1191,23 @@ def parse(cls, value): # We assume that values are URI-quoted; unquote them here. # Also perform necessary type conversion. - engine = urllib.unquote(engine) + engine = urllib.parse.unquote(engine) if username is not None: - username = urllib.unquote(username) + username = urllib.parse.unquote(username) if password is not None: - password = urllib.unquote(password) + password = urllib.parse.unquote(password) if host is not None: - host = urllib.unquote(host) + host = urllib.parse.unquote(host) if port is not None: - port = urllib.unquote(port) + port = urllib.parse.unquote(port) try: port = int(port) except ValueError: raise ValueError("expected port to be an integer;" " got %r" % port) - database = urllib.unquote(database) + database = urllib.parse.unquote(database) if options is not None: - options = dict(map(urllib.unquote, item.split('=', 1)) + options = dict(list(map(urllib.parse.unquote, item.split('=', 1))) for item in options.split('&')) # If a dictionary is given, assume it is a dictionary with @@ -1230,28 +1230,28 @@ def parse(cls, value): options = value.get('options') # Sanity check on the values. - if isinstance(engine, unicode): + if isinstance(engine, str): engine = engine.encode('utf-8') if not isinstance(engine, str): raise ValueError("engine must be a string; got %r" % engine) - if isinstance(database, unicode): + if isinstance(database, str): database = database.encode('utf-8') if not isinstance(database, str): raise ValueError("database must be a string; got %r" % database) - if isinstance(username, unicode): + if isinstance(username, str): username = username.encode('utf-8') if not isinstance(username, maybe(str)): raise ValueError("username must be a string; got %r" % username) - if isinstance(password, unicode): + if isinstance(password, str): password = password.encode('utf-8') if not isinstance(password, maybe(str)): raise ValueError("password must be a string; got %r" % password) - if isinstance(host, unicode): + if isinstance(host, str): host = host.encode('utf-8') if not isinstance(host, maybe(str)): raise ValueError("host must be a string; got %r" % host) - if isinstance(port, (str, unicode)): + if isinstance(port, str): try: port = int(port) except ValueError: @@ -1278,18 +1278,18 @@ def __unicode__(self): if ((self.username is not None or self.password is not None) or (self.host is None and self.port is not None)): if self.username is not None: - chunks.append(urllib.quote(self.username, safe='')) + chunks.append(urllib.parse.quote(self.username, safe='')) if self.password is not None: chunks.append(':') - chunks.append(urllib.quote(self.password, safe='')) + chunks.append(urllib.parse.quote(self.password, safe='')) chunks.append('@') if self.host is not None: - chunks.append(urllib.quote(self.host, safe='')) + chunks.append(urllib.parse.quote(self.host, safe='')) if self.port is not None: chunks.append(':') chunks.append(str(self.port)) chunks.append('/') - chunks.append(urllib.quote(self.database)) + chunks.append(urllib.parse.quote(self.database)) if self.options: chunks.append('?') is_first = True @@ -1298,10 +1298,10 @@ def __unicode__(self): is_first = False else: chunks.append('&') - chunks.append(urllib.quote(key, safe='')) + chunks.append(urllib.parse.quote(key, safe='')) chunks.append('=') - chunks.append(urllib.quote(self.options[key])) - return u''.join(chunks) + chunks.append(urllib.parse.quote(self.options[key])) + return ''.join(chunks) # diff --git a/src/htsql/core/validator.py b/src/htsql/core/validator.py index 7cdb2b3..7462546 100644 --- a/src/htsql/core/validator.py +++ b/src/htsql/core/validator.py @@ -106,18 +106,18 @@ def __call__(self, value): raise ValueError("the null value is not permitted") # A byte or a Unicode string is expected. - if not isinstance(value, (str, unicode)): + if not isinstance(value, str): raise ValueError("a string value is expected; got %r" % value) # Byte strings must be UTF-8 encoded. if isinstance(value, str): try: value.decode('utf-8') - except UnicodeDecodeError, exc: + except UnicodeDecodeError as exc: raise ValueError("unable to decode %r: %s" % (value, exc)) # Translate Unicode strings to UTF-8 encoded byte strings. - if isinstance(value, unicode): + if isinstance(value, str): value = value.encode('utf-8') # Verify that the value does not contain the NUL character. @@ -168,20 +168,9 @@ def __call__(self, value): raise ValueError("the null value is not permitted") # A byte or a Unicode string is expected. - if not isinstance(value, (str, unicode)): + if not isinstance(value, str): raise ValueError("a string value is expected; got %r" % value) - # Byte strings must be UTF-8 encoded. - if isinstance(value, str): - try: - value.decode('utf-8') - except UnicodeDecodeError, exc: - raise ValueError("unable to decode %r: %s" % (value, exc)) - - # Translate Unicode strings to UTF-8 encoded byte strings. - if isinstance(value, unicode): - value = value.encode('utf-8') - # Check if the string matches the word pattern. if not self.regexp.match(value): raise ValueError("a string containing alphanumeric characters," @@ -220,16 +209,9 @@ def __call__(self, value): raise ValueError("the null value is not permitted") # A byte or a Unicode string is expected. - if not isinstance(value, (str, unicode)): + if not isinstance(value, str): raise ValueError("a string value is expected; got %r" % value) - # Byte strings must be UTF-8 encoded. - if isinstance(value, str): - try: - value = value.decode('utf-8') - except UnicodeDecodeError, exc: - raise ValueError("unable to decode %r: %s" % (value, exc)) - # Check if the string matches the name pattern. if not self.regexp.match(value): raise ValueError("a string containing alphanumeric characters" @@ -270,11 +252,11 @@ def __call__(self, value): raise ValueError("the null value is not permitted") # A byte or a Unicode string is expected. - if not isinstance(value, (str, unicode)): + if not isinstance(value, str): raise ValueError("a string value is expected; got %r" % value) # Translate Unicode strings to UTF-8 encoded byte strings. - if isinstance(value, unicode): + if isinstance(value, str): value = value.encode('utf-8') # Check if the value belongs to the specified set of choices. @@ -351,8 +333,8 @@ class IntVal(Validator): def __init__(self, min_bound=None, max_bound=None, is_nullable=False): # Sanity check on the arguments. - assert isinstance(min_bound, maybe(oneof(int, long))) - assert isinstance(max_bound, maybe(oneof(int, long))) + assert isinstance(min_bound, maybe(oneof(int, int))) + assert isinstance(max_bound, maybe(oneof(int, int))) assert isinstance(is_nullable, bool) self.min_bound = min_bound @@ -368,9 +350,9 @@ def __call__(self, value): raise ValueError("the null value is not permitted") # Convert string values; a non-numeric string triggers `ValueError`. - if isinstance(value, (str, unicode)): + if isinstance(value, str): value = int(value) - if not isinstance(value, (int, long)): + if not isinstance(value, int): raise ValueError("an integer value is required; got %r" % value) # Check the boundary conditions. @@ -382,7 +364,7 @@ def __call__(self, value): " got %s" % (self.max_bound, value)) # `value` is an integer or a long integer here. - assert isinstance(value, (int, long)) + assert isinstance(value, int) return value @@ -446,9 +428,9 @@ def __call__(self, value): raise ValueError("the null value is not permitted") # Convert string and integer values. - if isinstance(value, (str, unicode)): + if isinstance(value, str): value = float(value) - if isinstance(value, (int, long)): + if isinstance(value, int): value = float(value) if not isinstance(value, float): raise ValueError("a float value is required; got %r" % value) @@ -539,7 +521,7 @@ def __call__(self, value): raise ValueError("the null value is not permitted") # Translate Unicode strings to UTF-8 byte strings. - if isinstance(value, unicode): + if isinstance(value, str): value = value.encode('utf-8') # If the value is a string, parse it and extract the elements. @@ -610,7 +592,7 @@ def __call__(self, value): for idx, item in enumerate(value): try: item = self.item_validator(item) - except ValueError, exc: + except ValueError as exc: raise ValueError("invalid sequence item" " #%s (%s)" % (idx+1, exc)) items.append(item) @@ -685,7 +667,7 @@ def __call__(self, value): raise ValueError("the null value is not permitted") # Translate Unicode strings to UTF-8 encoded byte strings. - if isinstance(value, unicode): + if isinstance(value, str): value = value.encode('utf-8') # If the value is a string, parse it and extract the elements. @@ -789,7 +771,7 @@ def __call__(self, value): for key in sorted(value): try: validated_key = self.key_validator(key) - except ValueError, exc: + except ValueError as exc: raise ValueError("invalid mapping key (%s)" % exc) if validated_key in key_set: raise ValueError("duplicate mapping key %r" % key) @@ -797,7 +779,7 @@ def __call__(self, value): item = value[key] try: validated_item = self.item_validator(item) - except ValueError, exc: + except ValueError as exc: raise ValueError("invalid mapping item for key %r (%s)" % (key, item)) pairs.append((validated_key, validated_item)) @@ -827,7 +809,7 @@ def __call__(self, value): for validator in self.validators: try: return validator(value) - except ValueError, exc: + except ValueError as exc: messages.append(str(exc)) raise ValueError("; ".join(messages)) @@ -852,7 +834,7 @@ def __call__(self, value): else: raise ValueError("the null value is not permitted") - if isinstance(value, (str, unicode)): + if isinstance(value, str): validator = MapVal(WordVal(), AnyVal()) value = validator(value) @@ -922,7 +904,7 @@ def __call__(self, value): raise ValueError("the null value is not permitted") # Translate Unicode strings to UTF-8 encoded byte strings. - if isinstance(value, unicode): + if isinstance(value, str): value = value.encode('utf-8') # If the value is a string, parse it and extract the elements. diff --git a/src/htsql/core/wsgi.py b/src/htsql/core/wsgi.py index 0f1bc15..3223bf2 100644 --- a/src/htsql/core/wsgi.py +++ b/src/htsql/core/wsgi.py @@ -14,7 +14,7 @@ from .error import HTTPError from .cmd.command import UniversalCmd from .cmd.act import render -import urllib +import urllib.request, urllib.parse, urllib.error class WSGI(Utility): @@ -36,7 +36,7 @@ def request(self): # Extract an HTSQL request from `environ`. path_info = self.environ['PATH_INFO'] query_string = self.environ.get('QUERY_STRING') - uri = urllib.quote(path_info) + uri = urllib.parse.quote(path_info) if query_string: uri += '?'+query_string return uri @@ -53,7 +53,7 @@ def __call__(self): try: command = UniversalCmd(uri) status, headers, body = render(command, self.environ) - except HTTPError, exc: + except HTTPError as exc: return exc(self.environ, self.start_response) self.start_response(status, headers) return body diff --git a/src/htsql/ctl/extension.py b/src/htsql/ctl/extension.py index 19bcb96..842d3cf 100644 --- a/src/htsql/ctl/extension.py +++ b/src/htsql/ctl/extension.py @@ -67,7 +67,7 @@ def describe_extension(self): raise ScriptError("unknown extension %s" % self.addon) try: addon_class = addon_registry.load(self.addon) - except Exception, exc: + except Exception as exc: raise ScriptError("failed to load extension %s: %s" % (self.addon, exc)) hint = addon_class.get_hint() diff --git a/src/htsql/ctl/help.py b/src/htsql/ctl/help.py index 884b4b0..1b4afee 100644 --- a/src/htsql/ctl/help.py +++ b/src/htsql/ctl/help.py @@ -91,7 +91,7 @@ def describe_script(self): self.ctl.out() self.ctl.out("Available routines:") routines = set(routine_class - for routine_class in self.ctl.routine_by_name.values() + for routine_class in list(self.ctl.routine_by_name.values()) if routine_class.name) for routine_class in sorted(routines, key=(lambda c: c.name)): name = routine_class.name diff --git a/src/htsql/ctl/regress.py b/src/htsql/ctl/regress.py index 5f489fd..d984011 100644 --- a/src/htsql/ctl/regress.py +++ b/src/htsql/ctl/regress.py @@ -21,7 +21,7 @@ MapVal, ClassVal, AnyVal) from ..core.util import maybe, trim_doc, DB import traceback -import StringIO +import io import sys import os, os.path import shutil @@ -46,7 +46,7 @@ DO_SKIP = object() -class TermStringIO(StringIO.StringIO): +class TermStringIO(io.StringIO): """ A readable file-like object with an "echo". Whenever some content is read from it, the same content is echoed to the specified `output` stream. @@ -69,16 +69,16 @@ class TermStringIO(StringIO.StringIO): """ def __init__(self, buf, output): - StringIO.StringIO.__init__(self, buf) + io.StringIO.__init__(self, buf) self.output = output def read(self, n=-1): - data = StringIO.StringIO.read(self, n) + data = io.StringIO.read(self, n) self.output.write(data) return data def readline(self, length=None): - data = StringIO.StringIO.readline(self, length) + data = io.StringIO.readline(self, length) self.output.write(data) return data @@ -340,7 +340,7 @@ def __init__(self, routine, state, input, output): # the test case leaves the quiet mode, all the accumulated data # is dumped to the standard output stream. self.is_quiet = routine.quiet - self.quiet_buffer = StringIO.StringIO() + self.quiet_buffer = io.StringIO() def make_output(self, **attributes): # Generate a new test output record with the given attributes. @@ -1583,7 +1583,7 @@ def execute(self): # Run the routine; return the output # Prepare the standard streams and the script instance. - stdout = StringIO.StringIO() + stdout = io.StringIO() stderr = stdout stdin = TermStringIO(self.input.stdin, stdout) command_line = [self.routine.executable]+self.input.ctl @@ -1892,8 +1892,8 @@ def execute(self): old_stdin = sys.stdin old_stdout = sys.stdout old_stderr = sys.stderr - sys.stdin = StringIO.StringIO(self.input.stdin) - sys.stdout = StringIO.StringIO() + sys.stdin = io.StringIO(self.input.stdin) + sys.stdout = io.StringIO() sys.stderr = sys.stdout # Prepare the code. code = self.load() @@ -1901,7 +1901,7 @@ def execute(self): # Execute the code. exc_info = None try: - exec code in context + exec(code, context) except: exc_info = sys.exc_info() # Make new output record. @@ -2026,7 +2026,7 @@ def verify(self): from htsql.core.split_sql import split_sql try: app = HTSQL(self.input.connect) - except Exception, exc: + except Exception as exc: self.out_exception(sys.exc_info()) return self.failed("*** an exception occured while" " initializing an HTSQL application") @@ -2038,14 +2038,14 @@ def verify(self): # SQL statements. try: statements = list(split_sql(sql)) - except ValueError, exc: + except ValueError as exc: return self.failed("*** invalid SQL: %s" % exc) # Realize the connector and connect to the database. try: connection = connect(with_autocommit=self.input.autocommit) cursor = connection.cursor() - except Error, exc: + except Error as exc: return self.failed("*** failed to connect to the database:" "\n%s" % exc) @@ -2054,7 +2054,7 @@ def verify(self): try: # Execute the statement in the current connection. cursor.execute(statement) - except Error, exc: + except Error as exc: # Display the statement that caused a problem. for line in statement.splitlines(): self.out(line, indent=4) @@ -2072,7 +2072,7 @@ def verify(self): if not self.input.autocommit: try: connection.commit() - except Error, exc: + except Error as exc: if not self.input.ignore: return self.failed("*** failed to commit" " a transaction:\n%s" % exc) @@ -2082,7 +2082,7 @@ def verify(self): # of the `ignore` flag. try: connection.close() - except Error, exc: + except Error as exc: return self.failed("*** failed to close the connection:" "\n%s" % exc) @@ -2532,7 +2532,7 @@ def construct_yaml_map(self, node): key = self.construct_object(key_node, deep=True) try: hash(key) - except TypeError, exc: + except TypeError as exc: raise yaml.constructor.ConstructorError( "while constructing a mapping", node.start_mark, @@ -2560,7 +2560,7 @@ def construct_yaml_map(self, node): # If we can't find a suitable record class, it must be a regular # dictionary. if detected_record_class is None: - return dict(zip(keys, values)) + return dict(list(zip(keys, values))) # Check that the node does not contain any keys other than # the record fields. @@ -2584,7 +2584,7 @@ def construct_yaml_map(self, node): value = value_by_key[key] try: value = field.val(value) - except ValueError, exc: + except ValueError as exc: raise yaml.constructor.ConstructorError(None, None, "invalid field %r (%s)" % (key, exc), value_mark_by_key[key]) @@ -2601,7 +2601,7 @@ def construct_yaml_map(self, node): try: record = detected_record_class(self.routine, case_class, attributes, location) - except ValueError, exc: + except ValueError as exc: raise yaml.constructor.ConstructorError(None, None, "invalid test data (%s)" % exc, node.start_mark) @@ -2635,19 +2635,19 @@ def replace(match): # Register custom constructors for `!!str``, `!!map`` and ``!environ``. RegressYAMLLoader.add_constructor( - u'tag:yaml.org,2002:str', + 'tag:yaml.org,2002:str', RegressYAMLLoader.construct_yaml_str) RegressYAMLLoader.add_constructor( - u'tag:yaml.org,2002:map', + 'tag:yaml.org,2002:map', RegressYAMLLoader.construct_yaml_map) RegressYAMLLoader.add_constructor( - u'!environ', + '!environ', RegressYAMLLoader.construct_environ) # Register a resolver for ``!environ``. RegressYAMLLoader.add_implicit_resolver( - u'!environ', RegressYAMLLoader.environ_regexp, [u'$']) + '!environ', RegressYAMLLoader.environ_regexp, ['$']) class RegressYAMLDumper(BaseYAMLDumper): @@ -2728,10 +2728,10 @@ def represent_str(self, data): style = '|' try: data = data.decode('utf-8') - tag = u'tag:yaml.org,2002:str' + tag = 'tag:yaml.org,2002:str' except UnicodeDecodeError: data = data.encode('base64') - tag = u'tag:yaml.org,2002:binary' + tag = 'tag:yaml.org,2002:binary' style = '|' return self.represent_scalar(tag, data, style=style) @@ -2750,7 +2750,7 @@ def represent_record(self, data): continue mapping.append((name, value)) # Generate a mapping node. - return self.represent_mapping(u'tag:yaml.org,2002:map', mapping, + return self.represent_mapping('tag:yaml.org,2002:map', mapping, flow_style=False) @@ -2938,7 +2938,7 @@ def load_input(self, path): loader = RegressYAMLLoader(self, True, False, stream) try: input = loader.load() - except yaml.YAMLError, exc: + except yaml.YAMLError as exc: raise ScriptError("failed to load test input data: %s" % exc) return input @@ -2949,7 +2949,7 @@ def load_output(self, path): loader = RegressYAMLLoader(self, False, True, stream) try: input = loader.load() - except yaml.YAMLError, exc: + except yaml.YAMLError as exc: raise ScriptError("failed to load test output data: %s" % exc) return input @@ -2964,7 +2964,7 @@ def save_output(self, path, output): dumper = RegressYAMLDumper(self, False, True, stream) try: dumper.dump(output) - except yaml.YAMLError, exc: + except yaml.YAMLError as exc: raise ScriptError("failed to write test output data: %s" % exc) diff --git a/src/htsql/ctl/request.py b/src/htsql/ctl/request.py index 672d626..4091b1c 100644 --- a/src/htsql/ctl/request.py +++ b/src/htsql/ctl/request.py @@ -12,8 +12,8 @@ import sys import os.path import wsgiref.util -import urllib -import StringIO +import urllib.request, urllib.parse, urllib.error +import io import mimetypes import re import getpass @@ -25,13 +25,13 @@ class ConfigYAMLLoader(BaseYAMLLoader): - name_pattern = ur""" + name_pattern = r""" ^ [a-zA-Z_-][0-9a-zA-Z_-]* $ """ name_regexp = re.compile(name_pattern, re.X) - dotted_name_pattern = ur""" + dotted_name_pattern = r""" ^ [a-zA-Z_-][0-9a-zA-Z_-]* (?: \. [a-zA-Z_-][0-9a-zA-Z_-]* )* @@ -49,30 +49,30 @@ def load(self): def construct_document(self, node): document_node = node if (not (isinstance(document_node, yaml.ScalarNode) and - document_node.tag == u'tag:yaml.org,2002:null') and + document_node.tag == 'tag:yaml.org,2002:null') and not (isinstance(document_node, yaml.MappingNode) and - document_node.tag == u'tag:yaml.org,2002:map')): + document_node.tag == 'tag:yaml.org,2002:map')): raise yaml.constructor.ConstructorError(None, None, "invalid structure of configuration file", document_node.start_mark) if isinstance(document_node, yaml.MappingNode): for name_node, addon_node in document_node.value: if not (isinstance(name_node, yaml.ScalarNode) and - name_node.tag == u'tag:yaml.org,2002:str' and + name_node.tag == 'tag:yaml.org,2002:str' and self.dotted_name_regexp.match(name_node.value)): raise yaml.constructor.ConstructorError(None, None, "invalid addon name", name_node.start_mark) if (not (isinstance(addon_node, yaml.ScalarNode) and - addon_node.tag == u'tag:yaml.org,2002:null') and + addon_node.tag == 'tag:yaml.org,2002:null') and not (isinstance(addon_node, yaml.MappingNode) and - addon_node.tag == u'tag:yaml.org,2002:map')): + addon_node.tag == 'tag:yaml.org,2002:map')): raise yaml.constructor.ConstructorError(None, None, "invalid addon configuration", addon_node.start_mark) if isinstance(addon_node, yaml.MappingNode): for attribute_node, value_node in addon_node.value: if not (isinstance(attribute_node, yaml.ScalarNode) and attribute_node.tag - == u'tag:yaml.org,2002:str' and + == 'tag:yaml.org,2002:str' and self.name_regexp.match(attribute_node.value)): raise yaml.constructor.ConstructorError(None, None, "invalid parameter name", @@ -98,7 +98,7 @@ def construct_include(self, node): filename = os.path.join(os.path.dirname(basename), filename) try: stream = open(filename, 'rb') - except IOError, exc: + except IOError as exc: raise yaml.constructor.ConstructorError(None, None, "unable to open a file: %s" % exc, node.start_mark) loader = self.__class__(stream) @@ -107,7 +107,7 @@ def construct_include(self, node): return super(ConfigYAMLLoader, self).construct_object(node) -ConfigYAMLLoader.add_constructor(u'!include', +ConfigYAMLLoader.add_constructor('!include', ConfigYAMLLoader.construct_include) @@ -174,7 +174,7 @@ def prepare(cls, method, query, remote_user=None, else: path_info = query query_string = '' - path_info = urllib.unquote(path_info) + path_info = urllib.parse.unquote(path_info) environ['PATH_INFO'] = path_info environ['QUERY_STRING'] = query_string @@ -195,7 +195,7 @@ def prepare(cls, method, query, remote_user=None, content_body = content_body.read() environ['CONTENT_TYPE'] = content_type environ['CONTENT_LENGTH'] = str(len(content_body)) - environ['wsgi.input'] = StringIO.StringIO(content_body) + environ['wsgi.input'] = io.StringIO(content_body) # Transfer HTTP headers to the WSGI `environ`. if extra_headers is not None: @@ -230,7 +230,7 @@ def start_response(status, headers, exc_info=None): response.set(status=status, headers=headers) # Note that we don't expect the application to use the returned # stream object, so we don't keep it. - return StringIO.StringIO() + return io.StringIO() # Copy the `environ` dictionary in case the application modifies it. # TODO: that is not enough to make `execute()` truly re-entrant: for @@ -364,7 +364,7 @@ def run(self): loader = ConfigYAMLLoader(stream) try: config_extension = loader.load() - except yaml.YAMLError, exc: + except yaml.YAMLError as exc: raise ScriptError("failed to load application configuration:" " %s" % exc) if config_extension is not None: @@ -377,7 +377,7 @@ def run(self): loader = ConfigYAMLLoader(stream) try: default_extension = loader.load() - except yaml.YAMLError, exc: + except yaml.YAMLError as exc: raise ScriptError("failed to load default configuration: %s" % exc) if default_extension is not None: @@ -387,7 +387,7 @@ def run(self): from htsql import HTSQL try: app = HTSQL(*parameters) - except ImportError, exc: + except ImportError as exc: raise ScriptError("failed to construct application: %s" % exc) # Run the routine-specific code. diff --git a/src/htsql/ctl/script.py b/src/htsql/ctl/script.py index ad135ae..222cdd3 100644 --- a/src/htsql/ctl/script.py +++ b/src/htsql/ctl/script.py @@ -212,7 +212,7 @@ def main(self, argv): # Execute the routine. return routine.run() - except (ScriptError, IOError, KeyboardInterrupt), exc: + except (ScriptError, IOError, KeyboardInterrupt) as exc: # Regular exceptions are passed through and produce a traceback. # However for a selected list of exceptions, we want to omit # the traceback and just show the error message. These exceptions @@ -508,7 +508,7 @@ def make_argument_attributes(self, routine_class, values): else: try: value = argument.validator(value) - except ValueError, exc: + except ValueError as exc: raise ScriptError("invalid parameter %r: %s" % (argument.attribute, exc)) attributes[argument.attribute] = value @@ -547,7 +547,7 @@ def make_option_attributes(self, routine_class, option_values): if value != '-': try: value = option.validator(value) - except ValueError, exc: + except ValueError as exc: raise ScriptError("invalid parameter %r: %s" % (option.attribute, exc)) else: diff --git a/src/htsql/ctl/server.py b/src/htsql/ctl/server.py index 621bddb..76e1b32 100644 --- a/src/htsql/ctl/server.py +++ b/src/htsql/ctl/server.py @@ -14,12 +14,12 @@ from .option import HostOption, PortOption, QuietOption from .request import DBRoutine import socket -import SocketServer +import socketserver import wsgiref.simple_server import binascii -class HTSQLServer(SocketServer.ThreadingMixIn, +class HTSQLServer(socketserver.ThreadingMixIn, wsgiref.simple_server.WSGIServer, object): # We override `WSGIServer` to pass a `ServerRoutine` object to the # constructor. The routine is used to get the server address diff --git a/src/htsql/ctl/shell.py b/src/htsql/ctl/shell.py index 3d88991..277e8df 100644 --- a/src/htsql/ctl/shell.py +++ b/src/htsql/ctl/shell.py @@ -19,7 +19,7 @@ from ..core.classify import classify, normalize, relabel, localize from ..core.entity import UniqueKeyEntity, ForeignKeyEntity import traceback -import StringIO +import io import mimetypes import sys import os, os.path @@ -418,7 +418,7 @@ def label(self, name): return None return self.names_by_node[self.nodes[-1]].get(name) - def __nonzero__(self): + def __bool__(self): return bool(self.nodes) def clone(self): @@ -615,14 +615,14 @@ def dump(self, response): if (self.state.with_pager and (length >= max_lines or width >= max_columns)): # Pipe the response to the pager. - stream = StringIO.StringIO() + stream = io.StringIO() response.dump(stream, self.state.with_headers) output = stream.getvalue() process = subprocess.Popen(self.routine.pager.split(), stdin=subprocess.PIPE) try: process.communicate(output) - except IOError, exc: + except IOError as exc: self.ctl.out(exc) else: # Dump the response. @@ -1305,7 +1305,7 @@ def shutdown_interactive(self): directory = os.path.dirname(path) if not os.path.exists(directory): try: - os.mkdir(directory, 0700) + os.mkdir(directory, 0o700) except OSError: return readline.write_history_file(path) @@ -1324,7 +1324,7 @@ def loop_interactive(self): database = os.path.splitext(database)[0] prompt = "%s$ " % database try: - line = raw_input(prompt) + line = input(prompt) except EOFError: self.ctl.out() return True diff --git a/src/htsql/tweak/csrf/wsgi.py b/src/htsql/tweak/csrf/wsgi.py index 1518b9b..7cd30a6 100644 --- a/src/htsql/tweak/csrf/wsgi.py +++ b/src/htsql/tweak/csrf/wsgi.py @@ -7,7 +7,7 @@ from ...core.adapter import rank from ...core.wsgi import WSGI from ...core.fmt.html import Template -import Cookie +import http.cookies import os import binascii @@ -21,7 +21,7 @@ class CSRFWSGI(WSGI): def __call__(self): token = None if 'HTTP_COOKIE' in self.environ: - cookie = Cookie.SimpleCookie(self.environ['HTTP_COOKIE']) + cookie = http.cookies.SimpleCookie(self.environ['HTTP_COOKIE']) if 'htsql-csrf-token' in cookie: token = cookie['htsql-csrf-token'].value secret = None @@ -44,8 +44,8 @@ def __call__(self): path = self.environ.get('SCRIPT_NAME', '') if not path.endswith('/'): path += '/' - morsel = Cookie.Morsel() - morsel.set('htsql-csrf-token', token, Cookie._quote(token)) + morsel = http.cookies.Morsel() + morsel.set('htsql-csrf-token', token, http.cookies._quote(token)) morsel['path'] = path cookie = morsel.OutputString() # FIXME: avoid state changes in the adapter. diff --git a/src/htsql/tweak/django/introspect.py b/src/htsql/tweak/django/introspect.py index 9dc6a9f..0ddc1ed 100644 --- a/src/htsql/tweak/django/introspect.py +++ b/src/htsql/tweak/django/introspect.py @@ -32,7 +32,7 @@ def __call__(self): model._meta.auto_created not in seen_models): continue all_models.append(model) - schema = catalog.add_schema(u"") + schema = catalog.add_schema("") relations = [] table_by_model = {} column_by_field = {} diff --git a/src/htsql/tweak/etl/cmd/clone.py b/src/htsql/tweak/etl/cmd/clone.py index bf3ab35..1061458 100644 --- a/src/htsql/tweak/etl/cmd/clone.py +++ b/src/htsql/tweak/etl/cmd/clone.py @@ -167,7 +167,7 @@ def __call__(self): row = execute_clone(row, key) key = execute_insert(row) row = resolve_identity(key) - except Error, error: + except Error as error: if extract_node.is_list: message = "While cloning record #%s" % (idx+1) else: diff --git a/src/htsql/tweak/etl/cmd/command.py b/src/htsql/tweak/etl/cmd/command.py index 9b5daaf..73ee9fd 100644 --- a/src/htsql/tweak/etl/cmd/command.py +++ b/src/htsql/tweak/etl/cmd/command.py @@ -50,7 +50,7 @@ def __init__(self, table): class DoCmd(Command): def __init__(self, blocks): - assert isinstance(blocks, listof(tupleof(maybe(unicode), Command))) + assert isinstance(blocks, listof(tupleof(maybe(str), Command))) self.blocks = blocks @@ -69,7 +69,7 @@ def __init__(self, tests, values, else_value=None): class ForCmd(Command): def __init__(self, name, iterator, body): - assert isinstance(name, unicode) + assert isinstance(name, str) assert isinstance(iterator, Command) assert isinstance(body, Command) self.name = name diff --git a/src/htsql/tweak/etl/cmd/copy.py b/src/htsql/tweak/etl/cmd/copy.py index a3c9388..981603d 100644 --- a/src/htsql/tweak/etl/cmd/copy.py +++ b/src/htsql/tweak/etl/cmd/copy.py @@ -28,10 +28,10 @@ def __init__(self, table, columns): self.dumps = [column.domain.dump for column in columns] self.stream = tempfile.TemporaryFile() - def __call__(self, row, unicode=unicode): + def __call__(self, row, str=str): self.stream.write( "\t".join([ - unicode(item).encode('utf-8') + str(item).encode('utf-8') .replace('\\', '\\\\') .replace('\n', '\\n') .replace('\r', '\\r') @@ -96,7 +96,7 @@ def __call__(self): collect_copy( extract_table( extract_node(record))) - except Error, exc: + except Error as exc: if extract_node.is_list: message = "While copying record #%s" % (idx+1) else: @@ -108,7 +108,7 @@ def __call__(self): extract_table = None try: collect_copy.copy() - except Error, exc: + except Error as exc: exc.wrap("While copying a batch of records", None) raise meta = decorate(VoidBinding()) diff --git a/src/htsql/tweak/etl/cmd/delete.py b/src/htsql/tweak/etl/cmd/delete.py index 68a7c02..5eee671 100644 --- a/src/htsql/tweak/etl/cmd/delete.py +++ b/src/htsql/tweak/etl/cmd/delete.py @@ -25,7 +25,7 @@ class ExecuteDeletePipe(object): def __init__(self, table, key_columns, sql): assert isinstance(table, TableEntity) assert isinstance(key_columns, listof(ColumnEntity)) - assert isinstance(sql, unicode) + assert isinstance(sql, str) self.table = table self.key_columns = key_columns self.sql = sql @@ -95,7 +95,7 @@ def __call__(self): id_value, row = extract_node(record) key = resolve_key(id_value) execute_delete(key) - except Error, error: + except Error as error: if extract_node.is_list: message = "While deleting record #%s" % (idx+1) else: diff --git a/src/htsql/tweak/etl/cmd/insert.py b/src/htsql/tweak/etl/cmd/insert.py index 6c6f85f..01b9a5f 100644 --- a/src/htsql/tweak/etl/cmd/insert.py +++ b/src/htsql/tweak/etl/cmd/insert.py @@ -180,7 +180,7 @@ def __call__(self, row): except ValueError: message = "Failed to adapt value of %s to %s" \ % (self.name, self.to_domain) - quote = unicode(Value(self.from_domain, item)) + quote = str(Value(self.from_domain, item)) raise Error(message, quote) @@ -386,7 +386,7 @@ def __init__(self, table, input_columns, output_columns, sql): assert isinstance(table, TableEntity) assert isinstance(input_columns, listof(ColumnEntity)) assert isinstance(output_columns, listof(ColumnEntity)) - assert isinstance(sql, unicode) + assert isinstance(sql, str) self.table = table self.input_columns = input_columns self.output_columns = output_columns @@ -535,9 +535,9 @@ def __call__(self, value): if len(data) != 1: quote = None if self.name: - quote = u"%s[%s]" % (self.name, self.domain.dump(value)) + quote = "%s[%s]" % (self.name, self.domain.dump(value)) else: - quote = u"[%s]" % self.domain.dump(value) + quote = "[%s]" % self.domain.dump(value) raise Error("Unable to resolve a link", quote) return data[0] @@ -620,9 +620,9 @@ def __call__(self, value): except KeyError: quote = None if self.name: - quote = u"%s[%s]" % (self.name, self.domain.dump(value)) + quote = "%s[%s]" % (self.name, self.domain.dump(value)) else: - quote = u"[%s]" % self.domain.dump(value) + quote = "[%s]" % self.domain.dump(value) raise Error("Unable to resolve a link", quote) @@ -692,7 +692,7 @@ def __call__(self): execute_insert( extract_table( extract_node(record)))) - except Error, exc: + except Error as exc: if extract_node.is_list: message = "While inserting record #%s" % (idx+1) else: diff --git a/src/htsql/tweak/etl/cmd/merge.py b/src/htsql/tweak/etl/cmd/merge.py index 533a7af..feaae71 100644 --- a/src/htsql/tweak/etl/cmd/merge.py +++ b/src/htsql/tweak/etl/cmd/merge.py @@ -106,9 +106,9 @@ def __call__(self, value): if self.with_error: quote = None if self.name: - quote = u"%s[%s]" % (self.name, self.domain.dump(value)) + quote = "%s[%s]" % (self.name, self.domain.dump(value)) else: - quote = u"[%s]" % self.domain.dump(value) + quote = "[%s]" % self.domain.dump(value) raise Error("Unable to find an entity", quote) return None @@ -204,7 +204,7 @@ def __init__(self, table, input_columns, key_columns, assert isinstance(input_columns, listof(ColumnEntity)) assert isinstance(key_columns, listof(ColumnEntity)) assert isinstance(output_columns, listof(ColumnEntity)) - assert isinstance(sql, unicode) + assert isinstance(sql, str) self.table = table self.input_columns = input_columns self.key_columns = key_columns @@ -311,7 +311,7 @@ def __call__(self): row = extract_table(row) key = execute_insert(row) row = resolve_identity(key) - except Error, exc: + except Error as exc: if extract_node.is_list: message = "While merging record #%s" % (idx+1) else: diff --git a/src/htsql/tweak/etl/cmd/update.py b/src/htsql/tweak/etl/cmd/update.py index 2722f7f..1136a94 100644 --- a/src/htsql/tweak/etl/cmd/update.py +++ b/src/htsql/tweak/etl/cmd/update.py @@ -49,7 +49,7 @@ def __call__(self): row = extract_table(row) key = execute_update(key, row) row = resolve_identity(key) - except Error, error: + except Error as error: if extract_node.is_list: message = "While updating record #%s" % (idx+1) else: diff --git a/src/htsql/tweak/etl/cmd/with_.py b/src/htsql/tweak/etl/cmd/with_.py index 689ada8..2b7ab0f 100644 --- a/src/htsql/tweak/etl/cmd/with_.py +++ b/src/htsql/tweak/etl/cmd/with_.py @@ -31,7 +31,7 @@ def __call__(self): if isinstance(input.data, dict): for key, value in sorted(input.data.items()): try: - if not isinstance(key, unicode): + if not isinstance(key, str): raise TypeError name = to_name(key) value = Embed.__invoke__(value) diff --git a/src/htsql/tweak/etl/tr/dump.py b/src/htsql/tweak/etl/tr/dump.py index 2702da1..00fc349 100644 --- a/src/htsql/tweak/etl/tr/dump.py +++ b/src/htsql/tweak/etl/tr/dump.py @@ -43,36 +43,36 @@ def dump_insert(self): table=self.table.name) def dump_columns(self): - self.write(u" (") + self.write(" (") for idx, column in enumerate(self.columns): self.format("{column:name}", column=column.name) if idx < len(self.columns)-1: - self.write(u", ") - self.write(u")") + self.write(", ") + self.write(")") def dump_no_columns(self): pass def dump_values(self): self.newline() - self.write(u"VALUES (") + self.write("VALUES (") for idx, column in enumerate(self.columns): self.format("{index:placeholder}", index=None) if idx < len(self.columns)-1: - self.write(u", ") - self.write(u")") + self.write(", ") + self.write(")") def dump_no_values(self): self.newline() - self.write(u"DEFAULT VALUES") + self.write("DEFAULT VALUES") def dump_returning(self): self.newline() - self.write(u"RETURNING ") + self.write("RETURNING ") for idx, column in enumerate(self.returning_columns): self.format("{column:name}", column=column.name) if idx < len(self.returning_columns)-1: - self.write(u", ") + self.write(", ") class SerializeUpdate(Utility, DumpBase): @@ -110,7 +110,7 @@ def dump_update(self): def dump_columns(self): self.newline() - self.write(u"SET ") + self.write("SET ") self.indent() for idx, column in enumerate(self.columns): if idx > 0: @@ -118,25 +118,25 @@ def dump_columns(self): self.format("{column:name} = {index:placeholder}", column=column.name, index=None) if idx < len(self.columns)-1: - self.write(u",") + self.write(",") self.dedent() def dump_keys(self): self.newline() - self.write(u"WHERE ") + self.write("WHERE ") for idx, column in enumerate(self.key_columns): if idx > 0: - self.write(u" AND ") + self.write(" AND ") self.format("{column:name} = {index:placeholder}", column=column.name, index=None) def dump_returning(self): self.newline() - self.write(u"RETURNING ") + self.write("RETURNING ") for idx, column in enumerate(self.returning_columns): self.format("{column:name}", column=column.name) if idx < len(self.returning_columns)-1: - self.write(u", ") + self.write(", ") class SerializeDelete(Utility, DumpBase): @@ -166,10 +166,10 @@ def dump_delete(self): def dump_keys(self): self.newline() - self.write(u"WHERE ") + self.write("WHERE ") for idx, column in enumerate(self.key_columns): if idx > 0: - self.write(u" AND ") + self.write(" AND ") self.format("{column:name} = {index:placeholder}", column=column.name, index=None) diff --git a/src/htsql/tweak/filedb/connect.py b/src/htsql/tweak/filedb/connect.py index 308a164..a570fa1 100644 --- a/src/htsql/tweak/filedb/connect.py +++ b/src/htsql/tweak/filedb/connect.py @@ -80,7 +80,7 @@ def __call__(self): """, (table_name,)+meta) try: stream = open(source_file, mode="rU") - except IOError, exc: + except IOError as exc: raise Error("Failed to open file", source_file) reader = csv.reader(stream) try: @@ -99,7 +99,7 @@ def __call__(self): if name: name = to_name(name) if not name or name in column_names or re.match(r"^_\d+$", name): - name = u"_%s" % (idx+1) + name = "_%s" % (idx+1) column_names.append(name) records = [] for row in reader: diff --git a/src/htsql/tweak/inet/domain.py b/src/htsql/tweak/inet/domain.py index 5900cdb..f36f22c 100644 --- a/src/htsql/tweak/inet/domain.py +++ b/src/htsql/tweak/inet/domain.py @@ -13,7 +13,7 @@ class INetDomain(Domain): family = 'inet' def parse(self, data): - assert isinstance(data, maybe(unicode)) + assert isinstance(data, maybe(str)) if data is None: return None data = data.encode('utf-8') @@ -24,7 +24,7 @@ def parse(self, data): return data.decode('utf-8') def dump(self, value): - assert isinstance(value, maybe(oneof(str, unicode))) - return unicode(value) + assert isinstance(value, maybe(oneof(str, str))) + return str(value) diff --git a/src/htsql/tweak/meta/slave/connect.py b/src/htsql/tweak/meta/slave/connect.py index 792d27d..28f16a0 100644 --- a/src/htsql/tweak/meta/slave/connect.py +++ b/src/htsql/tweak/meta/slave/connect.py @@ -144,7 +144,7 @@ def build_data(self): VALUES (?, ?, ?, ?) """, [table_name, name, kind, sort]) if isinstance(arc, ColumnArc): - domain = unicode(arc.column.domain.__class__) + domain = str(arc.column.domain.__class__) is_mandatory = (not arc.column.is_nullable) cursor.execute(""" INSERT INTO "column" (table_name, name, diff --git a/src/htsql/tweak/override/classify.py b/src/htsql/tweak/override/classify.py index 9d15767..bc32b5f 100644 --- a/src/htsql/tweak/override/classify.py +++ b/src/htsql/tweak/override/classify.py @@ -51,7 +51,7 @@ def __init__(self): parameters = list(parameters) arity = len(parameters) signature = (field_name, arity) - name = u"%s.%s" % (class_name, field_name) + name = "%s.%s" % (class_name, field_name) if (class_name, None) not in self.node_by_signature: addon.unused_pattern_cache.add(name.encode('utf-8')) continue @@ -195,7 +195,7 @@ def __call__(self): for idx, (name, parameters) \ in enumerate(addon.field_orders[class_name, None]): if name not in names or parameters is not None: - name = u"%s.%s" % (class_name, name) + name = "%s.%s" % (class_name, name) addon.unused_pattern_cache.add(name.encode('utf-8')) else: orders[name] = idx diff --git a/src/htsql/tweak/override/pattern.py b/src/htsql/tweak/override/pattern.py index 7d70afa..a9543e9 100644 --- a/src/htsql/tweak/override/pattern.py +++ b/src/htsql/tweak/override/pattern.py @@ -30,7 +30,7 @@ def matches(entity, pattern): assert isinstance(entity, maybe(NamedEntity)) - assert isinstance(pattern, maybe(unicode)) + assert isinstance(pattern, maybe(str)) if entity is None: return (pattern is None) if pattern is None: @@ -45,14 +45,14 @@ def __unicode__(self): raise NotImplementedError() def __str__(self): - return unicode(self).encode('utf-8') + return str(self).encode('utf-8') class TablePattern(Pattern): def __init__(self, schema_pattern, table_pattern): - assert isinstance(schema_pattern, maybe(unicode)) - assert isinstance(table_pattern, unicode) + assert isinstance(schema_pattern, maybe(str)) + assert isinstance(table_pattern, str) self.schema_pattern = schema_pattern self.table_pattern = table_pattern @@ -65,16 +65,16 @@ def matches(self, entity): def __unicode__(self): if self.schema_pattern is not None: - return u"%s.%s" % (self.schema_pattern, self.table_pattern) + return "%s.%s" % (self.schema_pattern, self.table_pattern) return self.table_pattern class ColumnPattern(Pattern): def __init__(self, schema_pattern, table_pattern, column_pattern): - assert isinstance(schema_pattern, maybe(unicode)) - assert isinstance(table_pattern, maybe(unicode)) - assert isinstance(column_pattern, unicode) + assert isinstance(schema_pattern, maybe(str)) + assert isinstance(table_pattern, maybe(str)) + assert isinstance(column_pattern, str) self.schema_pattern = schema_pattern self.table_pattern = table_pattern self.column_pattern = column_pattern @@ -97,16 +97,16 @@ def __unicode__(self): if self.table_pattern is not None: chunks.append(self.table_pattern) chunks.append(self.column_pattern) - return u".".join(chunks) + return ".".join(chunks) class UniqueKeyPattern(Pattern): def __init__(self, schema_pattern, table_pattern, column_patterns, is_primary, is_partial): - assert isinstance(schema_pattern, maybe(unicode)) - assert isinstance(table_pattern, unicode) - assert isinstance(column_patterns, listof(unicode)) + assert isinstance(schema_pattern, maybe(str)) + assert isinstance(table_pattern, str) + assert isinstance(column_patterns, listof(str)) assert len(column_patterns) > 0 assert isinstance(is_primary, bool) assert isinstance(is_partial, bool) @@ -143,14 +143,14 @@ def __unicode__(self): chunks = [] if self.schema_pattern is not None: chunks.append(self.schema_pattern) - chunks.append(u".") + chunks.append(".") chunks.append(self.table_pattern) - chunks.append(u"(%s)" % ",".join(self.column_patterns)) + chunks.append("(%s)" % ",".join(self.column_patterns)) if self.is_primary: - chunks.append(u"!") + chunks.append("!") if self.is_partial: - chunks.append(u"?") - return u"".join(chunks) + chunks.append("?") + return "".join(chunks) class ForeignKeyPattern(Pattern): @@ -158,13 +158,13 @@ class ForeignKeyPattern(Pattern): def __init__(self, schema_pattern, table_pattern, column_patterns, target_schema_pattern, target_table_pattern, target_column_patterns, is_partial): - assert isinstance(schema_pattern, maybe(unicode)) - assert isinstance(table_pattern, unicode) - assert isinstance(column_patterns, listof(unicode)) + assert isinstance(schema_pattern, maybe(str)) + assert isinstance(table_pattern, str) + assert isinstance(column_patterns, listof(str)) assert len(column_patterns) > 0 - assert isinstance(target_schema_pattern, maybe(unicode)) - assert isinstance(target_table_pattern, unicode) - assert isinstance(target_column_patterns, maybe(listof(unicode))) + assert isinstance(target_schema_pattern, maybe(str)) + assert isinstance(target_table_pattern, str) + assert isinstance(target_column_patterns, maybe(listof(str))) assert (target_column_patterns is None or len(target_column_patterns) == len(column_patterns)) assert isinstance(is_partial, bool) @@ -231,19 +231,19 @@ def __unicode__(self): chunks = [] if self.schema_pattern is not None: chunks.append(self.schema_pattern) - chunks.append(u".") + chunks.append(".") chunks.append(self.table_pattern) - chunks.append(u"(%s)" % u",".join(self.column_patterns)) + chunks.append("(%s)" % ",".join(self.column_patterns)) if self.is_partial: chunks.append("?") chunks.append(" -> ") if self.target_schema_pattern is not None: chunks.append(self.target_schema_pattern) - chunks.append(u".") + chunks.append(".") chunks.append(self.target_table_pattern) if self.target_column_patterns is not None: - chunks.append(u"(%s)" % u",".join(self.target_column_patterns)) - return u"".join(chunks) + chunks.append("(%s)" % ",".join(self.target_column_patterns)) + return "".join(chunks) class ArcPattern(Pattern): @@ -262,7 +262,7 @@ class ColumnArcPattern(ArcPattern): is_column = True def __init__(self, column_pattern): - assert isinstance(column_pattern, unicode) + assert isinstance(column_pattern, str) self.column_pattern = column_pattern def extract(self, node, parameters): @@ -291,8 +291,8 @@ class TableArcPattern(ArcPattern): is_table = True def __init__(self, schema_pattern, table_pattern): - assert isinstance(schema_pattern, maybe(unicode)) - assert isinstance(table_pattern, unicode) + assert isinstance(schema_pattern, maybe(str)) + assert isinstance(table_pattern, str) self.schema_pattern = schema_pattern self.table_pattern = table_pattern @@ -319,7 +319,7 @@ def extract(self, node, parameters): def __unicode__(self): if self.schema_pattern is not None: - return u"%s.%s" % (self.schema_pattern, self.schema_pattern) + return "%s.%s" % (self.schema_pattern, self.schema_pattern) return self.table_pattern @@ -328,13 +328,13 @@ class JoinPattern(Pattern): def __init__(self, schema_pattern, table_pattern, column_patterns, target_schema_pattern, target_table_pattern, target_column_patterns): - assert isinstance(schema_pattern, maybe(unicode)) - assert isinstance(table_pattern, unicode) - assert isinstance(column_patterns, maybe(listof(unicode))) + assert isinstance(schema_pattern, maybe(str)) + assert isinstance(table_pattern, str) + assert isinstance(column_patterns, maybe(listof(str))) assert column_patterns is None or len(column_patterns) > 0 - assert isinstance(target_schema_pattern, maybe(unicode)) - assert isinstance(target_table_pattern, unicode) - assert isinstance(target_column_patterns, maybe(listof(unicode))) + assert isinstance(target_schema_pattern, maybe(str)) + assert isinstance(target_table_pattern, str) + assert isinstance(target_column_patterns, maybe(listof(str))) assert (target_column_patterns is None or len(target_column_patterns) > 0) assert (column_patterns is None or target_column_patterns is None or @@ -388,18 +388,18 @@ def __unicode__(self): chunks = [] if self.schema_pattern is not None: chunks.append(self.schema_pattern) - chunks.append(u".") + chunks.append(".") chunks.append(self.table_pattern) if self.column_patterns is not None: - chunks.append(u"(%s)" % u",".join(self.column_patterns)) + chunks.append("(%s)" % ",".join(self.column_patterns)) chunks.append(" -> ") if self.target_schema_pattern is not None: chunks.append(self.target_schema_pattern) - chunks.append(u".") + chunks.append(".") chunks.append(self.target_table_pattern) if self.target_column_patterns is not None: - chunks.append(u"(%s)" % u",".join(self.target_column_patterns)) - return u"".join(chunks) + chunks.append("(%s)" % ",".join(self.target_column_patterns)) + return "".join(chunks) class ChainArcPattern(ArcPattern): @@ -428,7 +428,7 @@ def extract(self, node, parameters): return ChainArc(table, joins) def __unicode__(self): - return u", ".join(unicode(pattern) for pattern in self.join_patterns) + return ", ".join(str(pattern) for pattern in self.join_patterns) class SyntaxArcPattern(ArcPattern): @@ -436,16 +436,16 @@ class SyntaxArcPattern(ArcPattern): is_syntax = True def __init__(self, syntax): - assert isinstance(syntax, unicode) + assert isinstance(syntax, str) self.syntax = syntax def extract(self, node, parameters): assert isinstance(node, Node) - syntax = parse(self.syntax, u'flow_pipe') + syntax = parse(self.syntax, 'flow_pipe') return SyntaxArc(node, parameters, syntax) def __unicode__(self): - return unicode(self.syntax) + return str(self.syntax) class BindGlobal(BindByName): @@ -461,7 +461,7 @@ def __enabled__(component): return (component.__app__() is context.app) def __call__(self): - body = parse(self.body, u'flow_pipe') + body = parse(self.body, 'flow_pipe') recipe = SubstitutionRecipe(self.state.scope, [], self.parameters, body) recipe = ClosedRecipe(recipe) @@ -471,11 +471,11 @@ def __call__(self): class GlobalPattern(ArcPattern): def __init__(self, syntax): - assert isinstance(syntax, unicode) + assert isinstance(syntax, str) self.syntax = syntax def register(self, app, name, parameters): - assert isinstance(name, unicode) + assert isinstance(name, str) class_name = "Bind%s" % name.title().replace('_', '').encode('utf-8') arity = None if parameters is not None: @@ -491,7 +491,7 @@ def register(self, app, name, parameters): return bind_class def __unicode__(self): - return unicode(self.syntax) + return str(self.syntax) class CustomCmd(Command): @@ -544,11 +544,11 @@ def __call__(self): class CommandPattern(Pattern): def __init__(self, syntax): - assert isinstance(syntax, unicode) + assert isinstance(syntax, str) self.syntax = syntax def register(self, app, name, parameters): - assert isinstance(name, unicode) + assert isinstance(name, str) class_name = "Summon%s" % name.title().replace('_', '').encode('utf-8') parameters = list(parameters) namespace = { @@ -561,7 +561,7 @@ def register(self, app, name, parameters): return summon_class def __unicode__(self): - return unicode(self.syntax) + return str(self.syntax) class TablePatternVal(Validator): @@ -579,7 +579,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): match = self.regexp.match(value) if match is None: raise ValueError("expected table pattern, got %r" @@ -610,7 +610,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): match = self.regexp.match(value) if match is None: raise ValueError("expected column pattern, got %r" @@ -649,7 +649,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): match = self.regexp.match(value) if match is None: raise ValueError("expected unique key pattern, got %r" @@ -698,7 +698,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): match = self.regexp.match(value) if match is None: raise ValueError("expected foreign key pattern, got %r" @@ -754,7 +754,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): match = self.regexp.match(value) if match is None: raise ValueError("expected class pattern, got %r" @@ -824,7 +824,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): match = self.regexp.match(value) if match is None: raise ValueError("expected field pattern, got %r" @@ -889,7 +889,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): value = GlobalPattern(value) if not isinstance(value, GlobalPattern): raise ValueError("expected global pattern, got %r" % value) @@ -903,7 +903,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): value = CommandPattern(value) if not isinstance(value, CommandPattern): raise ValueError("expected command pattern, got %r" % value) @@ -928,7 +928,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): match = self.regexp.match(value) if match is None: raise ValueError("expected label, got %r" @@ -942,7 +942,7 @@ def __call__(self, value): if not name: continue is_reference = False - if name.startswith(u"$"): + if name.startswith("$"): is_reference = True name = name[1:] name = normalize(name) @@ -973,7 +973,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): match = self.regexp.match(value) if match is None: raise ValueError("expected label, got %r" @@ -988,7 +988,7 @@ def __call__(self, value): if not name: continue is_reference = False - if name.startswith(u"$"): + if name.startswith("$"): is_reference = True name = name[1:] name = normalize(name) @@ -1018,7 +1018,7 @@ def __call__(self, value): return ValueError("the null value is not permitted") if isinstance(value, str): value = value.decode('utf-8', 'replace') - if isinstance(value, unicode): + if isinstance(value, str): match = self.regexp.match(value) if match is None: raise ValueError("expected command label, got %r" diff --git a/src/htsql/tweak/resource/locate.py b/src/htsql/tweak/resource/locate.py index 0bec4e0..8f2424f 100644 --- a/src/htsql/tweak/resource/locate.py +++ b/src/htsql/tweak/resource/locate.py @@ -9,9 +9,9 @@ import mimetypes import hashlib import os, os.path -import cStringIO +import io import zipfile -import urllib2 +import urllib.request, urllib.error, urllib.parse import pkg_resources diff --git a/src/htsql/tweak/shell/command.py b/src/htsql/tweak/shell/command.py index 8eff26d..99def44 100644 --- a/src/htsql/tweak/shell/command.py +++ b/src/htsql/tweak/shell/command.py @@ -32,7 +32,7 @@ class ShellCmd(Command): def __init__(self, query=None, is_implicit=False): - assert isinstance(query, maybe(unicode)) + assert isinstance(query, maybe(str)) assert isinstance(is_implicit, bool) self.query = query self.is_implicit = is_implicit @@ -41,14 +41,14 @@ def __init__(self, query=None, is_implicit=False): class CompleteCmd(Command): def __init__(self, names): - assert isinstance(names, listof(unicode)) + assert isinstance(names, listof(str)) self.names = names class ProduceCmd(Command): def __init__(self, query, page=None): - assert isinstance(query, unicode) + assert isinstance(query, str) assert isinstance(page, maybe(int)) if page is None: page = 1 @@ -59,7 +59,7 @@ def __init__(self, query, page=None): class AnalyzeCmd(Command): def __init__(self, query): - assert isinstance(query, unicode) + assert isinstance(query, str) self.query = query @@ -87,7 +87,7 @@ def __call__(self): if isinstance(syntax, StringSyntax): query = syntax.text else: - query = unicode(syntax) + query = str(syntax) command = ShellCmd(query, False) return command @@ -167,7 +167,7 @@ def __call__(self): raise Error("Expected a string literal") try: value = domain.parse(literal.text) - except ValueError, exc: + except ValueError as exc: raise Error(str(exc)) values.append(value) can_read, can_write = values @@ -198,15 +198,15 @@ def __call__(self): resource_root = (server_root + '/%s/shell/' % context.app.tweak.resource.indicator) resource_root = resource_root.decode('utf-8') - if query is not None and query not in [u'', u'/']: + if query is not None and query not in ['', '/']: query_on_start = query - evaluate_on_start = u'true' + evaluate_on_start = 'true' else: - query_on_start = u'/' - evaluate_on_start = u'false' - can_read_on_start = unicode(context.env.can_read).lower() - can_write_on_start = unicode(context.env.can_write).lower() - implicit_shell = unicode(self.command.is_implicit).lower() + query_on_start = '/' + evaluate_on_start = 'false' + can_read_on_start = str(context.env.can_read).lower() + can_write_on_start = str(context.env.can_write).lower() + implicit_shell = str(self.command.is_implicit).lower() status = '200 OK' headers = [('Content-Type', 'text/html; charset=UTF-8')] if self.command.is_implicit: @@ -280,9 +280,9 @@ def __call__(self): def render_names(self, names): yield JS_MAP - yield u"type" - yield u"complete" - yield u"names" + yield "type" + yield "complete" + yield "names" yield JS_SEQ for name in names: yield name @@ -312,11 +312,11 @@ def __call__(self): product = safe_produce(command, cut=limit+1) else: product = produce(command) - except UnsupportedActionError, exc: + except UnsupportedActionError as exc: body = self.render_unsupported(exc) - except PermissionError, exc: + except PermissionError as exc: body = self.render_permissions(exc) - except Error, exc: + except Error as exc: body = self.render_error(exc) else: if isinstance(self.command, AnalyzeCmd): @@ -336,16 +336,16 @@ def __call__(self): def render_unsupported(self, exc): yield JS_MAP - yield u"type" - yield u"unsupported" + yield "type" + yield "unsupported" yield JS_END def render_permissions(self, exc): - detail = unicode(exc) + detail = str(exc) yield JS_MAP - yield u"type" - yield u"permissions" - yield u"detail" + yield "type" + yield "permissions" + yield "detail" yield detail yield JS_END @@ -357,34 +357,34 @@ def render_error(self, exc): first_column = None last_line = None last_column = None - detail = unicode(exc) + detail = str(exc) for paragraph in reversed(exc.paragraphs): if isinstance(paragraph.quote, Mark) and paragraph.quote: mark = paragraph.quote break if mark: - first_break = mark.text.rfind(u'\n', 0, mark.start)+1 - last_break = mark.text.rfind(u'\n', 0, mark.end)+1 - first_line = mark.text.count(u'\n', 0, first_break) - last_line = mark.text.count(u'\n', 0, last_break) + first_break = mark.text.rfind('\n', 0, mark.start)+1 + last_break = mark.text.rfind('\n', 0, mark.end)+1 + first_line = mark.text.count('\n', 0, first_break) + last_line = mark.text.count('\n', 0, last_break) first_column = mark.start-first_break last_column = mark.end-last_break if hint is not None: hint = hint.decode('utf-8') yield JS_MAP - yield u"type" - yield u"error" - yield u"detail" + yield "type" + yield "error" + yield "detail" yield detail - yield u"hint" + yield "hint" yield hint - yield u"first_line" + yield "first_line" yield first_line - yield u"first_column" + yield "first_column" yield first_column - yield u"last_line" + yield "last_line" yield last_line - yield u"last_column" + yield "last_column" yield last_column yield JS_END @@ -396,15 +396,15 @@ def render_product(self, product, limit): data = data[:limit] data = product_to_raw(data) yield JS_MAP - yield u"type" - yield u"product" - yield u"meta" + yield "type" + yield "product" + yield "meta" for token in meta: yield token - yield u"data" + yield "data" for token in data: yield token - yield u"more" + yield "more" yield (limit is not None and isinstance(product.data, list) and len(product.data) > limit) @@ -412,19 +412,19 @@ def render_product(self, product, limit): def render_empty(self): yield JS_MAP - yield u"type" - yield u"empty" + yield "type" + yield "empty" yield JS_END def render_sql(self, plan): if 'sql' in plan.properties: sql = plan.properties['sql'] else: - sql = u"" + sql = "" yield JS_MAP - yield u"type" - yield u"sql" - yield u"sql" + yield "type" + yield "sql" + yield "sql" yield sql yield JS_END diff --git a/src/htsql/tweak/sqlalchemy/introspect.py b/src/htsql/tweak/sqlalchemy/introspect.py index 734e209..137fad3 100644 --- a/src/htsql/tweak/sqlalchemy/introspect.py +++ b/src/htsql/tweak/sqlalchemy/introspect.py @@ -75,7 +75,7 @@ def __call__(self): table.add_unique_key(columns, is_primary) elif isinstance(key_record, ForeignKeyConstraint): column_records = [table_record.columns[column_record] - if isinstance(column_record, basestring) + if isinstance(column_record, str) else column_record for column_record in key_record.columns] names = [decode(column_record.name, column_record.quote) diff --git a/src/htsql_django/views.py b/src/htsql_django/views.py index cb9ed0b..807bef3 100644 --- a/src/htsql_django/views.py +++ b/src/htsql_django/views.py @@ -13,9 +13,9 @@ def to_environ(request): prefix = reverse(gateway) if prefix.endswith('/'): prefix = prefix[:-1] - if isinstance(environ['PATH_INFO'], unicode): + if isinstance(environ['PATH_INFO'], str): environ['PATH_INFO'] = environ['PATH_INFO'].encode('utf-8') - if isinstance(environ['SCRIPT_NAME'], unicode): + if isinstance(environ['SCRIPT_NAME'], str): environ['SCRIPT_NAME'] = environ['SCRIPT_NAME'].encode('utf-8') assert environ['PATH_INFO'].startswith(prefix) assert environ['SCRIPT_NAME'] == '' diff --git a/src/htsql_mssql/core/introspect.py b/src/htsql_mssql/core/introspect.py index 4ba0ce0..9633b3a 100644 --- a/src/htsql_mssql/core/introspect.py +++ b/src/htsql_mssql/core/introspect.py @@ -16,7 +16,7 @@ class IntrospectMSSQL(Introspect): - system_schema_names = [u'guest', u'INFORMATION_SCHEMA', u'sys', u'db_*'] + system_schema_names = ['guest', 'INFORMATION_SCHEMA', 'sys', 'db_*'] def __call__(self): connection = connect() diff --git a/src/htsql_mssql/core/tr/dump.py b/src/htsql_mssql/core/tr/dump.py index a3d87ea..0cafd4f 100644 --- a/src/htsql_mssql/core/tr/dump.py +++ b/src/htsql_mssql/core/tr/dump.py @@ -25,23 +25,23 @@ class MSSQLFormatName(FormatName): def __call__(self): - self.stream.write(u"[%s]" % self.value.replace(u"]", u"]]")) + self.stream.write("[%s]" % self.value.replace("]", "]]")) class MSSQLFormatPlaceholder(FormatPlaceholder): def __call__(self): - self.stream.write(u"%s") + self.stream.write("%s") class MSSQLDumpBranch(DumpBranch): def dump_select(self): aliases = self.state.select_aliases_by_tag[self.frame.tag] - self.write(u"SELECT ") + self.write("SELECT ") self.indent() if self.frame.limit is not None: - self.write(u"TOP "+unicode(self.frame.limit)) + self.write("TOP "+str(self.frame.limit)) self.newline() for index, phrase in enumerate(self.frame.select): alias = None @@ -62,7 +62,7 @@ def dump_select(self): self.format("{selection}", selection=phrase) if index < len(self.frame.select)-1: - self.write(u",") + self.write(",") self.newline() self.dedent() @@ -91,9 +91,9 @@ class MSSQLDumpBoolean(DumpBoolean): def __call__(self): if self.value is True: - self.write(u"1") + self.write("1") if self.value is False: - self.write(u"0") + self.write("0") class MSSQLDumpInteger(DumpInteger): @@ -103,11 +103,11 @@ def __call__(self): raise Error("Got invalid integer value") if abs(self.value) < 2**31: if self.value >= 0: - self.write(unicode(self.value)) + self.write(str(self.value)) else: - self.write(u"(%s)" % self.value) + self.write("(%s)" % self.value) else: - self.write(u"CAST(%s AS BIGINT)" % self.value) + self.write("CAST(%s AS BIGINT)" % self.value) class MSSQLDumpFloat(DumpFloat): @@ -119,7 +119,7 @@ def __call__(self): value = value+'e0' if value[0] == '-': value = "(%s)" % value - self.write(unicode(value)) + self.write(str(value)) class MSSQLDumpDecimal(DumpDecimal): @@ -133,14 +133,14 @@ def __call__(self): value = "%s." % value if value[0] == '-': value = "(%s)" % value - self.write(unicode(value)) + self.write(str(value)) class MSSQLDumpDate(DumpDate): def __call__(self): self.format("CAST({value:literal} AS DATETIME)", - value=unicode(self.value)) + value=str(self.value)) class MSSQLDumpTime(DumpTime): @@ -151,7 +151,7 @@ def __call__(self): value = repr(value) if 'e' not in value and 'E' not in value: value = value+'e0' - self.write(unicode(value)) + self.write(str(value)) class MSSQLDumpDateTime(DumpDateTime): @@ -159,9 +159,9 @@ class MSSQLDumpDateTime(DumpDateTime): def __call__(self): value = self.value.replace(tzinfo=None) if not value.microsecond: - value = unicode(value) + value = str(value) else: - value = unicode(value)[:-3] + value = str(value)[:-3] self.format("CAST({value:literal} AS DATETIME)", value=value) @@ -319,7 +319,7 @@ def __call__(self): if scale is not None: self.format("CAST(ROUND({op}, {precision})" " AS DECIMAL(38,{scale:pass}))", - self.arguments, self.signature, scale=unicode(scale)) + self.arguments, self.signature, scale=str(scale)) else: self.format("ROUND({op}, {precision})", self.arguments, self.signature) @@ -353,7 +353,7 @@ def __call__(self): " CAST(POWER(10e0, {precision}) AS DECIMAL(38,19))," " {precision})" " AS DECIMAL(38,{scale:pass}))", - self.arguments, self.signature, scale=unicode(scale)) + self.arguments, self.signature, scale=str(scale)) else: self.format("ROUND({op} -" " (CASE WHEN {op} >= 0 THEN 0.5 ELSE -0.5 END) /" diff --git a/src/htsql_mssql/core/tr/encode.py b/src/htsql_mssql/core/tr/encode.py index 217e6a3..1ad6edb 100644 --- a/src/htsql_mssql/core/tr/encode.py +++ b/src/htsql_mssql/core/tr/encode.py @@ -15,23 +15,23 @@ def __call__(self): rop = self.state.encode(self.flow.rop) if isinstance(rop, LiteralCode): if rop.value is not None: - value = (u"%" + rop.value.replace(u"\\", u"\\\\") - .replace(u"[", u"\\[") - .replace(u"]", u"\\]") - .replace(u"%", u"\\%") - .replace(u"_", u"\\_") + u"%") + value = ("%" + rop.value.replace("\\", "\\\\") + .replace("[", "\\[") + .replace("]", "\\]") + .replace("%", "\\%") + .replace("_", "\\_") + "%") rop = rop.clone(value=value) else: - backslash_literal = LiteralCode(u"\\", rop.domain, self.flow) - xbackslash_literal = LiteralCode(u"\\\\", rop.domain, self.flow) - lbracket_literal = LiteralCode(u"[", rop.domain, self.flow) - xlbracket_literal = LiteralCode(u"\\[", rop.domain, self.flow) - rbracket_literal = LiteralCode(u"]", rop.domain, self.flow) - xrbracket_literal = LiteralCode(u"\\]", rop.domain, self.flow) - percent_literal = LiteralCode(u"%", rop.domain, self.flow) - xpercent_literal = LiteralCode(u"\\%", rop.domain, self.flow) - underscore_literal = LiteralCode(u"_", rop.domain, self.flow) - xunderscore_literal = LiteralCode(u"\\_", rop.domain, self.flow) + backslash_literal = LiteralCode("\\", rop.domain, self.flow) + xbackslash_literal = LiteralCode("\\\\", rop.domain, self.flow) + lbracket_literal = LiteralCode("[", rop.domain, self.flow) + xlbracket_literal = LiteralCode("\\[", rop.domain, self.flow) + rbracket_literal = LiteralCode("]", rop.domain, self.flow) + xrbracket_literal = LiteralCode("\\]", rop.domain, self.flow) + percent_literal = LiteralCode("%", rop.domain, self.flow) + xpercent_literal = LiteralCode("\\%", rop.domain, self.flow) + underscore_literal = LiteralCode("_", rop.domain, self.flow) + xunderscore_literal = LiteralCode("\\_", rop.domain, self.flow) rop = FormulaCode(ReplaceSig(), rop.domain, self.flow, op=rop, old=backslash_literal, new=xbackslash_literal) diff --git a/src/htsql_mysql/core/introspect.py b/src/htsql_mysql/core/introspect.py index 3a9a807..659579b 100644 --- a/src/htsql_mysql/core/introspect.py +++ b/src/htsql_mysql/core/introspect.py @@ -16,7 +16,7 @@ class IntrospectMySQL(Introspect): - system_schema_names = [u'mysql', u'information_schema'] + system_schema_names = ['mysql', 'information_schema'] def __call__(self): connection = connect() @@ -71,15 +71,15 @@ def __call__(self): data_type = row.data_type column_type = row.column_type length = row.character_maximum_length - if isinstance(length, long): + if isinstance(length, int): length = int(length) - if isinstance(length, long): # LONGTEXT + if isinstance(length, int): # LONGTEXT length = None precision = row.numeric_precision - if isinstance(precision, long): + if isinstance(precision, int): precision = int(precision) scale = row.numeric_scale - if isinstance(scale, long): + if isinstance(scale, int): scale = int(scale) domain = IntrospectMySQLDomain.__invoke__(data_type, column_type, length, precision, scale) diff --git a/src/htsql_mysql/core/tr/compile.py b/src/htsql_mysql/core/tr/compile.py index 6403ba0..5706dce 100644 --- a/src/htsql_mysql/core/tr/compile.py +++ b/src/htsql_mysql/core/tr/compile.py @@ -19,12 +19,12 @@ class MySQLCompileCovering(CompileCovering): def clip(self, term, order, partition): - prefix = u"!htsql:%s" % term.tag - row_number = FormulaCode(UserVariableSig(u"%s:row_number" % prefix), + prefix = "!htsql:%s" % term.tag + row_number = FormulaCode(UserVariableSig("%s:row_number" % prefix), coerce(IntegerDomain()), self.space.flow) keys = [] for idx, code in enumerate(partition): - key = FormulaCode(UserVariableSig(u"%s:partition:%s" + key = FormulaCode(UserVariableSig("%s:partition:%s" % (prefix, idx+1)), code.domain, self.space.flow) keys.append(key) diff --git a/src/htsql_mysql/core/tr/dump.py b/src/htsql_mysql/core/tr/dump.py index 92a216d..44594ad 100644 --- a/src/htsql_mysql/core/tr/dump.py +++ b/src/htsql_mysql/core/tr/dump.py @@ -26,22 +26,22 @@ class MySQLFormatName(FormatName): def __call__(self): - self.stream.write(u"`%s`" % self.value.replace(u"`", u"``")) + self.stream.write("`%s`" % self.value.replace("`", "``")) class MySQLFormatLiteral(FormatLiteral): def __call__(self): - self.stream.write(u"'%s'" % self.value.replace(u"\\", ur"\\") - .replace(u"'", ur"\'") - .replace(u"\n", ur"\n") - .replace(u"\r", ur"\r")) + self.stream.write("'%s'" % self.value.replace("\\", r"\\") + .replace("'", r"\'") + .replace("\n", r"\n") + .replace("\r", r"\r")) class MySQLFormatPlaceholder(FormatPlaceholder): def __call__(self): - self.stream.write(u"%s") + self.stream.write("%s") class MySQLDumpFloat(DumpFloat): @@ -53,7 +53,7 @@ def __call__(self): value = value+'e0' if value[0] == "-": value = "(%s)" % value - self.write(unicode(value)) + self.write(str(value)) class MySQLDumpDecimal(DumpDecimal): @@ -67,19 +67,19 @@ def __call__(self): value = "%s." % value if value[0] == "-": value = "(%s)" % value - self.write(unicode(value)) + self.write(str(value)) class MySQLDumpDate(DumpDate): def __call__(self): - self.format("DATE({value:literal})", value=unicode(self.value)) + self.format("DATE({value:literal})", value=str(self.value)) class MySQLDumpTime(DumpTime): def __call__(self): - self.format("TIME({value:literal})", value=unicode(self.value)) + self.format("TIME({value:literal})", value=str(self.value)) class MySQLDumpDateTime(DumpDateTime): @@ -87,7 +87,7 @@ class MySQLDumpDateTime(DumpDateTime): def __call__(self): # MySQLdb driver does not handle datetime values with microseconds. value = self.value.replace(microsecond=0, tzinfo=None) - self.format("TIMESTAMP({value:literal})", value=unicode(value)) + self.format("TIMESTAMP({value:literal})", value=str(value)) class MySQLDumpToInteger(DumpToInteger): diff --git a/src/htsql_mysql/core/tr/signature.py b/src/htsql_mysql/core/tr/signature.py index 2d1cd07..6ac9f39 100644 --- a/src/htsql_mysql/core/tr/signature.py +++ b/src/htsql_mysql/core/tr/signature.py @@ -10,7 +10,7 @@ class UserVariableSig(NullarySig): def __init__(self, name): - assert isinstance(name, unicode) and len(name) > 0 + assert isinstance(name, str) and len(name) > 0 self.name = name def __basis__(self): diff --git a/src/htsql_oracle/core/connect.py b/src/htsql_oracle/core/connect.py index ed7c9ba..74b6ae7 100644 --- a/src/htsql_oracle/core/connect.py +++ b/src/htsql_oracle/core/connect.py @@ -33,7 +33,7 @@ def outputtypehandler(cls, cursor, name, defaultType, return cursor.var(str, 100, cursor.arraysize, outconverter=cls.outconverter) if defaultType in (cx_Oracle.STRING, cx_Oracle.FIXED_CHAR): - return cursor.var(unicode, size, cursor.arraysize) + return cursor.var(str, size, cursor.arraysize) def open(self): addon = context.app.htsql @@ -102,7 +102,7 @@ def convert(value): if isinstance(value, cx_Oracle.LOB): try: value = value.read() - except cx_Oracle.Error, exc: + except cx_Oracle.Error as exc: message = str(exc) raise Error(message, exc) if isinstance(value, str): diff --git a/src/htsql_oracle/core/tr/dump.py b/src/htsql_oracle/core/tr/dump.py index 5aa1ac9..78e5a4e 100644 --- a/src/htsql_oracle/core/tr/dump.py +++ b/src/htsql_oracle/core/tr/dump.py @@ -32,7 +32,7 @@ class OracleSerializeSegment(SerializeSegment): class OracleFormatPlaceholder(FormatPlaceholder): def __call__(self): - self.stream.write(u":%s" % self.value) + self.stream.write(":%s" % self.value) class OracleDumpScalar(Dump): @@ -40,7 +40,7 @@ class OracleDumpScalar(Dump): adapt(ScalarFrame) def __call__(self): - self.write(u"DUAL") + self.write("DUAL") class OracleDumpBranch(DumpBranch): @@ -87,15 +87,15 @@ def __call__(self): alias = None self.newline() if self.clause.is_cross: - self.write(u"CROSS JOIN ") + self.write("CROSS JOIN ") elif self.clause.is_inner: - self.write(u"INNER JOIN ") + self.write("INNER JOIN ") elif self.clause.is_left and not self.clause.is_right: - self.write(u"LEFT OUTER JOIN ") + self.write("LEFT OUTER JOIN ") elif self.clause.is_right and not self.clause.is_left: - self.write(u"RIGHT OUTER JOIN ") + self.write("RIGHT OUTER JOIN ") else: - self.write(u"FULL OUTER JOIN ") + self.write("FULL OUTER JOIN ") self.indent() self.state.push_hook(with_aliases=True) if alias is not None: @@ -132,18 +132,18 @@ class OracleDumpBoolean(DumpBoolean): def __call__(self): if self.value is True: - self.write(u"1") + self.write("1") if self.value is False: - self.write(u"0") + self.write("0") class OracleDumpInteger(DumpInteger): def __call__(self): if self.value >= 0: - self.write(unicode(self.value)) + self.write(str(self.value)) else: - self.write(u"(%s)" % self.value) + self.write("(%s)" % self.value) class OracleDumpFloat(DumpFloat): @@ -151,22 +151,22 @@ class OracleDumpFloat(DumpFloat): def __call__(self): assert not math.isinf(self.value) and not math.isnan(self.value) if self.value >= 0.0: - self.write(u"%rD" % self.value) + self.write("%rD" % self.value) else: - self.write(u"(%rD)" % self.value) + self.write("(%rD)" % self.value) class OracleDumpTime(DumpTime): def __call__(self): self.format("INTERVAL {value:literal} HOUR TO SECOND", - value=unicode(self.value)) + value=str(self.value)) class OracleDumpDateTime(DumpDateTime): def __call__(self): - self.format("TIMESTAMP {value:literal}", value=unicode(self.value)) + self.format("TIMESTAMP {value:literal}", value=str(self.value)) class OracleDumpToFloat(DumpToFloat): @@ -282,7 +282,7 @@ class OracleDumpRowNumber(DumpBySignature): adapt(RowNumSig) def __call__(self): - self.write(u"ROWNUM") + self.write("ROWNUM") class OracleDumpLength(DumpLength): diff --git a/src/htsql_pgsql/core/introspect.py b/src/htsql_pgsql/core/introspect.py index 066a48b..09ca8cf 100644 --- a/src/htsql_pgsql/core/introspect.py +++ b/src/htsql_pgsql/core/introspect.py @@ -17,10 +17,10 @@ class IntrospectPGSQL(Introspect): - system_schema_names = [u'pg_*', u'information_schema'] + system_schema_names = ['pg_*', 'information_schema'] system_table_names = [] - system_column_names = [u'tableoid', u'cmax', u'xmax', - u'cmin', u'xmin', u'ctid'] + system_column_names = ['tableoid', 'cmax', 'xmax', + 'cmin', 'xmin', 'ctid'] def __call__(self): connection = connect() diff --git a/src/htsql_pgsql/core/tr/dump.py b/src/htsql_pgsql/core/tr/dump.py index f981e7a..a44ce50 100644 --- a/src/htsql_pgsql/core/tr/dump.py +++ b/src/htsql_pgsql/core/tr/dump.py @@ -18,21 +18,21 @@ class PGSQLFormatLiteral(FormatLiteral): def __call__(self): - value = self.value.replace(u"'", u"''") - if u"\\" in value: - value = value.replace(u"\\", u"\\\\") - self.stream.write(u"E'%s'" % value) + value = self.value.replace("'", "''") + if "\\" in value: + value = value.replace("\\", "\\\\") + self.stream.write("E'%s'" % value) else: - self.stream.write(u"'%s'" % value) + self.stream.write("'%s'" % value) class PGSQLFormatPlaceholder(FormatPlaceholder): def __call__(self): if self.value is None: - self.stream.write(u"%s") + self.stream.write("%s") else: - self.stream.write(u"%%(%s)s" % self.value) + self.stream.write("%%(%s)s" % self.value) class PGSQLDumpSortDirection(DumpSortDirection): @@ -49,30 +49,30 @@ class PGSQLDumpFloat(DumpFloat): def __call__(self): if self.value >= 0.0: - self.write(u"%s::FLOAT8" % repr(self.value)) + self.write("%s::FLOAT8" % repr(self.value)) else: - self.write(u"'%s'::FLOAT8" % repr(self.value)) + self.write("'%s'::FLOAT8" % repr(self.value)) class PGSQLDumpDecimal(DumpDecimal): def __call__(self): if not self.value.is_signed(): - self.write(u"%s::NUMERIC" % self.value) + self.write("%s::NUMERIC" % self.value) else: - self.write(u"'%s'::NUMERIC" % self.value) + self.write("'%s'::NUMERIC" % self.value) class PGSQLDumpDate(DumpDate): def __call__(self): - self.format("{value:literal}::DATE", value=unicode(self.value)) + self.format("{value:literal}::DATE", value=str(self.value)) class PGSQLDumpTime(DumpTime): def __call__(self): - self.format("{value:literal}::TIME", value=unicode(self.value)) + self.format("{value:literal}::TIME", value=str(self.value)) class PGSQLDumpDateTime(DumpDateTime): @@ -80,10 +80,10 @@ class PGSQLDumpDateTime(DumpDateTime): def __call__(self): if self.value.tzinfo is None: self.format("{value:literal}::TIMESTAMP", - value=unicode(self.value)) + value=str(self.value)) else: self.format("{value:literal}::TIMESTAMPTZ", - value=unicode(self.value)) + value=str(self.value)) class PGSQLDumpToFloat(DumpToFloat): diff --git a/src/htsql_pgsql/tweak/system/introspect.py b/src/htsql_pgsql/tweak/system/introspect.py index cac4d2c..ea44371 100644 --- a/src/htsql_pgsql/tweak/system/introspect.py +++ b/src/htsql_pgsql/tweak/system/introspect.py @@ -287,9 +287,9 @@ def __call__(self): catalog = super(PGCatalogIntrospectPGSQL, self).__call__() for schema_name, table_name in sorted(self.primary_keys): column_names = self.primary_keys[schema_name, table_name] - schema_name = unicode(schema_name) - table_name = unicode(table_name) - column_names = map(unicode, column_names) + schema_name = str(schema_name) + table_name = str(table_name) + column_names = list(map(str, column_names)) if schema_name not in catalog: continue schema = catalog[schema_name] @@ -308,8 +308,8 @@ def __call__(self): table.add_primary_key(columns) for origin_schema_name, origin_table_name in sorted(self.foreign_keys): keys = self.foreign_keys[origin_schema_name, origin_table_name] - origin_schema_name = unicode(origin_schema_name) - origin_table_name = unicode(origin_table_name) + origin_schema_name = str(origin_schema_name) + origin_table_name = str(origin_table_name) if origin_schema_name not in catalog: continue origin_schema = catalog[schema_name] @@ -318,10 +318,10 @@ def __call__(self): origin = origin_schema[origin_table_name] for (origin_column_names, (target_schema_name, target_table_name), target_column_names) in keys: - origin_column_names = map(unicode, origin_column_names) - target_schema_name = unicode(target_schema_name) - target_table_name = unicode(target_table_name) - target_column_names = map(unicode, target_column_names) + origin_column_names = list(map(str, origin_column_names)) + target_schema_name = str(target_schema_name) + target_table_name = str(target_table_name) + target_column_names = list(map(str, target_column_names)) if any(column_name not in origin.columns for column_name in origin_column_names): continue diff --git a/src/htsql_sqlite/core/connect.py b/src/htsql_sqlite/core/connect.py index b70dede..4cd5e46 100644 --- a/src/htsql_sqlite/core/connect.py +++ b/src/htsql_sqlite/core/connect.py @@ -92,7 +92,7 @@ class UnscrambleSQLiteInteger(Unscramble): def convert(value): if value is None: return None - if isinstance(value, (int, long)): + if isinstance(value, int): return value raise Error("Expected an integer value, got", repr(value)) @@ -136,7 +136,7 @@ def convert(value): value = value.decode('utf-8') except UnicodeDecodeError: pass - if not isinstance(value, unicode): + if not isinstance(value, str): raise Error("Expected a text value, got", repr(value)) return value @@ -151,7 +151,7 @@ def convert(value): return None if isinstance(value, datetime.date): return value - if not isinstance(value, (str, unicode)): + if not isinstance(value, str): raise Error("Expected a date value, got", repr(value)) converter = sqlite3.converters['DATE'] value = converter(value) @@ -168,7 +168,7 @@ def convert(value): return None if isinstance(value, datetime.time): return value - if not isinstance(value, (str, unicode)): + if not isinstance(value, str): raise Error("Expected a time value, got", repr(value)) # FIXME: verify that the value is in valid format. hour, minute, second = value.split(':') @@ -195,7 +195,7 @@ def convert(value): return None if isinstance(value, datetime.datetime): return value - if not isinstance(value, (str, unicode)): + if not isinstance(value, str): raise Error("Expected a timestamp value, got", repr(value)) converter = sqlite3.converters['TIMESTAMP'] value = converter(value) diff --git a/src/htsql_sqlite/core/introspect.py b/src/htsql_sqlite/core/introspect.py index 5fdc543..505945c 100644 --- a/src/htsql_sqlite/core/introspect.py +++ b/src/htsql_sqlite/core/introspect.py @@ -24,7 +24,7 @@ def __call__(self): catalog = make_catalog() - schema = catalog.add_schema(u'') + schema = catalog.add_schema('') cursor.execute(""" SELECT * @@ -85,9 +85,9 @@ def __call__(self): # See `http://www.sqlite.org/cvstrac/tktview?tn=3800` # and `http://www.sqlite.org/src/ci/600482d161`. # The bug is fixed in SQLite 3.6.14. - if (target_name.startswith(u'"') and - target_name.endswith(u'"')): - target_name = target_name[1:-1].replace(u'""', u'"') + if (target_name.startswith('"') and + target_name.endswith('"')): + target_name = target_name[1:-1].replace('""', '"') target_by_id[row.id] = schema[target_name] target_columns_by_id[row.id] = [] target = target_by_id[row.id] diff --git a/src/htsql_sqlite/core/tr/dump.py b/src/htsql_sqlite/core/tr/dump.py index 510f632..dd90953 100644 --- a/src/htsql_sqlite/core/tr/dump.py +++ b/src/htsql_sqlite/core/tr/dump.py @@ -24,11 +24,11 @@ class SQLiteDumpBoolean(DumpBoolean): def __call__(self): if self.value is None: - self.write(u"NULL") + self.write("NULL") if self.value is True: - self.write(u"1") + self.write("1") if self.value is False: - self.write(u"0") + self.write("0") class SQLiteDumpDecimal(DumpDecimal): @@ -37,29 +37,29 @@ def __call__(self): assert self.value.is_finite() value = float(self.value) if value >= 0.0: - self.write(u"%s" % value) + self.write("%s" % value) else: - self.write(u"(%s)" % value) + self.write("(%s)" % value) class SQLiteDumpDate(DumpDate): def __call__(self): - self.format("{value:literal}", value=unicode(self.value)) + self.format("{value:literal}", value=str(self.value)) class SQLiteDumpTime(DumpTime): def __call__(self): value = self.value.replace(tzinfo=None) - self.format("{value:literal}", value=unicode(value)) + self.format("{value:literal}", value=str(value)) class SQLiteDumpDateTime(DumpDateTime): def __call__(self): value = self.value.replace(tzinfo=None) - self.format("{value:literal}", value=unicode(value)) + self.format("{value:literal}", value=str(value)) class SQLiteDumpToFloat(DumpToFloat): @@ -124,11 +124,11 @@ def __call__(self): scale = self.phrase.precision.value if scale >= 0: self.format("ROUND({op}, {scale:pass})", - self.arguments, scale=unicode(scale)) + self.arguments, scale=str(scale)) else: power = 10**(-scale) self.format("(ROUND({op} / {power:pass}.0) * {power:pass}.0)", - self.arguments, power=unicode(power)) + self.arguments, power=str(power)) else: self.format("(ROUND({op} * POWER(10, {precision}))" " / POWER(10, {precision}))",