Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-lint
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-lint
Commits
6f586016
Commit
6f586016
authored
Nov 06, 2015
by
Calen Pennington
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #11 from edx/ned/python3-compatibility
Make it work on Python 3
parents
96f4c581
6c728fb8
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
71 additions
and
45 deletions
+71
-45
edx_lint/pylint/getattr_check.py
+3
-1
edx_lint/pylint/i18n_check.py
+3
-1
edx_lint/tamper_evident.py
+16
-10
test/input/func_i18n_computed_strings.py
+5
-1
test/input/func_noerror_hello_world.py
+0
-3
test/input/func_noerror_ok_i18n.py
+3
-1
test/input/func_noerror_range.py
+7
-0
test/input/func_range.py
+6
-0
test/messages/func_i18n_computed_strings.txt
+4
-4
test/messages/func_range.txt
+4
-4
test/test_tamper_evident.py
+20
-20
No files found.
edx_lint/pylint/getattr_check.py
View file @
6f586016
"""Check that getattr and setattr aren't being used with literal attribute names."""
import
six
import
astroid
from
pylint.checkers
import
BaseChecker
,
utils
...
...
@@ -49,7 +51,7 @@ class GetSetAttrLiteralChecker(BaseChecker):
second
=
node
.
args
[
1
]
if
isinstance
(
second
,
astroid
.
Const
):
if
isinstance
(
second
.
value
,
basestring
):
if
isinstance
(
second
.
value
,
six
.
string_types
):
# The first argument is a constant string! Bad!
self
.
add_message
(
self
.
MESSAGE_ID
,
args
=
node
.
func
.
name
,
node
=
node
)
...
...
edx_lint/pylint/i18n_check.py
View file @
6f586016
import
six
import
astroid
from
pylint.checkers
import
BaseChecker
,
utils
...
...
@@ -51,7 +53,7 @@ class TranslationStringConstantsChecker(BaseChecker):
first
=
node
.
args
[
0
]
if
isinstance
(
first
,
astroid
.
Const
):
if
isinstance
(
first
.
value
,
basestring
):
if
isinstance
(
first
.
value
,
six
.
string_types
):
# The first argument is a constant string! All is well!
return
...
...
edx_lint/tamper_evident.py
View file @
6f586016
...
...
@@ -15,7 +15,7 @@ class TamperEvidentFile(object):
def
__init__
(
self
,
filename
):
self
.
filename
=
filename
def
write
(
self
,
text
,
hashline
=
"# {}"
):
def
write
(
self
,
text
,
hashline
=
b
"# {}"
):
"""
Write `text` to the file.
...
...
@@ -25,16 +25,22 @@ class TamperEvidentFile(object):
The last line is written with the `hashline` format string, which can
be changed to accommodate different file syntaxes.
Arguments:
text (byte string): the contents of the file to write.
hashline (byte string): the format of the last line to append to
the file, with "{}" replaced with the hash.
"""
if
not
text
.
endswith
(
"
\n
"
):
text
+=
"
\n
"
if
not
text
.
endswith
(
b
"
\n
"
):
text
+=
b
"
\n
"
hash
=
hashlib
.
sha1
(
text
)
.
hexdigest
()
with
open
(
self
.
filename
,
"w"
)
as
f
:
with
open
(
self
.
filename
,
"w
b
"
)
as
f
:
f
.
write
(
text
)
f
.
write
(
hashline
.
format
(
hash
))
f
.
write
(
"
\n
"
)
f
.
write
(
hashline
.
decode
(
"ascii"
)
.
format
(
hash
)
.
encode
(
"ascii"
))
f
.
write
(
b
"
\n
"
)
def
validate
(
self
):
"""
...
...
@@ -44,18 +50,18 @@ class TamperEvidentFile(object):
with.
"""
with
open
(
self
.
filename
,
"r"
)
as
f
:
with
open
(
self
.
filename
,
"r
b
"
)
as
f
:
text
=
f
.
read
()
start_last_line
=
text
.
rfind
(
"
\n
"
,
0
,
-
1
)
start_last_line
=
text
.
rfind
(
b
"
\n
"
,
0
,
-
1
)
if
start_last_line
==
-
1
:
return
False
original_text
=
text
[:
start_last_line
+
1
]
last_line
=
text
[
start_last_line
+
1
:]
expected_hash
=
hashlib
.
sha1
(
original_text
)
.
hexdigest
()
match
=
re
.
search
(
r"[0-9a-f]{40}"
,
last_line
)
expected_hash
=
hashlib
.
sha1
(
original_text
)
.
hexdigest
()
.
encode
(
"ascii"
)
match
=
re
.
search
(
b
r
"[0-9a-f]{40}"
,
last_line
)
if
not
match
:
return
False
actual_hash
=
match
.
group
(
0
)
...
...
test/input/func_i18n_computed_strings.py
View file @
6f586016
...
...
@@ -2,7 +2,11 @@
# pylint: disable=missing-docstring
from
string
import
lower
as
_
,
upper
as
gettext
def
_
(
text
):
return
text
def
gettext
(
text
):
return
text
def
welcome
(
name
):
_
(
"Hello"
+
"There"
)
...
...
test/input/func_noerror_hello_world.py
deleted
100644 → 0
View file @
96f4c581
"""No-op file to see a test run."""
print
"Hello, world!"
test/input/func_noerror_ok_i18n.py
View file @
6f586016
"""These are all good uses of _()"""
from
string
import
lower
as
_
def
_
(
text
):
"""A dummy _() to use."""
return
text
_
(
"Hello"
)
...
...
test/input/func_noerror_range.py
View file @
6f586016
"""Good uses of range."""
import
six
if
six
.
PY3
:
def
xrange
(
*
args_unused
):
# pylint: disable=unused-argument, redefined-builtin
"""Just to keep PY3 happy."""
i
=
2
range
(
10
)
...
...
test/input/func_range.py
View file @
6f586016
"""Bad uses of range()."""
import
six
if
six
.
PY3
:
def
xrange
(
*
args_unused
):
# pylint: disable=unused-argument, redefined-builtin
"""Just to keep PY3 happy."""
i
=
12
range
(
0
,
10
)
...
...
test/messages/func_i18n_computed_strings.txt
View file @
6f586016
E:
8
:welcome: i18n function _() must be called with a literal string
E:
9
:welcome: i18n function _() must be called with a literal string
E: 1
0
:welcome: i18n function _() must be called with a literal string
E: 1
4
:welcome: i18n function gettext() must be called with a literal string
E:
12
:welcome: i18n function _() must be called with a literal string
E:
13
:welcome: i18n function _() must be called with a literal string
E: 1
4
:welcome: i18n function _() must be called with a literal string
E: 1
8
:welcome: i18n function gettext() must be called with a literal string
test/messages/func_range.txt
View file @
6f586016
C: 5: range() call could be single-argument
C: 6: range() call could be single-argument
C: 7: range() call could be single-argument
C: 8: xrange() call could be single-argument
C: 11: range() call could be single-argument
C: 12: range() call could be single-argument
C: 13: range() call could be single-argument
C: 14: xrange() call could be single-argument
C: 19: range() call could be single-argument
test/test_tamper_evident.py
View file @
6f586016
...
...
@@ -23,60 +23,60 @@ class TamperEvidentFileTest(unittest.TestCase):
def
test_writing
(
self
):
# The contents are written, with a hash.
# Different contents produce different hashes.
filename1
=
self
.
write_tamper_evident
(
"Hello!"
)
filename1
=
self
.
write_tamper_evident
(
b
"Hello!"
)
with
open
(
filename1
)
as
f
:
with
open
(
filename1
,
"rb"
)
as
f
:
self
.
assertEqual
(
f
.
read
(),
"Hello!
\n
# a8d191538209e335154750d2df575b9ddfb16fc7
\n
"
b
"Hello!
\n
# a8d191538209e335154750d2df575b9ddfb16fc7
\n
"
)
filename2
=
self
.
write_tamper_evident
(
"Hello?"
)
filename2
=
self
.
write_tamper_evident
(
b
"Hello?"
)
with
open
(
filename2
)
as
f
:
with
open
(
filename2
,
"rb"
)
as
f
:
self
.
assertEqual
(
f
.
read
(),
"Hello?
\n
# 4820175d44ef1a2c92e52bd1b3b7f05020d66e1c
\n
"
b
"Hello?
\n
# 4820175d44ef1a2c92e52bd1b3b7f05020d66e1c
\n
"
)
def
test_hashline_formatting
(
self
):
filename1
=
self
.
write_tamper_evident
(
"Hello!"
,
hashline
=
"XXX {} YYY"
)
filename1
=
self
.
write_tamper_evident
(
b
"Hello!"
,
hashline
=
b
"XXX {} YYY"
)
with
open
(
filename1
)
as
f
:
with
open
(
filename1
,
"rb"
)
as
f
:
self
.
assertEqual
(
f
.
read
(),
"Hello!
\n
XXX a8d191538209e335154750d2df575b9ddfb16fc7 YYY
\n
"
b
"Hello!
\n
XXX a8d191538209e335154750d2df575b9ddfb16fc7 YYY
\n
"
)
def
test_validating_a_good_file
(
self
):
filename
=
self
.
write_tamper_evident
(
"Am I OK?"
)
filename
=
self
.
write_tamper_evident
(
b
"Am I OK?"
)
tef
=
TamperEvidentFile
(
filename
)
self
.
assertTrue
(
tef
.
validate
())
def
test_appending_is_detected
(
self
):
filename
=
self
.
write_tamper_evident
(
"Am I OK?"
)
filename
=
self
.
write_tamper_evident
(
b
"Am I OK?"
)
with
open
(
filename
,
"a"
)
as
f
:
f
.
write
(
"tamper
\n
"
)
with
open
(
filename
,
"a
b
"
)
as
f
:
f
.
write
(
b
"tamper
\n
"
)
tef
=
TamperEvidentFile
(
filename
)
self
.
assertFalse
(
tef
.
validate
())
def
test_editing_is_detected
(
self
):
filename
=
self
.
write_tamper_evident
(
"Line 1
\n
Line 2
\n
Line 3
\n
"
)
with
open
(
filename
,
"r"
)
as
f
:
filename
=
self
.
write_tamper_evident
(
b
"Line 1
\n
Line 2
\n
Line 3
\n
"
)
with
open
(
filename
,
"r
b
"
)
as
f
:
text
=
f
.
read
()
with
open
(
filename
,
"w"
)
as
f
:
f
.
write
(
"X"
)
with
open
(
filename
,
"w
b
"
)
as
f
:
f
.
write
(
b
"X"
)
f
.
write
(
text
[
1
:])
tef
=
TamperEvidentFile
(
filename
)
self
.
assertFalse
(
tef
.
validate
())
def
test_oneline_file_is_detected
(
self
):
filename
=
self
.
write_tamper_evident
(
"Am I OK?"
)
filename
=
self
.
write_tamper_evident
(
b
"Am I OK?"
)
with
open
(
filename
,
"w"
)
as
f
:
f
.
write
(
"tamper"
)
with
open
(
filename
,
"w
b
"
)
as
f
:
f
.
write
(
b
"tamper"
)
tef
=
TamperEvidentFile
(
filename
)
self
.
assertFalse
(
tef
.
validate
())
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment