Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
Spack
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
eic_tools
Spack
Commits
d95e7ecf
Commit
d95e7ecf
authored
10 years ago
by
Todd Gamblin
Browse files
Options
Downloads
Patches
Plain Diff
Remove dependency on Python2.7 OrderedDict, revise config parser
parent
d86a6380
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
lib/spack/external/ordereddict.py
+262
-0
262 additions, 0 deletions
lib/spack/external/ordereddict.py
lib/spack/spack/config.py
+22
-44
22 additions, 44 deletions
lib/spack/spack/config.py
with
284 additions
and
44 deletions
lib/spack/external/ordereddict.py
0 → 100644
+
262
−
0
View file @
d95e7ecf
#
# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
# Passes Python2.7's test suite and incorporates all the latest updates.
#
# From http://code.activestate.com/recipes/576693-ordered-dictionary-for-py24/
# This file is in the public domain, and has no particular license.
#
try
:
from
thread
import
get_ident
as
_get_ident
except
ImportError
:
from
dummy_thread
import
get_ident
as
_get_ident
try
:
from
_abcoll
import
KeysView
,
ValuesView
,
ItemsView
except
ImportError
:
pass
class
OrderedDict
(
dict
):
'
Dictionary that remembers insertion order
'
# An inherited dict maps keys to values.
# The inherited dict provides __getitem__, __len__, __contains__, and get.
# The remaining methods are order-aware.
# Big-O running times for all methods are the same as for regular dictionaries.
# The internal self.__map dictionary maps keys to links in a doubly linked list.
# The circular doubly linked list starts and ends with a sentinel element.
# The sentinel element never gets deleted (this simplifies the algorithm).
# Each link is stored as a list of length three: [PREV, NEXT, KEY].
def
__init__
(
self
,
*
args
,
**
kwds
):
'''
Initialize an ordered dictionary. Signature is the same as for
regular dictionaries, but keyword arguments are not recommended
because their insertion order is arbitrary.
'''
if
len
(
args
)
>
1
:
raise
TypeError
(
'
expected at most 1 arguments, got %d
'
%
len
(
args
))
try
:
self
.
__root
except
AttributeError
:
self
.
__root
=
root
=
[]
# sentinel node
root
[:]
=
[
root
,
root
,
None
]
self
.
__map
=
{}
self
.
__update
(
*
args
,
**
kwds
)
def
__setitem__
(
self
,
key
,
value
,
dict_setitem
=
dict
.
__setitem__
):
'
od.__setitem__(i, y) <==> od[i]=y
'
# Setting a new item creates a new link which goes at the end of the linked
# list, and the inherited dictionary is updated with the new key/value pair.
if
key
not
in
self
:
root
=
self
.
__root
last
=
root
[
0
]
last
[
1
]
=
root
[
0
]
=
self
.
__map
[
key
]
=
[
last
,
root
,
key
]
dict_setitem
(
self
,
key
,
value
)
def
__delitem__
(
self
,
key
,
dict_delitem
=
dict
.
__delitem__
):
'
od.__delitem__(y) <==> del od[y]
'
# Deleting an existing item uses self.__map to find the link which is
# then removed by updating the links in the predecessor and successor nodes.
dict_delitem
(
self
,
key
)
link_prev
,
link_next
,
key
=
self
.
__map
.
pop
(
key
)
link_prev
[
1
]
=
link_next
link_next
[
0
]
=
link_prev
def
__iter__
(
self
):
'
od.__iter__() <==> iter(od)
'
root
=
self
.
__root
curr
=
root
[
1
]
while
curr
is
not
root
:
yield
curr
[
2
]
curr
=
curr
[
1
]
def
__reversed__
(
self
):
'
od.__reversed__() <==> reversed(od)
'
root
=
self
.
__root
curr
=
root
[
0
]
while
curr
is
not
root
:
yield
curr
[
2
]
curr
=
curr
[
0
]
def
clear
(
self
):
'
od.clear() -> None. Remove all items from od.
'
try
:
for
node
in
self
.
__map
.
itervalues
():
del
node
[:]
root
=
self
.
__root
root
[:]
=
[
root
,
root
,
None
]
self
.
__map
.
clear
()
except
AttributeError
:
pass
dict
.
clear
(
self
)
def
popitem
(
self
,
last
=
True
):
'''
od.popitem() -> (k, v), return and remove a (key, value) pair.
Pairs are returned in LIFO order if last is true or FIFO order if false.
'''
if
not
self
:
raise
KeyError
(
'
dictionary is empty
'
)
root
=
self
.
__root
if
last
:
link
=
root
[
0
]
link_prev
=
link
[
0
]
link_prev
[
1
]
=
root
root
[
0
]
=
link_prev
else
:
link
=
root
[
1
]
link_next
=
link
[
1
]
root
[
1
]
=
link_next
link_next
[
0
]
=
root
key
=
link
[
2
]
del
self
.
__map
[
key
]
value
=
dict
.
pop
(
self
,
key
)
return
key
,
value
# -- the following methods do not depend on the internal structure --
def
keys
(
self
):
'
od.keys() -> list of keys in od
'
return
list
(
self
)
def
values
(
self
):
'
od.values() -> list of values in od
'
return
[
self
[
key
]
for
key
in
self
]
def
items
(
self
):
'
od.items() -> list of (key, value) pairs in od
'
return
[(
key
,
self
[
key
])
for
key
in
self
]
def
iterkeys
(
self
):
'
od.iterkeys() -> an iterator over the keys in od
'
return
iter
(
self
)
def
itervalues
(
self
):
'
od.itervalues -> an iterator over the values in od
'
for
k
in
self
:
yield
self
[
k
]
def
iteritems
(
self
):
'
od.iteritems -> an iterator over the (key, value) items in od
'
for
k
in
self
:
yield
(
k
,
self
[
k
])
def
update
(
*
args
,
**
kwds
):
'''
od.update(E, **F) -> None. Update od from dict/iterable E and F.
If E is a dict instance, does: for k in E: od[k] = E[k]
If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
Or if E is an iterable of items, does: for k, v in E: od[k] = v
In either case, this is followed by: for k, v in F.items(): od[k] = v
'''
if
len
(
args
)
>
2
:
raise
TypeError
(
'
update() takes at most 2 positional
'
'
arguments (%d given)
'
%
(
len
(
args
),))
elif
not
args
:
raise
TypeError
(
'
update() takes at least 1 argument (0 given)
'
)
self
=
args
[
0
]
# Make progressively weaker assumptions about "other"
other
=
()
if
len
(
args
)
==
2
:
other
=
args
[
1
]
if
isinstance
(
other
,
dict
):
for
key
in
other
:
self
[
key
]
=
other
[
key
]
elif
hasattr
(
other
,
'
keys
'
):
for
key
in
other
.
keys
():
self
[
key
]
=
other
[
key
]
else
:
for
key
,
value
in
other
:
self
[
key
]
=
value
for
key
,
value
in
kwds
.
items
():
self
[
key
]
=
value
__update
=
update
# let subclasses override update without breaking __init__
__marker
=
object
()
def
pop
(
self
,
key
,
default
=
__marker
):
'''
od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
If key is not found, d is returned if given, otherwise KeyError is raised.
'''
if
key
in
self
:
result
=
self
[
key
]
del
self
[
key
]
return
result
if
default
is
self
.
__marker
:
raise
KeyError
(
key
)
return
default
def
setdefault
(
self
,
key
,
default
=
None
):
'
od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od
'
if
key
in
self
:
return
self
[
key
]
self
[
key
]
=
default
return
default
def
__repr__
(
self
,
_repr_running
=
{}):
'
od.__repr__() <==> repr(od)
'
call_key
=
id
(
self
),
_get_ident
()
if
call_key
in
_repr_running
:
return
'
...
'
_repr_running
[
call_key
]
=
1
try
:
if
not
self
:
return
'
%s()
'
%
(
self
.
__class__
.
__name__
,)
return
'
%s(%r)
'
%
(
self
.
__class__
.
__name__
,
self
.
items
())
finally
:
del
_repr_running
[
call_key
]
def
__reduce__
(
self
):
'
Return state information for pickling
'
items
=
[[
k
,
self
[
k
]]
for
k
in
self
]
inst_dict
=
vars
(
self
).
copy
()
for
k
in
vars
(
OrderedDict
()):
inst_dict
.
pop
(
k
,
None
)
if
inst_dict
:
return
(
self
.
__class__
,
(
items
,),
inst_dict
)
return
self
.
__class__
,
(
items
,)
def
copy
(
self
):
'
od.copy() -> a shallow copy of od
'
return
self
.
__class__
(
self
)
@classmethod
def
fromkeys
(
cls
,
iterable
,
value
=
None
):
'''
OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
and values equal to v (which defaults to None).
'''
d
=
cls
()
for
key
in
iterable
:
d
[
key
]
=
value
return
d
def
__eq__
(
self
,
other
):
'''
od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
while comparison to a regular mapping is order-insensitive.
'''
if
isinstance
(
other
,
OrderedDict
):
return
len
(
self
)
==
len
(
other
)
and
self
.
items
()
==
other
.
items
()
return
dict
.
__eq__
(
self
,
other
)
def
__ne__
(
self
,
other
):
return
not
self
==
other
# -- the following methods are only used in Python 2.7 --
def
viewkeys
(
self
):
"
od.viewkeys() -> a set-like object providing a view on od
'
s keys
"
return
KeysView
(
self
)
def
viewvalues
(
self
):
"
od.viewvalues() -> an object providing a view on od
'
s values
"
return
ValuesView
(
self
)
def
viewitems
(
self
):
"
od.viewitems() -> a set-like object providing a view on od
'
s items
"
return
ItemsView
(
self
)
This diff is collapsed.
Click to expand it.
lib/spack/spack/config.py
+
22
−
44
View file @
d95e7ecf
...
@@ -84,10 +84,9 @@
...
@@ -84,10 +84,9 @@
import
re
import
re
import
inspect
import
inspect
import
ConfigParser
as
cp
import
ConfigParser
as
cp
from
collections
import
OrderedDict
from
external.ordereddict
import
OrderedDict
from
llnl.util.lang
import
memoized
from
llnl.util.lang
import
memoized
import
spack.error
import
spack.error
__all__
=
[
__all__
=
[
...
@@ -222,7 +221,6 @@ class SpackConfigParser(cp.RawConfigParser):
...
@@ -222,7 +221,6 @@ class SpackConfigParser(cp.RawConfigParser):
"""
"""
# Slightly modify Python option expressions to allow leading whitespace
# Slightly modify Python option expressions to allow leading whitespace
OPTCRE
=
re
.
compile
(
r
'
\s*
'
+
cp
.
RawConfigParser
.
OPTCRE
.
pattern
)
OPTCRE
=
re
.
compile
(
r
'
\s*
'
+
cp
.
RawConfigParser
.
OPTCRE
.
pattern
)
OPTCRE_NV
=
re
.
compile
(
r
'
\s*
'
+
cp
.
RawConfigParser
.
OPTCRE_NV
.
pattern
)
def
__init__
(
self
,
file_or_files
):
def
__init__
(
self
,
file_or_files
):
cp
.
RawConfigParser
.
__init__
(
self
,
dict_type
=
OrderedDict
)
cp
.
RawConfigParser
.
__init__
(
self
,
dict_type
=
OrderedDict
)
...
@@ -341,14 +339,13 @@ def write(self, path_or_fp=None):
...
@@ -341,14 +339,13 @@ def write(self, path_or_fp=None):
def
_read
(
self
,
fp
,
fpname
):
def
_read
(
self
,
fp
,
fpname
):
"""
This is a copy of Python 2.7
'
s _read() method, with support for
"""
This is a copy of Python 2.6
'
s _read() method, with support for
continuation lines removed.
continuation lines removed.
"""
"""
cursect
=
None
# None, or a dictionary
cursect
=
None
# None, or a dictionary
optname
=
None
optname
=
None
lineno
=
0
comment
=
0
comment
=
0
e
=
None
# None, or an exception
lineno
=
0
e
=
None
# None, or an exception
while
True
:
while
True
:
line
=
fp
.
readline
()
line
=
fp
.
readline
()
if
not
line
:
if
not
line
:
...
@@ -359,7 +356,6 @@ def _read(self, fp, fpname):
...
@@ -359,7 +356,6 @@ def _read(self, fp, fpname):
(
line
.
split
(
None
,
1
)[
0
].
lower
()
==
'
rem
'
and
line
[
0
]
in
"
rR
"
)):
(
line
.
split
(
None
,
1
)[
0
].
lower
()
==
'
rem
'
and
line
[
0
]
in
"
rR
"
)):
self
.
_sections
[
"
comment-%d
"
%
comment
]
=
line
self
.
_sections
[
"
comment-%d
"
%
comment
]
=
line
comment
+=
1
comment
+=
1
continue
# a section header or option header?
# a section header or option header?
else
:
else
:
# is it a section header?
# is it a section header?
...
@@ -381,27 +377,21 @@ def _read(self, fp, fpname):
...
@@ -381,27 +377,21 @@ def _read(self, fp, fpname):
raise
cp
.
MissingSectionHeaderError
(
fpname
,
lineno
,
line
)
raise
cp
.
MissingSectionHeaderError
(
fpname
,
lineno
,
line
)
# an option line?
# an option line?
else
:
else
:
mo
=
self
.
_optcre
.
match
(
line
)
mo
=
self
.
OPTCRE
.
match
(
line
)
if
mo
:
if
mo
:
optname
,
vi
,
optval
=
mo
.
group
(
'
option
'
,
'
vi
'
,
'
value
'
)
optname
,
vi
,
optval
=
mo
.
group
(
'
option
'
,
'
vi
'
,
'
value
'
)
if
vi
in
(
'
=
'
,
'
:
'
)
and
'
;
'
in
optval
:
# ';' is a comment delimiter only if it follows
# a spacing character
pos
=
optval
.
find
(
'
;
'
)
if
pos
!=
-
1
and
optval
[
pos
-
1
].
isspace
():
optval
=
optval
[:
pos
]
optval
=
optval
.
strip
()
# allow empty values
if
optval
==
'""'
:
optval
=
''
optname
=
self
.
optionxform
(
optname
.
rstrip
())
optname
=
self
.
optionxform
(
optname
.
rstrip
())
# This check is fine because the OPTCRE cannot
cursect
[
optname
]
=
optval
# match if it would set optval to None
if
optval
is
not
None
:
if
vi
in
(
'
=
'
,
'
:
'
)
and
'
;
'
in
optval
:
# ';' is a comment delimiter only if it follows
# a spacing character
pos
=
optval
.
find
(
'
;
'
)
if
pos
!=
-
1
and
optval
[
pos
-
1
].
isspace
():
optval
=
optval
[:
pos
]
optval
=
optval
.
strip
()
# allow empty values
if
optval
==
'""'
:
optval
=
''
cursect
[
optname
]
=
[
optval
]
else
:
# valueless option handling
cursect
[
optname
]
=
optval
else
:
else
:
# a non-fatal parsing error occurred. set up the
# a non-fatal parsing error occurred. set up the
# exception but keep going. the exception will be
# exception but keep going. the exception will be
...
@@ -414,23 +404,13 @@ def _read(self, fp, fpname):
...
@@ -414,23 +404,13 @@ def _read(self, fp, fpname):
if
e
:
if
e
:
raise
e
raise
e
# join the multi-line values collected while reading
all_sections
=
[
self
.
_defaults
]
all_sections
.
extend
(
self
.
_sections
.
values
())
for
options
in
all_sections
:
# skip comments
if
isinstance
(
options
,
basestring
):
continue
for
name
,
val
in
options
.
items
():
if
isinstance
(
val
,
list
):
options
[
name
]
=
'
\n
'
.
join
(
val
)
def
_write
(
self
,
fp
):
def
_write
(
self
,
fp
):
"""
Write an .ini-format representation of the configuration state.
"""
Write an .ini-format representation of the configuration state.
This is taken from the default Python 2.
7
source. It writes 4
This is taken from the default Python 2.
6
source. It writes 4
spaces at the beginning of lines instead of no leading space.
spaces at the beginning of lines instead of no leading space.
"""
"""
if
self
.
_defaults
:
if
self
.
_defaults
:
...
@@ -449,11 +429,9 @@ def _write(self, fp):
...
@@ -449,11 +429,9 @@ def _write(self, fp):
# Allow leading whitespace
# Allow leading whitespace
fp
.
write
(
"
[%s]
\n
"
%
section
)
fp
.
write
(
"
[%s]
\n
"
%
section
)
for
(
key
,
value
)
in
self
.
_sections
[
section
].
items
():
for
(
key
,
value
)
in
self
.
_sections
[
section
].
items
():
if
key
==
"
__name__
"
:
if
key
!=
"
__name__
"
:
continue
fp
.
write
(
"
%s = %s
\n
"
%
if
(
value
is
not
None
)
or
(
self
.
_optcre
==
self
.
OPTCRE
):
(
key
,
str
(
value
).
replace
(
'
\n
'
,
'
\n\t
'
)))
key
=
"
=
"
.
join
((
key
,
str
(
value
).
replace
(
'
\n
'
,
'
\n\t
'
)))
fp
.
write
(
"
%s
\n
"
%
(
key
))
class
SpackConfigurationError
(
spack
.
error
.
SpackError
):
class
SpackConfigurationError
(
spack
.
error
.
SpackError
):
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment