1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
# This file is part of the Frescobaldi project, http://www.frescobaldi.org/
#
# Copyright (c) 2008 - 2014 by Wilbert Berendsen
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# See http://www.gnu.org/licenses/ for more information.
"""
Finds out which files are created by running the engraver.
"""
import itertools
import glob
import os
import app
import documentinfo
import jobmanager
import plugin
import util
def results(document):
return Results.instance(document)
# Set the basenames of the resulting documents to expect when a job starts
@app.jobStarted.connect
def _init_basenames(document, job):
results(document).saveDocumentInfo(job.start_time())
class Results(plugin.DocumentPlugin):
"""Can be queried to get the files created by running the engraver (LilyPond) on our document."""
def __init__(self, document):
self._jobfile = None
self._basenames = None
self._start_time = 0.0
document.saved.connect(self.forgetDocumentInfo)
def saveDocumentInfo(self, start_time):
"""Takes over some vital information from a DocumentInfo instance.
This method is called as soon as a job is started.
The file a job is run on and the basenames expected to be created are saved.
When the user saves a Document after a Job has run, this information is 'forgotten' again.
Otherwise the results of a Job would not be seen if the user starts a Job and then
saves the Document while the job is still running. The Job uses the scratcharea if the
document was modified but saving it would result in DocumentInfo.jobinfo()[0] pointing
to the real document instead.
"""
info = documentinfo.info(self.document())
self._start_time = start_time
self._jobfile = info.jobinfo()[0]
self._basenames = info.basenames()
def forgetDocumentInfo(self):
"""Called when the user saves a Document.
'Forgets' the basenames and job filename if set, but only if no job is currently running.
"""
if not jobmanager.is_running(self.document()):
self._start_time = 0.0
self._jobfile = None
self._basenames = None
def jobfile(self):
"""Returns the file that is currently being, or will be, engraved."""
if self._jobfile is None:
return documentinfo.info(self.document()).jobinfo()[0]
return self._jobfile
def basenames(self):
"""Returns the list of basenames the last or running Job is expected to create."""
if self._basenames is None:
return documentinfo.info(self.document()).basenames()
return self._basenames
def files(self, extension = '*', newer = True):
"""Returns a list of existing files matching our basenames and the given extension.
First the files basename + extension are returned,
then basename + '-[0-9]+' + extension,
then basename + '-.+' + extension.
If newer is True (the default), only files that are newer than the jobfile() are returned.
"""
jobfile = self.jobfile()
if jobfile:
files = util.files(self.basenames(), extension)
if newer:
try:
return util.newer_files(files, os.path.getmtime(jobfile))
except (OSError, IOError):
pass
return list(files)
return []
def files_lastjob(self, extension = '*'):
"""Like files(), but only returns files that were created by the last job.
If no job has yet run on the document, returns the same files as the
files_uptodate() method.
"""
if self._start_time:
files = util.files(self.basenames(), extension)
try:
files = util.newer_files(files, self._start_time)
except (OSError, IOError):
pass
return files
else:
return self.files(extension)
def is_newer(self, filename):
"""Return True if the given (generated) file is newer than the jobfile().
Also return True if the mtime of one of the files could not be read.
"""
jobfile = self.jobfile()
if jobfile:
try:
return os.path.getmtime(filename) > os.path.getmtime(jobfile)
except (OSError, IOError):
pass
return True
def currentDirectory(self):
"""Returns the directory the document resides in.
Returns the temporary directory if that was used last.
"""
directory = os.path.dirname(self.jobfile())
if os.path.isdir(directory):
return directory
|