Skip to content
GitLab
Explore
Sign in
Register
Commits on Source (2)
Use the namedtuple class supplied with Python
· dba05bac
Brian May
authored
Aug 20, 2018
dba05bac
Merge branch 'bam/security-tracker-use_pythons_namedtuple'
· 9dbc156e
Salvatore Bonaccorso
authored
Nov 11, 2018
9dbc156e
Show whitespace changes
Inline
Side-by-side
doc/python-format.txt
View file @
9dbc156e
...
...
@@ -3,8 +3,7 @@ NOTE: THIS DOES NOT DESCRIBE THE CURRENT IMPLEMENTATION
# Layout of major internal data structures
Most data structures use named tuples, as provided by
xcollections.namedtuples (they are not available in Python 2.5, but
the implementation from Python 2.6 works on Python 2.5, too).
collections.namedtuples.
Due to the way unpickling works, you need to import the "parsers"
package.
...
...
lib/python/sectracker/analyzers.py
View file @
9dbc156e
...
...
@@ -18,7 +18,7 @@
import
apt_pkg
as
_apt_pkg
import
re
as
_re
from
sectracker.x
collections
import
namedtuple
as
_namedtuple
from
collections
import
namedtuple
as
_namedtuple
# vercmp is the Debian version comparison algorithm
_apt_pkg
.
init
()
...
...
lib/python/sectracker/diagnostics.py
View file @
9dbc156e
...
...
@@ -15,7 +15,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
from
sectracker.x
collections
import
namedtuple
as
_namedtuple
from
collections
import
namedtuple
as
_namedtuple
Message
=
_namedtuple
(
"
Message
"
,
"
file line level message
"
)
...
...
lib/python/sectracker/parsers.py
View file @
9dbc156e
...
...
@@ -19,7 +19,7 @@ import re
import
debian_support
import
sectracker.regexpcase
as
_regexpcase
from
sectracker.x
collections
import
namedtuple
as
_namedtuple
from
collections
import
namedtuple
as
_namedtuple
import
sectracker.xpickle
as
_xpickle
import
sectracker.diagnostics
...
...
lib/python/sectracker/xcollections.py
deleted
100644 → 0
View file @
7b8c6e62
# Lifted from python2.6-minimal 2.6.5-1.
# See /usr/share/doc/python2.6/copyright for copyright information.
#
# This version has been modified, unneeded functions have been removed.
import
sys
as
_sys
from
keyword
import
iskeyword
as
_iskeyword
from
operator
import
itemgetter
as
_itemgetter
def
namedtuple
(
typename
,
field_names
,
verbose
=
False
):
"""
Returns a new subclass of tuple with named fields.
>>>
Point
=
namedtuple
(
'
Point
'
,
'
x y
'
)
>>>
Point
.
__doc__
# docstring for the new class
'
Point(x, y)
'
>>>
p
=
Point
(
11
,
y
=
22
)
# instantiate with positional args or keywords
>>>
p
[
0
]
+
p
[
1
]
# indexable like a plain tuple
33
>>>
x
,
y
=
p
# unpack like a regular tuple
>>>
x
,
y
(
11
,
22
)
>>>
p
.
x
+
p
.
y
# fields also accessable by name
33
>>>
d
=
p
.
_asdict
()
# convert to a dictionary
>>>
d
[
'
x
'
]
11
>>>
Point
(
**
d
)
# convert from a dictionary
Point
(
x
=
11
,
y
=
22
)
>>>
p
.
_replace
(
x
=
100
)
# _replace() is like str.replace() but targets named fields
Point
(
x
=
100
,
y
=
22
)
"""
# Parse and validate the field names. Validation serves two purposes,
# generating informative error messages and preventing template injection attacks.
if
isinstance
(
field_names
,
basestring
):
field_names
=
field_names
.
replace
(
'
,
'
,
'
'
).
split
()
# names separated by whitespace and/or commas
field_names
=
tuple
(
map
(
str
,
field_names
))
for
name
in
(
typename
,)
+
field_names
:
if
not
all
(
c
.
isalnum
()
or
c
==
'
_
'
for
c
in
name
):
raise
ValueError
(
'
Type names and field names can only contain alphanumeric characters and underscores: %r
'
%
name
)
if
_iskeyword
(
name
):
raise
ValueError
(
'
Type names and field names cannot be a keyword: %r
'
%
name
)
if
name
[
0
].
isdigit
():
raise
ValueError
(
'
Type names and field names cannot start with a number: %r
'
%
name
)
seen_names
=
set
()
for
name
in
field_names
:
if
name
.
startswith
(
'
_
'
):
raise
ValueError
(
'
Field names cannot start with an underscore: %r
'
%
name
)
if
name
in
seen_names
:
raise
ValueError
(
'
Encountered duplicate field name: %r
'
%
name
)
seen_names
.
add
(
name
)
# Create and fill-in the class template
numfields
=
len
(
field_names
)
argtxt
=
repr
(
field_names
).
replace
(
"'"
,
""
)[
1
:
-
1
]
# tuple repr without parens or quotes
reprtxt
=
'
,
'
.
join
(
'
%s=%%r
'
%
name
for
name
in
field_names
)
dicttxt
=
'
,
'
.
join
(
'
%r: t[%d]
'
%
(
name
,
pos
)
for
pos
,
name
in
enumerate
(
field_names
))
template
=
'''
class %(typename)s(tuple):
'
%(typename)s(%(argtxt)s)
'
\n
__slots__ = ()
\n
_fields = %(field_names)r
\n
def __new__(_cls, %(argtxt)s):
return _tuple.__new__(_cls, (%(argtxt)s))
\n
def __repr__(self):
return
'
%(typename)s(%(reprtxt)s)
'
%% self
\n
def _asdict(t):
'
Return a new dict which maps field names to their values
'
return {%(dicttxt)s}
\n
def __getnewargs__(self):
return tuple(self)
\n\n
'''
%
locals
()
for
i
,
name
in
enumerate
(
field_names
):
template
+=
'
%s = _property(_itemgetter(%d))
\n
'
%
(
name
,
i
)
if
verbose
:
print
(
template
)
# Execute the template string in a temporary namespace and
# support tracing utilities by setting a value for frame.f_globals['__name__']
namespace
=
dict
(
_itemgetter
=
_itemgetter
,
__name__
=
'
namedtuple_%s
'
%
typename
,
_property
=
property
,
_tuple
=
tuple
)
try
:
exec
template
in
namespace
except
SyntaxError
as
e
:
raise
SyntaxError
(
e
.
message
+
'
:
\n
'
+
template
)
result
=
namespace
[
typename
]
# For pickling to work, the __module__ variable needs to be set to the frame
# where the named tuple is created. Bypass this step in enviroments where
# sys._getframe is not defined (Jython for example).
if
hasattr
(
_sys
,
'
_getframe
'
):
result
.
__module__
=
_sys
.
_getframe
(
1
).
f_globals
.
get
(
'
__name__
'
,
'
__main__
'
)
return
result