source: server/lib/gutenbach/server/printer.py @ ffbe41d

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

Clean up core ipp code a bit

  • Property mode set to 100644
File size: 7.5 KB
Line 
1from . import InvalidJobException, InvalidPrinterStateException
2from . import Job
3import gutenbach.ipp as ipp
4import logging
5import time
6
7# initialize logger
8logger = logging.getLogger(__name__)
9
10class GutenbachPrinter(object):
11
12    # for IPP
13    attributes = [
14        "printer-uri-supported",
15        "uri-authentication-supported",
16        "uri-security-supported",
17        "printer-name",
18        "printer-state",
19        "printer-state-reasons",
20        "ipp-versions-supported",
21        "operations-supported",
22        "charset-configured",
23        "charset-supported",
24        "natural-language-configured",
25        "generated-natural-language-supported",
26        "document-format-default",
27        "document-format-supported",
28        "printer-is-accepting-jobs",
29        "queued-job-count",
30        "pdl-override-supported",
31        "printer-up-time",
32        "compression-supported",
33        "multiple-operation-time-out",
34        "multiple-document-jobs-supported",
35    ]
36
37    operations = [
38        "print-job",
39        "complete-job",
40        "start-job",
41        "get-job",
42        "get-jobs",
43    ]
44       
45
46    def __init__(self, name):
47
48        self.name = name
49        self.uri = "ipp://localhost:8000/printers/" + self.name
50        self.time_created = int(time.time())
51        self.state = "idle"
52
53        self.finished_jobs = []
54        self.active_jobs = []
55        self.jobs = {}
56
57        # cups ignores jobs with id 0, so we have to start at 1
58        self._next_jobid = 1 
59
60    def __getattr__(self, attr):
61        try:
62            return self.__getattribute__(attr)
63        except AttributeError:
64            pass
65        return self.__getattribute__(attr.replace("-", "_"))
66
67    def __hasattr__(self, attr):
68        try:
69            getattr(self, attr)
70            return True
71        except AttributeError:
72            return False
73
74    ## Printer attributes
75
76    @property
77    def printer_uri_supported(self):
78        return ipp.PrinterUriSupported(self.uri)
79
80    @property
81    def uri_authentication_supported(self):
82        return ipp.UriAuthenticationSupported("none")
83
84    @property
85    def uri_security_supported(self):
86        return ipp.UriSecuritySupported("none")
87
88    @property
89    def printer_name(self):
90        return ipp.PrinterName(self.name)
91
92    @property
93    def printer_state(self):
94        return ipp.PrinterState(ipp.constants.PrinterStates.IDLE)
95
96    @property
97    def printer_state_reasons(self):
98        return ipp.PrinterStateReasons("none")
99
100    @property
101    def ipp_versions_supported(self):
102        return ipp.IppVersionsSupported("1.0", "1.1")
103
104    # XXX: We should query ourself for the supported operations
105    @property
106    def operations_supported(self):
107        return ipp.OperationsSupported(ipp.OperationCodes.GET_JOBS)
108
109    @property
110    def charset_configured(self):
111        return ipp.CharsetConfigured("utf-8")
112
113    @property
114    def charset_supported(self):
115        return ipp.CharsetSupported("utf-8")
116
117    @property
118    def natural_language_configured(self):
119        return ipp.NaturalLanguageConfigured("en-us")
120
121    @property
122    def generated_natural_language_supported(self):
123        return ipp.GeneratedNaturalLanguageSupported("en-us")
124
125    @property
126    def document_format_default(self):
127        return ipp.DocumentFormatDefault("application/octet-stream")
128
129    @property
130    def document_format_supported(self):
131        return ipp.DocumentFormatSupported("application/octet-stream", "audio/mp3")
132
133    @property
134    def printer_is_accepting_jobs(self):
135        return ipp.PrinterIsAcceptingJobs(True)
136
137    @property
138    def queued_job_count(self):
139        return ipp.QueuedJobCount(len(self.active_jobs))
140
141    @property
142    def pdl_override_supported(self):
143        return ipp.PdlOverrideSupported("not-attempted")
144
145    @property
146    def printer_up_time(self):
147        return ipp.PrinterUpTime(int(time.time()) - self.time_created)
148
149    @property
150    def compression_supported(self):
151        return ipp.CompressionSupported("none")
152
153    @property
154    def multiple_operation_time_out(self):
155        return ipp.MultipleOperationTimeOut(240)
156
157    @property
158    def multiple_document_jobs_supported(self):
159        return ipp.MultipleDocumentJobsSupported(False)
160
161    ## Printer operations
162
163    def get_printer_attributes(self, request=None):
164        if request and 'requested-attributes' in request:
165            requested = []
166            for value in request['requested-attributes'].values:
167                if value.value in self.attributes:
168                    requested.append(value.value)
169        else:
170            requested = self.attributes
171           
172        attributes = [getattr(self, attr) for attr in requested]
173        return attributes
174
175    def create_job(self, request):
176        operation = request.attribute_groups[0]
177        kwargs = {}
178       
179        # requesting username
180        if 'requesting-user-name' in operation:
181            username_attr = operation['requesting-user-name']
182            username = username_attr.values[0].value
183            if username_attr != ipp.RequestingUserName(username):
184                raise ipp.errors.ClientErrorBadRequest(str(username_attr))
185            kwargs['creator'] = username
186
187        # job name
188        if 'job-name' in operation:
189            job_name_attr = operation['job-name']
190            job_name = job_name_attr.values[0].value
191            if job_name_attr != ipp.JobName(job_name):
192                raise ipp.errors.ClientErrorBadRequest(str(job_name_attr))
193            kwargs['name'] = job_name
194
195        # job size
196        if 'job-k-octets' in operation:
197            job_k_octets_attr = operation['job-k-octets']
198            job_k_octets = job_k_octets_attr.values[0].value
199            if job_k_octets_attr != ipp.JobKOctets(job_k_octets):
200                raise ipp.errors.ClientErrorBadRequest(str(job_k_octets_attr))
201            kwargs['size'] = job_k_octets
202
203        job_id = self._next_jobid
204        self._next_jobid += 1
205       
206        job = Job(job_id, self, **kwargs)
207        self.jobs[job_id] = job
208        self.active_jobs.append(job_id)
209        return job
210
211    def send_document(self, jobid, document):
212        job = self.jobs[jobid]
213        if job.status != ipp.JobStates.HELD:
214            raise InvalidPrinterStateException(
215                "Invalid job state: %d" % job.status)
216        job.document = document
217        logger.debug("document for job %d is '%s'" % (jobid, job.document.name))
218        job.status = ipp.JobStates.PENDING
219
220    def print_job(self, job):
221        pass
222
223    def complete_job(self, jobid):
224        job = self.jobs[self.active_jobs.pop(0)]
225        self.finished_jobs.append(job)
226        job.finish()
227        return job.jid
228
229    def start_job(self, jobid):
230        job = self.jobs[self.active_jobs[0]]
231        if job.status != ipp.JobStates.PENDING:
232            raise InvalidPrinterStateException(
233                "Invalid job state: %s" % job.status)
234        job.play()
235
236    @property
237    def next_job(self):
238        if len(self.active_jobs) == 0:
239            job = None
240        else:
241            job = self.active_jobs[0]
242        return job
243
244    def stop(self):
245        if len(self.active_jobs) == 0:
246            return
247        job = self.jobs[self.active_jobs[0]]
248        if job.player is not None:
249            logger.info("stopping printer %s" % self.name)
250            job.player.terminate()
251
252    def get_job(self, jobid):
253        if jobid not in self.jobs:
254            raise InvalidJobException(jobid)
255        return self.jobs[jobid]
256
257    def get_jobs(self):
258        print self.active_jobs
259        jobs = [self.jobs[job_id] for job_id in self.active_jobs]
260        return jobs
261
262    # def __repr__(self):
263    #     return str(self)
264
265    # def __str__(self):
266    #     return "<Printer '%s'>" % self.name
Note: See TracBrowser for help on using the repository browser.