forked from LSSTDESC/ceci
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/LSSTDESC/ceci
- Loading branch information
Showing
3 changed files
with
231 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
from contextlib import contextmanager | ||
import sys | ||
|
||
@contextmanager | ||
def extra_paths(paths, start=True): | ||
# allow passing a single path or | ||
# a list of them | ||
if isinstance(paths, str): | ||
paths = paths.split() | ||
|
||
# On enter, add paths to sys.path, | ||
# either the start or the end depending | ||
# on the start argument | ||
for path in paths: | ||
if start: | ||
sys.path.insert(0, path) | ||
else: | ||
sys.path.append(path) | ||
|
||
# Return control to caller | ||
try: | ||
yield | ||
# On exit, remove the paths | ||
finally: | ||
for path in paths: | ||
try: | ||
if start: | ||
sys.path.remove(path) | ||
else: | ||
remove_last(sys.path, path) | ||
# If e.g. user has already done this | ||
# manually for some reason then just | ||
# skip | ||
except ValueError: | ||
pass | ||
|
||
def remove_last(lst, item): | ||
""" | ||
Removes (in-place) the last instance of item from the list lst. | ||
Raises ValueError if item is not in list | ||
Parameters | ||
---------- | ||
lst: List | ||
A list of anything | ||
item: object | ||
Item to be removed | ||
Returns | ||
------- | ||
None | ||
""" | ||
tmp = lst[::-1] | ||
tmp.remove(item) | ||
lst[:] = tmp[::-1] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import sys | ||
from ceci.main import run | ||
from ceci.utils import remove_last, extra_paths | ||
import pytest | ||
|
||
def test_remove_item(): | ||
l = list('abcdea') | ||
remove_last(l, 'a') | ||
assert l == list('abcde') | ||
|
||
l = list('abcde') | ||
remove_last(l, 'b') | ||
assert l == list('acde') | ||
|
||
with pytest.raises(ValueError): | ||
remove_last([1, 2 ,3], 4) | ||
|
||
class MyError(Exception): | ||
pass | ||
|
||
def test_extra_paths(): | ||
p = 'xxx111yyy222' | ||
orig_path = sys.path[:] | ||
|
||
# check path is put in | ||
with extra_paths(p): | ||
assert sys.path[0] == p | ||
|
||
# check everything back to normal | ||
# after with statement | ||
assert p not in sys.path | ||
assert sys.path == orig_path | ||
|
||
# check that an exception does not interfere | ||
# with this | ||
try: | ||
with extra_paths(p): | ||
assert sys.path[0] == p | ||
raise MyError("x") | ||
except MyError: | ||
pass | ||
|
||
assert p not in sys.path | ||
assert sys.path == orig_path | ||
|
||
|
||
# now putting the item at the end not the start | ||
with extra_paths(p, start=False): | ||
assert sys.path[-1] == p | ||
|
||
assert p not in sys.path | ||
assert sys.path == orig_path | ||
|
||
try: | ||
with extra_paths(p, start=False): | ||
assert sys.path[-1] == p | ||
raise MyError("x") | ||
except MyError: | ||
pass | ||
|
||
assert p not in sys.path | ||
assert sys.path == orig_path | ||
|
||
# now agan with a list of paths | ||
p = ['xxx111yyy222', 'aaa222333'] | ||
with extra_paths(p): | ||
assert sys.path[0] == p[1] | ||
assert sys.path[1] == p[0] | ||
|
||
for p1 in p: | ||
assert p1 not in sys.path | ||
assert sys.path == orig_path | ||
|
||
try: | ||
with extra_paths(p): | ||
assert sys.path[0] == p[1] | ||
assert sys.path[1] == p[0] | ||
raise MyError("x") | ||
except MyError: | ||
pass | ||
|
||
for p1 in p: | ||
assert p1 not in sys.path | ||
assert sys.path == orig_path | ||
|
||
|
||
|
||
# now agan with a list of paths, at the end | ||
p = ['xxx111yyy222', 'aaa222333'] | ||
with extra_paths(p, start=False): | ||
assert sys.path[-1] == p[1] | ||
assert sys.path[-2] == p[0] | ||
|
||
for p1 in p: | ||
assert p1 not in sys.path | ||
assert sys.path == orig_path | ||
|
||
try: | ||
with extra_paths(p, start=False): | ||
assert sys.path[-1] == p[1] | ||
assert sys.path[-2] == p[0] | ||
raise MyError("x") | ||
except MyError: | ||
pass | ||
|
||
assert p not in sys.path | ||
assert sys.path == orig_path | ||
|
||
# check that if the user removes the path | ||
# themselves then it is okay | ||
p = ['xxx111yyy222', 'aaa222333'] | ||
with extra_paths(p, start=True): | ||
sys.path.remove('xxx111yyy222') | ||
|
||
assert sys.path == orig_path | ||
|
||
# check only one copy is removed | ||
sys.path.append("aaa") | ||
tmp_paths = sys.path[:] | ||
p = "aaa" | ||
with extra_paths(p, start=True): | ||
pass | ||
|
||
assert sys.path == tmp_paths | ||
|
||
with extra_paths(p, start=False): | ||
pass |