source: server/lib/gutenbach/server/job.py @ 345c476

no-cups
Last change on this file since 345c476 was 345c476, checked in by Jessica B. Hamrick <jhamrick@…>, 12 years ago

Make status handling better in job.py

  • Property mode set to 100644
File size: 6.6 KB
Line 
1from .errors import InvalidJobStateException, MissingDataException
2from .player import Player
3from gutenbach.ipp import JobStates as States
4import logging
5import os
6
7# initialize logger
8logger = logging.getLogger(__name__)
9
10class GutenbachJob(object):
11
12    def __init__(self, job_id=None, creator=None, name=None,
13                 priority=None, document=None):
14        """Create an empty Gutenbach job.
15
16        """
17
18        self.player = None
19        self.document = None
20
21        self.id = job_id
22        self.creator = creator
23        self.name = name
24        self.priority = priority
25        self._why_done = None
26
27        if document is not None:
28            self.spool(document)
29
30    def __repr__(self):
31        return str(self)
32
33    def __str__(self):
34        return "<Job %d '%s'>" % (self.id, self.name)
35
36    def __cmp__(self, other):
37        return cmp(self.priority, other.priority)
38
39    ######################################################################
40    ###                          Properties                            ###
41    ######################################################################
42
43    @property
44    def id(self):
45        """Unique job identifier.  Should be a positive integer,
46        except when unassigned, when it defaults to -1.
47       
48        """
49        return self._id
50    @id.setter
51    def id(self, val):
52        try:
53            self._id = max(int(val), -1)
54        except TypeError:
55            self._id = -1
56
57    @property
58    def priority(self):
59        return self._priority
60    @priority.setter
61    def priority(self, val):
62        try:
63            self._priority = max(int(val), 1)
64        except TypeError:
65            self._priority = 1
66
67    @property
68    def creator(self):
69        """The user who created the job; analogous to the IPP
70        requesting-user-name.
71
72        """
73        return self._creator
74    @creator.setter
75    def creator(self, val):
76        if val is None:
77            self._creator = ""
78        else:
79            self._creator = str(val)
80
81    @property
82    def name(self):
83        """The job's name.
84
85        """
86        return self._name
87    @name.setter
88    def name(self, val):
89        if val is None:
90            self._name = ""
91        else:
92            self._name = str(val)
93
94    @property
95    def size(self):
96        """The size of the job in bytes.
97
98        """
99        try:
100            size = os.path.getsize(self.document)
101        except:
102            size = 0
103        return size
104
105    @property
106    def is_valid(self):
107        """Whether the job is ready to be manipulated (spooled,
108        played, etc).  Note that playing the job still requires it to
109        be spooled first.
110
111        """
112        return self.id > 0 and \
113               self.priority > 0
114
115    @property
116    def is_ready(self):
117        """Whether the job is ready to be played.
118
119        """
120        return self.is_valid and \
121               self.player is not None and \
122               not self.player.is_playing and \
123               not self._why_done == "cancelled" and \
124               not self._why_done == "aborted"
125
126    @property
127    def is_playing(self):
128        """Whether the job is currently playing (regardless of whether
129        it's paused).
130
131        """
132        return self.is_valid and \
133               self.player is not None and \
134               self.player.is_playing
135
136    @property
137    def is_paused(self):
138        """Whether the job is currently paused.
139
140        """
141        return self.is_valid and \
142               self.player is not None and \
143               self.player.is_paused       
144
145    @property
146    def is_done(self):
147        return (self.is_valid and \
148                self.player is not None and \
149                self.player.is_done) or \
150                (self._why_done == "cancelled" or \
151                 self._why_done == "aborted")
152
153    @property
154    def state(self):
155        if self.is_ready:
156            state = States.PENDING
157        elif self.is_playing and not self.is_paused:
158            state = States.PROCESSING
159        elif self.is_playing and self.is_paused:
160            state = States.STOPPED
161        elif self.is_done and self._why_done == "completed":
162            state = States.COMPLETE
163        elif self.is_done and self._why_done == "cancelled":
164            state = States.CANCELLED
165        elif self.is_done and self._why_done == "aborted":
166            state = States.ABORTED
167        else:
168            state = States.HELD
169        return state
170
171    ######################################################################
172    ###                            Methods                             ###
173    ######################################################################
174
175    def spool(self, document):
176        if not self.is_valid:
177            raise InvalidJobStateException(self.state)
178        self.document = document.name
179        self.player = Player(document)
180        logger.debug("document for job %d is '%s'" % (self.id, self.document))
181
182    def play(self):
183        """Non-blocking play function.  Sets the job state to
184        PROCESSING.
185
186        Raises
187        ------
188        InvalidJobStateException
189            If the job is not ready to be played.
190
191        """
192       
193        # make sure the job is waiting to be played and that it's
194        # valid
195        if not self.is_ready:
196            raise InvalidJobStateException(self.state)
197       
198        # and set the state to processing if we're good to go
199        logger.info("playing job %s" % str(self))
200
201        def _completed():
202            logger.info("completed job %s" % str(self))
203            self._why_done = "completed"
204        self.player.callback = _completed
205        self.player.start()
206
207    def pause(self):
208        """Non-blocking pause function.  Sets the job state to
209        STOPPED.
210
211        """
212       
213        if not self.is_playing:
214            raise InvalidJobStateException(self.state)
215        self.player.mplayer_pause()
216
217    def cancel(self):
218        def _cancelled():
219            logger.info("cancelled job %s" % str(self))
220            self._why_done = "cancelled"
221
222        if self.is_playing:
223            self.player.callback = _cancelled
224            self.player.mplayer_stop()
225        elif self.is_done and not self._why_done == "cancelled":
226            raise InvalidJobStateException(self.state)
227        else:
228            _cancelled()
229
230    def abort(self):
231        def _aborted():
232            logger.info("aborted job %s" % str(self))
233            self._why_done = "aborted"
234
235        if self.is_playing:
236            self.player.callback = _aborted
237            self.player.mplayer_stop()
238        elif self.is_done and not self._why_done == "aborted":
239            raise InvalidJobStateException(self.state)
240        else:
241            _aborted()
242
243
Note: See TracBrowser for help on using the repository browser.