Skip to content

Commit

Permalink
Drop Python 2 support
Browse files Browse the repository at this point in the history
Closes #179
  • Loading branch information
berkerpeksag committed Jan 1, 2025
1 parent 5594db5 commit 7fcca10
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 96 deletions.
8 changes: 1 addition & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,4 @@ There are some other similar libraries, but astor focuses on the following areas
Other derivatives of Armin's code are floating around, and typically
have fixes for a few corner cases that happened to be noticed by the
maintainers, but most of them have not been tested as thoroughly as
astor. One exception may be the version of codegen
`maintained at github by CensoredUsername`__. This has been tested
to work properly on Python 2.7 using astor's test suite, and, as it
is a single source file, it may be easier to drop into some applications
that do not require astor's other features or Python 3.x compatibility.
__ https://github.com/CensoredUsername/codegen
astor.
49 changes: 3 additions & 46 deletions astor/code_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,6 @@ class SourceGenerator(ExplicitNodeVisitor):
"""

using_unicode_literals = False

def __init__(self, indent_with, add_line_information=False,
pretty_string=pretty_string,
# constants
Expand Down Expand Up @@ -321,10 +319,6 @@ def visit_ImportFrom(self, node):
self.statement(node, 'from ', node.level * '.',
node.module or '', ' import ')
self.comma_list(node.names)
# Goofy stuff for Python 2.7 _pyio module
if node.module == '__future__' and 'unicode_literals' in (
x.name for x in node.names):
self.using_unicode_literals = True

def visit_Import(self, node):
self.statement(node, 'import ')
Expand Down Expand Up @@ -455,15 +449,6 @@ def visit_NameConstant(self, node):
def visit_Pass(self, node):
self.statement(node, 'pass')

def visit_Print(self, node):
# XXX: python 2.6 only
self.statement(node, 'print ')
values = node.values
if node.dest is not None:
self.write(' >> ')
values = [node.dest] + node.values
self.comma_list(values, not node.nl)

def visit_Delete(self, node):
self.statement(node, 'del ')
self.comma_list(node.targets)
Expand Down Expand Up @@ -540,14 +525,9 @@ def visit_Continue(self, node):
self.statement(node, 'continue')

def visit_Raise(self, node):
# XXX: Python 2.6 / 3.0 compatibility
self.statement(node, 'raise')
if self.conditional_write(' ', self.get_exc(node)):
self.conditional_write(' from ', node.cause)
elif self.conditional_write(' ', self.get_type(node)):
set_precedence(node, node.inst)
self.conditional_write(', ', node.inst)
self.conditional_write(', ', node.tback)

# Match statement (introduced in Python 3.10)
def visit_Match(self, node):
Expand Down Expand Up @@ -742,14 +722,12 @@ def recurse(node):
mystr = ''.join(result[index:])
del result[index:]
self.colinfo = res_index, str_index # Put it back like we found it
uni_lit = False # No formatted byte strings

else:
assert value is not None, "Node value cannot be None"
mystr = value
uni_lit = self.using_unicode_literals

mystr = self.pretty_string(mystr, embedded, current_line, uni_lit)
mystr = self.pretty_string(mystr, embedded, current_line)

if is_joined:
mystr = 'f' + mystr
Expand Down Expand Up @@ -804,27 +782,10 @@ def part(p, imaginary):
s = real
self.write(s)

def visit_Num(self, node,
# constants
new=sys.version_info >= (3, 0)):
def visit_Num(self, node):
with self.delimit(node) as delimiters:
self._handle_numeric_constant(node.n)

# We can leave the delimiters handling in visit_Num
# since this is meant to handle a Python 2.x specific
# issue and ast.Constant exists only in 3.6+

# The Python 2.x compiler merges a unary minus
# with a number. This is a premature optimization
# that we deal with here...
if not new and delimiters.discard:
if not isinstance(node.n, complex) and node.n < 0:
pow_lhs = Precedence.Pow + 1
delimiters.discard = delimiters.pp != pow_lhs
else:
op = self.get__p_op(node)
delimiters.discard = not isinstance(op, ast.USub)

def visit_Tuple(self, node):
with self.delimit(node) as delimiters:
# Two things are special about tuples:
Expand Down Expand Up @@ -902,6 +863,7 @@ def visit_NamedExpr(self, node):
def visit_UnaryOp(self, node):
with self.delimit(node, node.op) as delimiters:
set_precedence(delimiters.p, node.operand)
# TODO: Remove this.
# In Python 2.x, a unary negative of a literal
# number is merged into the number itself. This
# bit of ugliness means it is useful to know
Expand Down Expand Up @@ -989,11 +951,6 @@ def visit_IfExp(self, node):
def visit_Starred(self, node):
self.write('*', node.value)

def visit_Repr(self, node):
# XXX: python 2.6 only
with self.delimit('``'):
self.visit(node.value)

def visit_Module(self, node):
self.write(*node.body)

Expand Down
11 changes: 2 additions & 9 deletions astor/file_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,9 @@

import ast
import sys
import tokenize
import os

try:
from tokenize import open as fopen
except ImportError:
fopen = open


class CodeToAst(object):
"""Given a module, or a function that was compiled as part
Expand Down Expand Up @@ -56,12 +52,9 @@ def parse_file(fname):
"""Parse a python file into an AST.
This is a very thin wrapper around ast.parse
TODO: Handle encodings other than the default for Python 2
(issue #26)
"""
try:
with fopen(fname) as f:
with tokenize.open(fname) as f:
fstr = f.read()
except IOError:
if fname != 'stdin':
Expand Down
20 changes: 3 additions & 17 deletions astor/string_repr.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,10 @@
This is a lot harder than you would think.
This has lots of Python 2 / Python 3 ugliness.
"""

import re

try:
special_unicode = unicode
except NameError:
class special_unicode(object):
pass

try:
basestring = basestring
except NameError:
basestring = str


def _properly_indented(s, line_indent):
mylist = s.split('\n')[1:]
Expand Down Expand Up @@ -61,8 +48,7 @@ def string_triplequote_repr(s):
return '"""%s"""' % _prep_triple_quotes(s)


def pretty_string(s, embedded, current_line, uni_lit=False,
min_trip_str=20, max_line=100):
def pretty_string(s, embedded, current_line, min_trip_str=20, max_line=100):
"""There are a lot of reasons why we might not want to or
be able to return a triple-quoted string. We can always
punt back to the default normal string.
Expand All @@ -71,9 +57,9 @@ def pretty_string(s, embedded, current_line, uni_lit=False,
default = repr(s)

# Punt on abnormal strings
if (isinstance(s, special_unicode) or not isinstance(s, basestring)):
if isinstance(s, unicode):
return default
if uni_lit and isinstance(s, bytes):
if isinstance(s, bytes):
return 'b' + default

len_s = len(default)
Expand Down
7 changes: 3 additions & 4 deletions tests/test_code_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,10 +571,9 @@ def test_deprecated_constant_nodes(self):

self.assertAstEqualsSource(ast.Ellipsis(), "...")

if sys.version_info >= (3, 0):
self.assertAstEqualsSource(
ast.Assign(targets=[ast.Name(id='spam')], value=ast.Bytes(b"Bytes")),
"spam = b'Bytes'")
self.assertAstEqualsSource(
ast.Assign(targets=[ast.Name(id='spam')], value=ast.Bytes(b"Bytes")),
"spam = b'Bytes'")

self.assertAstEqualsSource(
ast.Assign(targets=[ast.Name(id='spam')], value=ast.Str("String")),
Expand Down
13 changes: 0 additions & 13 deletions tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,5 @@ def test_auto_generated_attributes(self):
self.assertEqual(treewalk.__dict__['post_handlers'], {})


class SourceReprTestCase(unittest.TestCase):
"""
Tests for helpers in astor.source_repr module.
Note that these APIs are not public.
"""

@unittest.skipUnless(sys.version_info[0] == 2, 'only applies to Python 2')
def test_split_lines_unicode_support(self):
source = [u'copy', '\n']
self.assertEqual(split_lines(source), source)


if __name__ == '__main__':
unittest.main()

0 comments on commit 7fcca10

Please sign in to comment.