Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Changes for compatibility with Python 3 #22

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Files to ignore by git.

# Back-up files
*~
*.swp

# Generic auto-generated build files
*.pyc
*.pyo

# Specific auto-generated build files
.eggs
.tox
/__pycache__
/build
/dist
/python_gflags.egg-info
2 changes: 1 addition & 1 deletion gflags/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ def ADOPT_module_key_flags( # pylint: disable=g-bad-name
# a different module. So, we can't use _GetKeyFlagsForModule.
# Instead, we take all flags from _SPECIAL_FLAGS (a private
# FlagValues, where no other module should register flags).
[f.name for f in _helpers.SPECIAL_FLAGS.FlagDict().itervalues()],
[f.name for f in iter(_helpers.SPECIAL_FLAGS.FlagDict().values())],
flag_values=_helpers.SPECIAL_FLAGS,
key_flag_values=flag_values)

Expand Down
7 changes: 3 additions & 4 deletions gflags/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ def GetCallingModuleObjectAndName():
Raises:
AssertionError: if no calling module could be identified.
"""
range_func = range if sys.version_info[0] >= 3 else xrange
for depth in range_func(1, sys.getrecursionlimit()):
for depth in range(1, sys.getrecursionlimit()):
# sys._getframe is the right thing to use here, as it's the best
# way to walk up the call stack.
globals_for_frame = sys._getframe(depth).f_globals # pylint: disable=protected-access
Expand Down Expand Up @@ -188,7 +187,7 @@ def GetHelpWidth():
return _DEFAULT_HELP_WIDTH
try:
data = fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, '1234')
columns = struct.unpack('hh', data)[1]
columns = struct.unpack('HH', data)[1]
# Emacs mode returns 0.
# Here we assume that any value below 40 is unreasonable.
if columns >= _MIN_HELP_WIDTH:
Expand Down Expand Up @@ -357,7 +356,7 @@ def FlagDictToArgs(flag_map):
Yields:
sequence of string suitable for a subprocess execution.
"""
for key, value in flag_map.iteritems():
for key, value in iter(flag_map.items()):
if value is None:
yield '--%s' % key
elif isinstance(value, bool):
Expand Down
20 changes: 10 additions & 10 deletions gflags/_helpers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,35 +52,35 @@ def setUp(self):
'ftree-ch']

def testDamerauLevenshteinId(self):
self.assertEquals(0, _helpers._DamerauLevenshtein('asdf', 'asdf'))
self.assertEqual(0, _helpers._DamerauLevenshtein('asdf', 'asdf'))

def testDamerauLevenshteinEmpty(self):
self.assertEquals(5, _helpers._DamerauLevenshtein('', 'kites'))
self.assertEquals(6, _helpers._DamerauLevenshtein('kitten', ''))
self.assertEqual(5, _helpers._DamerauLevenshtein('', 'kites'))
self.assertEqual(6, _helpers._DamerauLevenshtein('kitten', ''))

def testDamerauLevenshteinCommutative(self):
self.assertEquals(2, _helpers._DamerauLevenshtein('kitten', 'kites'))
self.assertEquals(2, _helpers._DamerauLevenshtein('kites', 'kitten'))
self.assertEqual(2, _helpers._DamerauLevenshtein('kitten', 'kites'))
self.assertEqual(2, _helpers._DamerauLevenshtein('kites', 'kitten'))

def testDamerauLevenshteinTransposition(self):
self.assertEquals(1, _helpers._DamerauLevenshtein('kitten', 'ktiten'))
self.assertEqual(1, _helpers._DamerauLevenshtein('kitten', 'ktiten'))

def testMispelledSuggestions(self):
suggestions = _helpers.GetFlagSuggestions('fstack_protector_all',
self.longopts)
self.assertEquals(['fstack-protector-all'], suggestions)
self.assertEqual(['fstack-protector-all'], suggestions)

def testAmbiguousPrefixSuggestion(self):
suggestions = _helpers.GetFlagSuggestions('fstack', self.longopts)
self.assertEquals(['fstack-protector', 'fstack-protector-all'], suggestions)
self.assertEqual(['fstack-protector', 'fstack-protector-all'], suggestions)

def testMisspelledAmbiguousPrefixSuggestion(self):
suggestions = _helpers.GetFlagSuggestions('stack', self.longopts)
self.assertEquals(['fstack-protector', 'fstack-protector-all'], suggestions)
self.assertEqual(['fstack-protector', 'fstack-protector-all'], suggestions)

def testCrazySuggestion(self):
suggestions = _helpers.GetFlagSuggestions('asdfasdgasdfa', self.longopts)
self.assertEquals([], suggestions)
self.assertEqual([], suggestions)


def main():
Expand Down
6 changes: 3 additions & 3 deletions gflags/argument_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@

"""Contains base classes used to parse and convert arguments."""

import cStringIO
import csv
import io
import string


Expand Down Expand Up @@ -325,7 +325,7 @@ def __init__(self, list_sep):

def Serialize(self, value):
"""Serialize a list as a string, if possible, or as a unicode string."""
output = cStringIO.StringIO()
output = io.StringIO()
writer = csv.writer(output)

# csv.writer doesn't accept unicode, so we convert to UTF-8.
Copy link

@barabo barabo Jun 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe there is a lurking bug on the following line when running in python3 (use of unicode keyword).

Instead, I believe you can replace all occurrences (there's only one) of CsvListSerializer(',') with ListSerializer(','). This prevents the need for importing the io module entirely.

Expand Down Expand Up @@ -382,7 +382,7 @@ def Parse(self, argument):
else:
try:
return [s.strip() for s in list(csv.reader([argument], strict=True))[0]]
except csv.Error, e:
except csv.Error as e:
# Provide a helpful report for case like
# --listflag="$(printf 'hello,\nworld')"
# IOW, list flag values containing naked newlines. This error
Expand Down
2 changes: 1 addition & 1 deletion gflags/flag.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def Parse(self, argument):
self.name, argument, self.value))
try:
self.value = self.parser.Parse(argument)
except ValueError, e: # Recast ValueError as IllegalFlagValue.
except ValueError as e: # Recast ValueError as IllegalFlagValue.
raise exceptions.IllegalFlagValue(
'flag --%s=%s: %s' % (self.name, argument, e))
self.present += 1
Expand Down
43 changes: 37 additions & 6 deletions gflags/flags_formatting_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#!/usr/bin/env python
import struct
import sys
import unittest

try:
import fcntl # pylint: disable=g-import-not-at-top
except ImportError:
fcntl = None
try:
# Importing termios will fail on non-unix platforms.
import termios # pylint: disable=g-import-not-at-top
except ImportError:
termios = None

import gflags
from gflags import _helpers

Expand All @@ -10,6 +22,25 @@
class FlagsUnitTest(unittest.TestCase):
"""Flags formatting Unit Test."""

def setUp(self):
"""Set up before running a test."""
self._winsize_data = None
if fcntl and termios:
# The tests rely on the terminal width so we need to set it to
# a value smaller than the minimum help width used in the tests.
winsize_data = struct.pack('HHHH', 0, 0, 0, 0)
self._winsize_data = fcntl.ioctl(
sys.stdout, termios.TIOCGWINSZ, winsize_data)
winsize = struct.unpack('HHHH', self._winsize_data)
winsize_data = struct.pack(
'HHHH', winsize[0], 0, winsize[2], winsize[3])
fcntl.ioctl(sys.stdout, termios.TIOCSWINSZ, winsize_data)

def tearDown(self):
"""Clean up after running a test."""
if fcntl and termios and self._winsize_data:
fcntl.ioctl(sys.stdout, termios.TIOCSWINSZ, self._winsize_data)

def testGetHelpWidth(self):
"""Verify that GetHelpWidth() reflects _help_width."""
default_help_width = _helpers._DEFAULT_HELP_WIDTH # Save.
Expand All @@ -30,7 +61,7 @@ def testTextWrap(self):
# Generate a string with length 40, no spaces
text = ''
expect = []
for n in xrange(4):
for n in range(4):
line = str(n)
line += '123456789'
text += line
Expand Down Expand Up @@ -62,7 +93,7 @@ def testTextWrap(self):
13: ['a b c d e f g', 'h'],
14: ['a b c d e f g', 'h'],
15: ['a b c d e f g h']}
for width, exp in expect.iteritems():
for width, exp in iter(expect.items()):
self.assertEqual(exp, gflags.TextWrap(input_value, width).split('\n'))

# We turn lines with only whitespace into empty lines
Expand Down Expand Up @@ -178,18 +209,18 @@ def testDocToHelp_FlagValues(self):
# Test the general outline of the converted docs
lines = doc.splitlines()
self.assertEqual(17, len(lines))
empty_lines = [index for index in xrange(len(lines)) if not lines[index]]
empty_lines = [index for index in range(len(lines)) if not lines[index]]
self.assertEqual([1, 3, 5, 8, 12, 15], empty_lines)
# test that some starting prefix is kept
flags_lines = [index for index in xrange(len(lines))
flags_lines = [index for index in range(len(lines))
if lines[index].startswith(' FLAGS')]
self.assertEqual([7, 10, 11], flags_lines)
# but other, especially common space has been removed
space_lines = [index for index in xrange(len(lines))
space_lines = [index for index in range(len(lines))
if lines[index] and lines[index][0].isspace()]
self.assertEqual([7, 10, 11, 14], space_lines)
# No right space was kept
rspace_lines = [index for index in xrange(len(lines))
rspace_lines = [index for index in range(len(lines))
if lines[index] != lines[index].rstrip()]
self.assertEqual([], rspace_lines)
# test double spaces are kept
Expand Down
2 changes: 1 addition & 1 deletion gflags/flags_modules_for_testing/module_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def ExecuteCode(code, global_dict):
"""
# Indeed, using exec generates a lint warning. But some user code
# actually uses exec, and we have to test for it ...
exec code in global_dict # pylint: disable=exec-used
exec(code, global_dict) # pylint: disable=exec-used


def DisclaimKeyFlags():
Expand Down
1 change: 1 addition & 0 deletions gflags/flags_unicode_literals_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
class FlagsUnicodeLiteralsTest(unittest.TestCase):

def testUnicodeFlagNameAndValueAreGood(self):
# This call triggers UnparsedFlagAccessError.
alleged_mountain_lion = gflags.FLAGS.seen_in_crittenden
self.assertTrue(
isinstance(alleged_mountain_lion, type(u'')),
Expand Down
18 changes: 9 additions & 9 deletions gflags/flagvalues.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def FindModuleDefiningFlag(self, flagname, default=None):
If no such module exists (i.e. no flag with this name exists),
we return default.
"""
for module, flags in self.FlagsByModuleDict().iteritems():
for module, flags in iter(self.FlagsByModuleDict().items()):
for flag in flags:
if flag.name == flagname or flag.short_name == flagname:
return module
Expand All @@ -263,7 +263,7 @@ def FindModuleIdDefiningFlag(self, flagname, default=None):
If no such module exists (i.e. no flag with this name exists),
we return default.
"""
for module_id, flags in self.FlagsByModuleIdDict().iteritems():
for module_id, flags in iter(self.FlagsByModuleIdDict().items()):
for flag in flags:
if flag.name == flagname or flag.short_name == flagname:
return module_id
Expand All @@ -275,7 +275,7 @@ def AppendFlagValues(self, flag_values):
Args:
flag_values: registry to copy from
"""
for flag_name, flag in flag_values.FlagDict().iteritems():
for flag_name, flag in iter(flag_values.FlagDict().items()):
# Each flags with shortname appears here twice (once under its
# normal name, and again with its short name). To prevent
# problems (DuplicateFlagError) with double flag registration, we
Expand Down Expand Up @@ -405,7 +405,7 @@ def __setattr__(self, name, value):

def _AssertAllValidators(self):
all_validators = set()
for flag in self.FlagDict().itervalues():
for flag in iter(self.FlagDict().values()):
for validator in flag.validators:
all_validators.add(validator)
self._AssertValidators(all_validators)
Expand All @@ -425,7 +425,7 @@ def _AssertValidators(self, validators):
validators, key=lambda validator: validator.insertion_index):
try:
validator.Verify(self)
except gflags_validators.Error, e:
except gflags_validators.Error as e:
message = validator.PrintFlagsWithValues(self)
raise exceptions.IllegalFlagValue('%s: %s' % (message, str(e)))

Expand Down Expand Up @@ -500,7 +500,7 @@ def __RemoveFlagFromDictByModule(self, flags_by_module_dict, flag_obj):
flags.
flag_obj: A flag object.
"""
for unused_module, flags_in_module in flags_by_module_dict.iteritems():
for unused_module, flags_in_module in iter(flags_by_module_dict.items()):
# while (as opposed to if) takes care of multiple occurrences of a
# flag in the list for the same module.
while flag_obj in flags_in_module:
Expand Down Expand Up @@ -851,14 +851,14 @@ def ShortestUniquePrefixes(self, fl):
# name (the latter check uses cached info from the previous loop).
shortest_matches = {}
prev_idx = 0
for flag_idx in xrange(len(sorted_flags)):
for flag_idx in range(len(sorted_flags)):
curr = sorted_flags[flag_idx]
if flag_idx == (len(sorted_flags) - 1):
next_flag = None
else:
next_flag = sorted_flags[flag_idx+1]
next_flag_len = len(next_flag)
for curr_idx in xrange(len(curr)):
for curr_idx in range(len(curr)):
if (next_flag is None
or curr_idx >= next_flag_len
or curr[curr_idx] != next_flag[curr_idx]):
Expand Down Expand Up @@ -945,7 +945,7 @@ def __GetFlagFileLines(self, filename, parsed_file_stack=None):
flag_line_list = [] # Subset of lines w/o comments, blanks, flagfile= tags.
try:
file_obj = open(filename, 'r')
except IOError, e_msg:
except IOError as e_msg:
raise exceptions.CantOpenFlagFileError(
'ERROR:: Unable to open flagfile: %s' % e_msg)

Expand Down
9 changes: 5 additions & 4 deletions gflags/third_party/pep257/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/usr/bin/env python

import sys

def trim(docstring):
"""Removes indentation from triple-quoted strings.

Expand All @@ -10,18 +8,21 @@ def trim(docstring):
"""
if not docstring:
return ''
# Python 3 does not support sys.maxint so we use and arbitrary
# large integer instead.
maxint = 1 << 32
# Convert tabs to spaces (following the normal Python rules)
# and split into a list of lines:
lines = docstring.expandtabs().splitlines()
# Determine minimum indentation (first line doesn't count):
indent = sys.maxint
indent = maxint
for line in lines[1:]:
stripped = line.lstrip()
if stripped:
indent = min(indent, len(line) - len(stripped))
# Remove indentation (first line is special):
trimmed = [lines[0].strip()]
if indent < sys.maxint:
if indent < maxint:
for line in lines[1:]:
trimmed.append(line[indent:].rstrip())
# Strip off trailing and leading blank lines:
Expand Down
10 changes: 10 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[tox]
envlist = py27, py34

[testenv]
setenv =
PYTHONPATH = {toxinidir}
commands =
python gflags/flags_formatting_test.py
python gflags/flags_unicode_literals_test.py
python gflags/_helpers_test.py