Changeset 3437
- Timestamp:
- 10/06/08 00:24:42 (3 months ago)
- Location:
- pkipplib/trunk
- Files:
-
- 11 modified
-
bin/pksubscribe (modified) (9 diffs)
-
clean.sh (modified) (2 diffs)
-
MANIFEST.in (modified) (1 diff)
-
notifiers/samplenotifier (modified) (4 diffs)
-
pkipplib/__init__.py (modified) (2 diffs)
-
pkipplib/pkipplib.py (modified) (42 diffs)
-
pkipplib/version.py (modified) (2 diffs)
-
README (modified) (8 diffs)
-
setup.py (modified) (2 diffs)
-
tests/printjob.py (modified) (2 diffs)
-
tests/test.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
pkipplib/trunk/bin/pksubscribe
r45 r3437 1 1 #! /usr/bin/env python 2 # -*- coding: UTF-8 -*-2 # -*- coding: utf-8 -*- 3 3 # 4 4 # pkipplib : IPP and CUPS support for Python … … 9 9 # the Free Software Foundation, either version 3 of the License, or 10 10 # (at your option) any later version. 11 # 11 # 12 12 # This program is distributed in the hope that it will be useful, 13 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 15 # GNU General Public License for more details. 16 # 16 # 17 17 # You should have received a copy of the GNU General Public License 18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. … … 28 28 import optparse 29 29 30 from pkipplib import pkipplib 31 32 if __name__ == "__main__" : 30 from pkipplib import pkipplib 31 32 if __name__ == "__main__" : 33 33 try : 34 34 locale.setlocale(locale.LC_ALL, "") … … 40 40 gettext.NullTranslations().install() 41 41 parser = optparse.OptionParser(usage="pksubscribe [options] [subscriptions ids]") 42 parser.add_option("-v", "--version", 43 action="store_true", 42 parser.add_option("-v", "--version", 43 action="store_true", 44 44 dest="version", 45 45 help=_("show pksubscribe's version number and exit.")) 46 parser.add_option("-c", "--cups", 47 default="http://localhost:631", 46 parser.add_option("-c", "--cups", 47 default="http://localhost:631", 48 48 dest="cups", 49 49 help=_("the CUPS server to connect to. Defaults to http://localhost:631")) 50 parser.add_option("-d", "--debug", 51 action="store_true", 50 parser.add_option("-d", "--debug", 51 action="store_true", 52 52 dest="debug", 53 53 help=_("activate debug mode.")) 54 parser.add_option("-X", "--delete", 55 action="store_true", 54 parser.add_option("-X", "--delete", 55 action="store_true", 56 56 dest="delete", 57 57 help=_("deletes subscriptions.")) 58 parser.add_option("-p", "--printer", 58 parser.add_option("-p", "--printer", 59 59 dest="printer", 60 60 help=_("the printer's name for a printer subscription.")) 61 parser.add_option("-j", "--job", 62 type="int", 61 parser.add_option("-j", "--job", 62 type="int", 63 63 dest="job", 64 64 help=_("the job's id for a job subscripition.")) 65 parser.add_option("-r", "--recipient", 65 parser.add_option("-r", "--recipient", 66 66 dest="recipient", 67 67 help=_("the recipient's uri.")) 68 parser.add_option("-C", "--charset", 68 parser.add_option("-C", "--charset", 69 69 dest="charset", 70 70 help=_("the charset to use in notifications sent for this subscription.")) 71 parser.add_option("-L", "--language", 71 parser.add_option("-L", "--language", 72 72 dest="language", 73 73 help=_("the language to use in notifications sent for this subscription.")) 74 parser.add_option("-u", "--userdata", 74 parser.add_option("-u", "--userdata", 75 75 dest="userdata", 76 76 help=_("the user's data to use in notifications for this subscription.")) 77 parser.add_option("-U", "--username", 77 parser.add_option("-U", "--username", 78 78 dest="username", 79 79 help=_("the user's name to use when connecting to the CUPS server.")) 80 parser.add_option("-W", "--password", 80 parser.add_option("-W", "--password", 81 81 dest="password", 82 82 help=_("the user's password to use when connecting to the CUPS server.")) 83 parser.add_option("-E", "--events", 83 parser.add_option("-E", "--events", 84 84 dest="events", 85 85 help=_("a comma separated list of events to subscribe to.")) 86 parser.add_option("-P", "--pullmethod", 86 parser.add_option("-P", "--pullmethod", 87 87 dest="pullmethod", 88 88 help=_("the optional pull method's name.")) … … 91 91 dest="duration", 92 92 help=_("the duration of the subscription.")) 93 parser.add_option("-I", "--interval", 93 parser.add_option("-I", "--interval", 94 94 type="int", 95 95 dest="interval", 96 96 help=_("the time interval of the subscription.")) 97 97 98 98 (options, arguments) = parser.parse_args() 99 99 if options.version : … … 102 102 if not options.events and not options.delete : 103 103 sys.stderr.write(_("You MUST pass a list of events to subscribe to.\n")) 104 elif not options.recipient and not options.delete : 104 elif not options.recipient and not options.delete : 105 105 sys.stderr.write(_("You MUST pass a recipient for the subscription.\n")) 106 elif options.delete and not arguments : 106 elif options.delete and not arguments : 107 107 sys.stderr.write(_("You MUST pass a subscriptions ids at the end of your command line.\n")) 108 else : 108 else : 109 109 cups = pkipplib.CUPS(options.cups, 110 110 options.username, … … 112 112 debug=options.debug) 113 113 baseurl = options.cups.replace("http://", "ipp://") 114 if baseurl.endswith(":631") : 114 if baseurl.endswith(":631") : 115 115 baseurl = baseurl[:-4] 116 116 if options.printer : 117 117 url = "%s/printers/%s" % (baseurl, options.printer) 118 elif options.job : 118 elif options.job : 119 119 url = "%s/jobs/%i" % (baseurl, options.job) 120 else : 120 else : 121 121 url = baseurl 122 if not options.delete : 122 if not options.delete : 123 123 answer = cups.createSubscription(url, 124 124 [e.strip() for e in options.events.split(",")], … … 131 131 timeinterval=options.interval, 132 132 jobid=options.job) 133 try : 133 try : 134 134 subscriptionid = answer.subscription["notify-subscription-id"][0][1] 135 135 except KeyError : 136 136 sys.stderr.write("%s\n" % answer.operation["status-message"][0][1]) 137 else : 137 else : 138 138 print _("Subscription %i registered.") % subscriptionid 139 else : 139 else : 140 140 for subid in [int(arg) for arg in arguments] : 141 141 answer = cups.cancelSubscription(url, subid, options.job) … … 143 143 try : 144 144 error = answer.operation["status-message"][0][1] 145 except KeyError : 145 except KeyError : 146 146 print _("Subscription %i cancelled.") % subid 147 147 else : 148 148 sys.stderr.write("%s\n" % error) 149 else : 149 else : 150 150 sys.stderr.write(_("Incorrect answer (None)\n")) 151 151 -
pkipplib/trunk/clean.sh
r45 r3437 1 #! /bin/sh1 y#! /bin/sh 2 2 # 3 3 # pkipplib : IPP support for Python … … 8 8 # the Free Software Foundation, either version 3 of the License, or 9 9 # (at your option) any later version. 10 # 10 # 11 11 # This program is distributed in the hope that it will be useful, 12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 14 # GNU General Public License for more details. 15 # 15 # 16 16 # You should have received a copy of the GNU General Public License 17 17 # along with this program. If not, see <http://www.gnu.org/licenses/>. -
pkipplib/trunk/MANIFEST.in
r36 r3437 1 include README COPYING NEWS MANIFEST.in clean.sh bin/pksubscribe1 yinclude README COPYING NEWS MANIFEST.in clean.sh bin/pksubscribe 2 2 recursive-include notifiers * -
pkipplib/trunk/notifiers/samplenotifier
r45 r3437 1 1 #! /usr/bin/env python 2 # -*- coding: UTF-8 -*-2 # -*- coding: utf-8 -*- 3 3 # 4 4 # pkipplib : IPP and CUPS support for Python … … 9 9 # the Free Software Foundation, either version 3 of the License, or 10 10 # (at your option) any later version. 11 # 11 # 12 12 # This program is distributed in the hope that it will be useful, 13 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 15 # GNU General Public License for more details. 16 # 16 # 17 17 # You should have received a copy of the GNU General Public License 18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. … … 38 38 # First thing we do is put stdin in non-blocking mode. 39 39 fd = sys.stdin.fileno() 40 fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, 40 fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, 41 41 fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK) 42 42 43 43 # then we read the notification CUPS sent us to our stdin 44 44 notification = pkipplib.IPPRequest(sys.stdin.read()) 45 45 46 46 # now we parse it 47 47 notification.parse() 48 48 49 49 # then we act one way or another, depending on the event received. 50 50 event = notification.event_notification["notify-subscribed-event"][0][1] … … 53 53 if event.endswith("-added") : 54 54 action = "add" 55 else : 55 else : 56 56 action = "delete" 57 57 os.system('/usr/bin/pkprinters --%s "%s"' % (action, printername)) -
pkipplib/trunk/pkipplib/__init__.py
r45 r3437 1 # -*- coding: UTF-8 -*-1 # -*- coding: utf-8 -*- 2 2 # 3 3 # pkipplib : IPP and CUPS support for Python … … 8 8 # the Free Software Foundation, either version 3 of the License, or 9 9 # (at your option) any later version. 10 # 10 # 11 11 # This program is distributed in the hope that it will be useful, 12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 14 # GNU General Public License for more details. 15 # 15 # 16 16 # You should have received a copy of the GNU General Public License 17 17 # along with this program. If not, see <http://www.gnu.org/licenses/>. -
pkipplib/trunk/pkipplib/pkipplib.py
r45 r3437 1 1 #! /usr/bin/env python 2 # -*- coding: UTF-8 -*-2 # -*- coding: utf-8 -*- 3 3 # 4 4 # pkipplib : IPP and CUPS support for Python … … 9 9 # the Free Software Foundation, either version 3 of the License, or 10 10 # (at your option) any later version. 11 # 11 # 12 12 # This program is distributed in the hope that it will be useful, 13 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 15 # GNU General Public License for more details. 16 # 16 # 17 17 # You should have received a copy of the GNU General Public License 18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. … … 238 238 IPP_MULTIPLE_JOBS_NOT_SUPPORTED = 0x0509 239 239 IPP_PRINTER_IS_DEACTIVATED = 0x50a 240 240 241 241 CUPS_PRINTER_LOCAL = 0x0000 242 242 CUPS_PRINTER_CLASS = 0x0001 … … 265 265 CUPS_PRINTER_COMMANDS = 0x8000 266 266 CUPS_PRINTER_OPTIONS = 0xe6ff 267 268 267 268 269 269 class IPPError(Exception) : 270 270 """An exception for IPP related stuff.""" … … 282 282 self.request = request 283 283 self.name = name 284 284 285 285 def __setitem__(self, key, value) : 286 286 """Appends the value to the real attribute.""" … … 293 293 attribute[j][1].append(value) 294 294 return 295 attribute.append((key, [value])) 296 295 attribute.append((key, [value])) 296 297 297 def __getitem__(self, key) : 298 298 """Returns an attribute's value.""" … … 307 307 if answer : 308 308 return answer 309 raise KeyError, key 310 309 raise KeyError, key 310 311 311 class IPPRequest : 312 312 """A class for IPP requests.""" 313 313 attributes_types = ("operation", "job", "printer", "unsupported", \ 314 314 "subscription", "event_notification") 315 def __init__(self, data="", version=IPP_VERSION, 315 def __init__(self, data="", version=IPP_VERSION, 316 316 operation_id=None, \ 317 317 request_id=None, \ 318 318 debug=False) : 319 319 """Initializes an IPP Message object. 320 320 321 321 Parameters : 322 322 323 323 data : the complete IPP Message's content. 324 324 debug : a boolean value to output debug info on stderr. … … 327 327 self._data = data 328 328 self.parsed = False 329 329 330 330 # Initializes message 331 self.setVersion(version) 331 self.setVersion(version) 332 332 self.setOperationId(operation_id) 333 333 self.setRequestId(request_id) 334 334 self.data = "" 335 335 336 336 for attrtype in self.attributes_types : 337 337 setattr(self, "_%s_attributes" % attrtype, [[]]) 338 339 # Initialize tags 338 339 # Initialize tags 340 340 self.tags = [ None ] * 256 # by default all tags reserved 341 341 342 342 # Delimiter tags 343 343 self.tags[0x01] = "operation-attributes-tag" … … 348 348 self.tags[0x06] = "subscription-attributes-tag" 349 349 self.tags[0x07] = "event_notification-attributes-tag" 350 350 351 351 # out of band values 352 352 self.tags[0x10] = "unsupported" … … 357 357 self.tags[0x16] = "delete-attribute" 358 358 self.tags[0x17] = "admin-define" 359 359 360 360 # integer values 361 361 self.tags[0x20] = "generic-integer" … … 363 363 self.tags[0x22] = "boolean" 364 364 self.tags[0x23] = "enum" 365 365 366 366 # octetString 367 367 self.tags[0x30] = "octetString-with-an-unspecified-format" … … 373 373 self.tags[0x36] = "nameWithLanguage" 374 374 self.tags[0x37] = "endCollection" 375 375 376 376 # character strings 377 377 self.tags[0x40] = "generic-character-string" … … 385 385 self.tags[0x49] = "mimeMediaType" 386 386 self.tags[0x4a] = "memberAttrName" 387 387 388 388 # Reverse mapping to generate IPP messages 389 389 self.tagvalues = {} … … 392 392 if value is not None : 393 393 self.tagvalues[value] = i 394 395 def __getattr__(self, name) : 394 395 def __getattr__(self, name) : 396 396 """Fakes attribute access.""" 397 397 if name in self.attributes_types : … … 399 399 else : 400 400 raise AttributeError, name 401 402 def __str__(self) : 401 402 def __str__(self) : 403 403 """Returns the parsed IPP message in a readable form.""" 404 404 if not self.parsed : … … 414 414 for (name, value) in attribute : 415 415 mybuffer.append(" %s : %s" % (name, value)) 416 if self.data : 416 if self.data : 417 417 mybuffer.append("IPP datas : %s" % repr(self.data)) 418 418 return "\n".join(mybuffer) 419 420 def logDebug(self, msg) : 419 420 def logDebug(self, msg) : 421 421 """Prints a debug message.""" 422 422 if self.debug : 423 423 sys.stderr.write("%s\n" % msg) 424 424 sys.stderr.flush() 425 425 426 426 def setVersion(self, version) : 427 427 """Sets the request's operation id.""" … … 432 432 if len(version) == 2 : # 2-tuple 433 433 self.version = version 434 else : 434 else : 435 435 try : 436 436 self.version = [int(p) for p in str(float(version)).split(".")] 437 437 except : 438 438 self.version = [int(p) for p in IPP_VERSION.split(".")] 439 440 def setOperationId(self, opid) : 439 440 def setOperationId(self, opid) : 441 441 """Sets the request's operation id.""" 442 442 self.operation_id = opid 443 444 def setRequestId(self, reqid) : 443 444 def setRequestId(self, reqid) : 445 445 """Sets the request's request id.""" 446 446 self.request_id = reqid 447 448 def dump(self) : 447 448 def dump(self) : 449 449 """Generates an IPP Message. 450 450 451 451 Returns the message as a string of text. 452 """ 452 """ 453 453 mybuffer = [] 454 454 if None not in (self.version, self.operation_id) : … … 468 468 mybuffer.append(attrname) 469 469 nameprinted = 1 470 else : 470 else : 471 471 mybuffer.append(pack(">H", 0)) 472 472 if vtype in ("integer", "enum") : … … 476 476 mybuffer.append(pack(">H", 1)) 477 477 mybuffer.append(chr(val)) 478 else : 478 else : 479 479 mybuffer.append(pack(">H", len(val))) 480 480 mybuffer.append(val) 481 481 mybuffer.append(chr(self.tagvalues["end-of-attributes-tag"])) 482 mybuffer.append(self.data) 482 mybuffer.append(self.data) 483 483 return "".join(mybuffer) 484 484 485 485 def parse(self) : 486 486 """Parses an IPP Request. 487 487 488 488 NB : Only a subset of RFC2910 is implemented. 489 489 """ 490 490 self._curname = None 491 491 self._curattributes = None 492 492 493 493 try : 494 494 self.setVersion((ord(self._data[0]), ord(self._data[1]))) … … 509 509 self.position -= 1 510 510 continue 511 oldtag = tag 511 oldtag = tag 512 512 tag = ord(self._data[self.position]) 513 513 if tag == oldtag : … … 515 515 except IndexError : 516 516 raise IPPError, "Unexpected end of IPP message." 517 518 self.data = self._data[self.position+1:] 517 518 self.data = self._data[self.position+1:] 519 519 self.parsed = True 520 521 def parseTag(self) : 520 521 def parseTag(self) : 522 522 """Extracts information from an IPP tag.""" 523 523 pos = self.position … … 528 528 if not namelength : 529 529 name = self._curname 530 else : 530 else :
