mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Do not write shed_tool_data_table_config in place
This should prevent errors such as:
```
galaxy.util ERROR 2017-11-17 09:20:12,842 Error parsing file /data/users/mvandenb/gx/config/shed_tool_data_table_conf.xml
Traceback (most recent call last):
File "lib/galaxy/util/__init__.py", line 217, in parse_xml
root = tree.parse(fname, parser=ElementTree.XMLParser(target=DoctypeSafeCallbackTarget()))
File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 657, in parse
self._root = parser.close()
File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1654, in close
self._raiseerror(v)
File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1506, in _raiseerror
raise err
ParseError: no element found: line 1, column 0
```
reported in https://github.com/galaxyproject/galaxy/issues/5031.
This commit is contained in:
@@ -21,6 +21,7 @@ import requests
|
||||
from galaxy import util
|
||||
from galaxy.util.dictifiable import Dictifiable
|
||||
from galaxy.util.odict import odict
|
||||
from galaxy.util.renamed_temporary_file import RenamedTemporaryFile
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -186,7 +187,7 @@ class ToolDataTableManager(object):
|
||||
# add new elems
|
||||
out_elems.extend(new_elems)
|
||||
out_path_is_new = not os.path.exists(full_path)
|
||||
with open(full_path, 'wb') as out:
|
||||
with RenamedTemporaryFile(full_path) as out:
|
||||
out.write('<?xml version="1.0"?>\n<tables>\n')
|
||||
for elem in out_elems:
|
||||
out.write(util.xml_to_string(elem, pretty=True))
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
"""Safely write file to temporary file and then move file into place."""
|
||||
# Copied from https://stackoverflow.com/a/12007885.
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
|
||||
class RenamedTemporaryFile(object):
|
||||
"""
|
||||
A temporary file object which will be renamed to the specified
|
||||
path on exit.
|
||||
"""
|
||||
def __init__(self, final_path, **kwargs):
|
||||
tmpfile_dir = kwargs.pop('dir', None)
|
||||
|
||||
# Put temporary file in the same directory as the location for the
|
||||
# final file so that an atomic move into place can occur.
|
||||
|
||||
if tmpfile_dir is None:
|
||||
tmpfile_dir = os.path.dirname(final_path)
|
||||
|
||||
self.tmpfile = tempfile.NamedTemporaryFile(dir=tmpfile_dir, **kwargs)
|
||||
self.final_path = final_path
|
||||
|
||||
def __getattr__(self, attr):
|
||||
"""
|
||||
Delegate attribute access to the underlying temporary file object.
|
||||
"""
|
||||
return getattr(self.tmpfile, attr)
|
||||
|
||||
def __enter__(self):
|
||||
self.tmpfile.__enter__()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
if exc_type is None:
|
||||
self.tmpfile.delete = False
|
||||
result = self.tmpfile.__exit__(exc_type, exc_val, exc_tb)
|
||||
os.rename(self.tmpfile.name, self.final_path)
|
||||
else:
|
||||
result = self.tmpfile.__exit__(exc_type, exc_val, exc_tb)
|
||||
|
||||
return result
|
||||
Reference in New Issue
Block a user