def fetch_jobs(self, refresh_all): if not self.process_pending_events: # Skip this call. We'll get called again soon. return True user = cups.getUser() try: cups.setUser(self.user) c = cups.Connection(host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: self.emit('cups-connection-error') self.fetch_jobs_timer = None cups.setUser(user) return False limit = 1 r = [ "job-id", "job-printer-uri", "job-state", "job-originating-user-name", "job-k-octets", "job-name", "time-at-creation" ] try: fetched = c.getJobs(which_jobs=self.which_jobs, my_jobs=self.my_jobs, first_job_id=self.fetch_first_job_id, limit=limit, requested_attributes=r) except cups.IPPError as e: (e, m) = e.args self.emit('cups-ipp-error', e, m) self.fetch_jobs_timer = None cups.setUser(user) return False cups.setUser(user) got = len(fetched) debugprint("Got %s jobs, asked for %s" % (got, limit)) jobs = self.jobs.copy() jobids = list(fetched.keys()) jobids.sort() if got > 0: last_jobid = jobids[got - 1] if last_jobid < self.fetch_first_job_id: last_jobid = self.fetch_first_job_id + limit - 1 debugprint("Unexpected job IDs returned: %s" % repr(jobids)) debugprint("That's not what we asked for!") else: last_jobid = self.fetch_first_job_id + limit - 1 for jobid in range(self.fetch_first_job_id, last_jobid + 1): try: job = fetched[jobid] if self.specific_dests is not None: uri = job.get('job-printer-uri', '/') i = uri.rfind('/') printer = uri[i + 1:] if printer not in self.specific_dests: raise KeyError if jobid in jobs: n = 'job-event' else: n = 'job-added' jobs[jobid] = job self.emit(n, jobid, '', {}, job.copy()) except KeyError: # No job by that ID. if jobid in jobs: del jobs[jobid] self.emit('job-removed', jobid, '', {}) jobids = list(jobs.keys()) jobids.sort() if got < limit: trim = False for i in range(len(jobids)): jobid = jobids[i] if not trim and jobid > last_jobid: trim = True if trim: del jobs[jobid] self.emit('job-removed', jobid, '', {}) self.update_jobs(jobs) self.jobs = jobs if got < limit: # That's all. Don't run this timer again. self.fetch_jobs_timer = None return False # Remember where we got up to and run this timer again. next = jobid + 1 while not refresh_all and next in self.jobs: next += 1 self.fetch_first_job_id = next return True
def send_to_printer(filename, printername): conn = cups.Connection() conn.printFile(printer, filename, filename, {}) logging.debug('Printing') while (bool(conn.getJobs(which_jobs='not-completed'))): time.sleep(1) # Wait for completion
def printTestPage(self): ''' print a test page ''' conn = cups.Connection(self.server) conn.printTestPage(self.name)
def __init__(self, printer_name): self.printer_conn = cups.Connection() self.code39 = barcode.get_barcode_class('code39') self.printer = printer_name
def printFile(fileToPrint): conn = cups.Connection() printers = conn.getPrinters() printer_name = printers.keys()[0] conn.printFile(printer_name, fileToPrint, "", {})
def execute(self, entry): """Print a print job. This is the core of PrintingService. entry (QueueEntry): the entry containing the operation to perform. """ # TODO: automatically re-enqueue in case of a recoverable # error. printjob_id = entry.item.printjob_id with SessionGen() as session: # Obtain print job. printjob = PrintJob.get_from_id(printjob_id, session) if printjob is None: raise ValueError("Print job %d not found in the database." % printjob_id) user = printjob.participation.user contest = printjob.participation.contest timezone = get_timezone(user, contest) timestr = str( printjob.timestamp.replace( tzinfo=utc).astimezone(timezone).replace(tzinfo=None)) filename = printjob.filename # Check if it's ready to be printed. if printjob.done: logger.info("Print job %d was already sent to the printer.", printjob_id) directory = tempfile.mkdtemp(dir=config.temp_dir) logger.info("Preparing print job in directory %s", directory) # Take the base name just to be sure. relname = "source_" + os.path.basename(filename) source = os.path.join(directory, relname) with open(source, "wb") as file_: self.file_cacher.get_file_to_fobj(printjob.digest, file_) if filename.endswith(".pdf") and config.pdf_printing_allowed: source_pdf = source else: # Convert text to ps. source_ps = os.path.join(directory, "source.ps") cmd = [ "a2ps", source, "--delegate=no", "--output=" + source_ps, "--medium=%s" % config.paper_size.capitalize(), "--portrait", "--columns=1", "--rows=1", "--pages=1-%d" % (config.max_pages_per_job), "--header=", "--footer=", "--left-footer=", "--right-footer=", "--center-title=" + filename, "--left-title=" + timestr ] ret = subprocess.call(cmd, cwd=directory) if ret != 0: raise Exception( "Failed to convert text file to ps with command: %s" "(error %d)" % (pretty_print_cmdline(cmd), ret)) if not os.path.exists(source_ps): logger.warning("Unable to convert from text to ps.") printjob.done = True printjob.status = [N_("Invalid file")] session.commit() rmtree(directory) return # Convert ps to pdf source_pdf = os.path.join(directory, "source.pdf") cmd = [ "ps2pdf", "-sPAPERSIZE=%s" % config.paper_size.lower(), source_ps ] ret = subprocess.call(cmd, cwd=directory) if ret != 0: raise Exception( "Failed to convert ps file to pdf with command: %s" "(error %d)" % (pretty_print_cmdline(cmd), ret)) # Find out number of pages with open(source_pdf, "rb") as file_: pdfreader = PdfFileReader(file_) page_count = pdfreader.getNumPages() logger.info("Preparing %d page(s) (plus the title page)", page_count) if page_count > config.max_pages_per_job: logger.info("Too many pages.") printjob.done = True printjob.status = [N_("Print job has too many pages")] session.commit() rmtree(directory) return # Add the title page title_tex = os.path.join(directory, "title_page.tex") title_pdf = os.path.join(directory, "title_page.pdf") with open(title_tex, "wb") as f: f.write( self.jinja2_env.get_template("title_page.tex").render( user=user, filename=filename, timestr=timestr, page_count=page_count, paper_size=config.paper_size)) cmd = ["pdflatex", "-interaction", "nonstopmode", title_tex] ret = subprocess.call(cmd, cwd=directory) if ret != 0: raise Exception("Failed to create title page with command: %s" "(error %d)" % (pretty_print_cmdline(cmd), ret)) pdfmerger = PdfFileMerger() with open(title_pdf, "rb") as file_: pdfmerger.append(file_) with open(source_pdf, "rb") as file_: pdfmerger.append(file_) result = os.path.join(directory, "document.pdf") with open(result, "wb") as file_: pdfmerger.write(file_) try: printer_connection = cups.Connection() printer_connection.printFile(config.printer, result, "Printout %d" % printjob_id, {}) except cups.IPPError as error: logger.error("Unable to print: `%s'.", error) else: printjob.done = True printjob.status = [N_("Sent to printer")] session.commit() finally: rmtree(directory)
def generate(self): if not self.host: conn = cups.Connection() else: if not self.port: self.port = 631 conn = cups.Connection(self.host, self.port) printers = conn.getPrinters() for p, v in printers.items(): if v['printer-is-shared']: #pprint.pprint(v) # v contains keys: device-uri printer-info printer-is-shared printer-location printer-make-and-model printer-state printer-state-message printer-state-reasons printer-type printer-uri-supported attrs = conn.getPrinterAttributes(p) #pprint.pprint(attrs) uri = urlparse.urlparse(v['printer-uri-supported']) output = '_cups._sub._ipp._tcp\t\tIN\tPTR\t' + p + '._ipp._tcp\n' output += '_universal._sub._ipp._tcp\tIN\tPTR\t' + p + '._ipp._tcp\n' output += '_cups._sub._ipps._tcp\t\tIN\tPTR\t' + p + '._ipp._tcp\n' output += '_universal._sub._ipps._tcp\tIN\tPTR\t' + p + '._ipp._tcp\n' output += p + '._ipp._tcp\t\tIN\tSRV\t0 0 631 printserver\n' output += p + '._ipp._tcp\t\tIN\tTXT\t(' output += ' "txtvers=1"' output += ' "qtotal=1"' output += ' "rp=printers/' + p + '"' output += ' "adminurl=http://' + self.host + ':631/printers/' + p + '"' output += ' "ty=' + v['printer-info'] + '"' #s=v['printer-info'] #product = s[s.find("(")+1:s.find(")")] #output += ' "product=(' + product + ')"' output += ' "product=(GPL Ghostscript)"' output += ' "note=' + v['printer-location'] + '"' output += ' "transparent=t" "copies=t" "duplex=t" "color=f"' output += ' "pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png,image/urf"' output += ' "URF=W8,SRGB24,CP1,RS600" )\n\n' print output tree = ElementTree() tree.parse( StringIO( XML_TEMPLATE.replace('\n', '').replace('\r', '').replace('\t', ''))) name = tree.find('name') name.text = 'AirPrint %s @ %%h' % (p) service = tree.find('service') port = service.find('port') port_no = None if hasattr(uri, 'port'): port_no = uri.port if not port_no: port_no = self.port if not port_no: port_no = cups.getPort() port.text = '%d' % port_no if hasattr(uri, 'path'): rp = uri.path else: rp = uri[2] re_match = re.match(r'^//(.*):(\d+)(/.*)', rp) if re_match: rp = re_match.group(3) #Remove leading slashes from path #TODO XXX FIXME I'm worried this will match broken urlparse #results as well (for instance if they don't include a port) #the xml would be malform'd either way rp = re.sub(r'^/+', '', rp) path = Element('txt-record') path.text = 'rp=%s' % (rp) service.append(path) desc = Element('txt-record') desc.text = 'note=%s' % (v['printer-info']) service.append(desc) product = Element('txt-record') product.text = 'product=(GPL Ghostscript)' service.append(product) state = Element('txt-record') state.text = 'printer-state=%s' % (v['printer-state']) service.append(state) ptype = Element('txt-record') ptype.text = 'printer-type=%s' % (hex(v['printer-type'])) service.append(ptype) pdl = Element('txt-record') fmts = [] defer = [] for a in attrs['document-format-supported']: if a in DOCUMENT_TYPES: if DOCUMENT_TYPES[a]: fmts.append(a) else: defer.append(a) if 'image/urf' not in fmts: sys.stderr.write( 'image/urf is not in mime types, %s may not be available on ios6 (see https://github.com/tjfontaine/airprint-generate/issues/5)%s' % (p, os.linesep)) fmts = ','.join(fmts + defer) # sys.stderr.write('formats %s' % (fmts)) dropped = [] # TODO XXX FIXME all fields should be checked for 255 limit while len('pdl=%s' % (fmts)) >= 255: (fmts, drop) = fmts.rsplit(',', 1) dropped.append(drop) if len(dropped) and self.verbose: sys.stderr.write('%s Losing support for: %s%s' % (p, ','.join(dropped), os.linesep)) pdl.text = 'pdl=%s' % (fmts) service.append(pdl) if self.adminurl: admin = Element('txt-record') admin.text = 'adminurl=%s' % (v['printer-uri-supported']) service.append(admin) fname = '%s%s.service' % (self.prefix, p) if self.directory: fname = os.path.join(self.directory, fname) #f = open(fname, 'w') #if etree: # tree.write(f, pretty_print=True, xml_declaration=True, encoding="UTF-8") #else: # xmlstr = tostring(tree.getroot()) # doc = parseString(xmlstr) # dt= minidom.getDOMImplementation('').createDocumentType('service-group', None, 'avahi-service.dtd') # doc.insertBefore(dt, doc.documentElement) # doc.writexml(f) #f.close() if self.verbose: sys.stderr.write('Created: %s%s' % (fname, os.linesep))
def getCapabilities(self, gcpid, cupsprintername, overrideoptionsstring): """Gets capabilities of printer and maps them against list Args: gcpid: printer id from google cupsprintername: name of the printer in cups overrideoptionsstring: override for print job Returns: List of capabilities """ overrideoptions = overrideoptionsstring.split(' ') import cups connection = cups.Connection() cupsprinters = connection.getPrinters() capabilities = {"capabilities": []} overridecapabilities = {} for optiontext in overrideoptions: if '=' in optiontext: optionparts = optiontext.split('=') option = optionparts[0] value = optionparts[1] overridecapabilities[option] = value attrs = cups.PPD(connection.getPPD(cupsprintername)).attributes for attr in attrs: if attr.name.startswith('DefaultGCP_'): # gcp setting, reverse back to GCP capability gcpname = None hashname = attr.name.replace('DefaultGCP_', '') # find item name from hashes details = self.getPrinterDetails(gcpid) fulldetails = details['printers'][0] gcpoption = None for capability in fulldetails['capabilities']: if hashname == hashlib.sha256( self.sanitizeText( capability['name'])).hexdigest()[:7]: gcpname = capability['name'] for option in capability['options']: if attr.value == hashlib.sha256( self.sanitizeText( option['name'])).hexdigest()[:7]: gcpoption = option['name'] break for overridecapability in overridecapabilities: if 'Default' + overridecapability == attr.name: selectedoption = overridecapabilities[ overridecapability] for option in capability['options']: if selectedoption == hashlib.sha256( self.sanitizeText(option['name']) ).hexdigest()[:7]: gcpoption = option['name'] break break break # hardcoded to feature type temporarily if gcpname != None and gcpoption != None: capabilities['capabilities'].append({ 'type': 'Feature', 'name': gcpname, 'options': [{ 'name': gcpoption }] }) return capabilities
def test_printers(): global printerItem, requestors # test cups connection connection = cups.Connection() cupsprinters = connection.getPrinters() # total printer totalPrinters = 0 for requestor in requestors: totalPrinters += len(requestor.printers) fullprinters = printerItem.getPrinters(True) assert 'fulldetails' in fullprinters[0] printers = printerItem.getPrinters() assert 'fulldetails' not in printers[0] import re assert len(printers) == totalPrinters for printer in printers: # name assert isinstance(printer['name'], unicode) assert len(printer['name']) > 0 # account assert isinstance(printer['account'], str) assert len(printer['account']) > 0 # id assert isinstance(printer['id'], unicode) assert len(printer['id']) > 0 # test encoding and decoding printer details to/from uri uritest = re.compile("cloudprint://(.*)/" + urllib.quote(printer['account'])) uri = printerItem.printerNameToUri(printer['account'], printer['name']) assert isinstance(uri, str) assert len(uri) > 0 assert uritest.match(uri) != None printername, account = printerItem.parseURI(uri) assert isinstance(printername, str) assert urllib.unquote(printername) == printer['name'] assert isinstance(account, str) assert urllib.unquote(account) == printer['account'] printerId, requestor = printerItem.getPrinterIDByURI(uri) assert isinstance(printerId, unicode) assert isinstance(requestor, MockRequestor) # test add printer to cups assert printerItem.addPrinter(printername, uri, connection, 'testppd.ppd') != None testprintername = printerItem.sanitizePrinterName(printername) # test printer actually added to cups cupsPrinters = connection.getPrinters() found = False for cupsPrinter in cupsPrinters: if (cupsPrinters[cupsPrinter]['printer-info'] == testprintername): found = True break assert found == True # get details about printer printerItem.requestor = requestor printerdetails = printerItem.getPrinterDetails(printer['id']) assert printerdetails != None assert printerdetails['printers'][0] != None assert 'capabilities' in printerdetails['printers'][0] assert isinstance(printerdetails['printers'][0]['capabilities'], list) # test submitting job assert printerItem.submitJob(printerId, 'pdf', 'testfiles/Test Page.pdf', 'Test Page', testprintername) == True assert printerItem.submitJob(printerId, 'pdf', 'testfiles/Test Page Doesnt Exist.pdf', 'Test Page', testprintername) == False # png assert printerItem.submitJob(printerId, 'png', 'testfiles/Test Page.png', 'Test Page', testprintername) == True assert printerItem.submitJob(printerId, 'png', 'testfiles/Test Page Doesnt Exist.png', 'Test Page', testprintername) == False # ps assert printerItem.submitJob(printerId, 'ps', 'testfiles/Test Page.ps', 'Test Page', testprintername) == False assert printerItem.submitJob(printerId, 'ps', 'testfiles/Test Page Doesnt Exist.ps', 'Test Page', testprintername) == False # test failure of print job assert printerItem.submitJob(printerId, 'pdf', 'testfiles/Test Page.pdf', 'FAIL PAGE', testprintername) == False # delete test printer connection.deletePrinter(testprintername)
def __init__(self, user): self.cups = cups.Connection() self.attr = 'requesting-user-name-allowed' self.user = user.lower() self.refresh()
def NewPrinter (self, status, name, mfg, mdl, des, cmd): if name.find("/") >= 0: # name is a URI, no queue was generated, because no suitable # driver was found title = _("Missing printer driver") devid = "MFG:%s;MDL:%s;DES:%s;CMD:%s;" % (mfg, mdl, des, cmd) if (mfg and mdl) or des: if (mfg and mdl): device = "%s %s" % (mfg, mdl) else: device = des text = _("No printer driver for %s.") % device else: text = _("No driver for this printer.") n = Notify.Notification.new (title, text, 'printer') if "actions" in Notify.get_server_caps(): n.set_urgency (Notify.Urgency.CRITICAL) n.set_timeout (Notify.EXPIRES_NEVER) n.add_action ("setup-printer", _("Search"), lambda x, y: self.setup_printer (x, y, name, devid)) else: self.setup_printer (None, None, name, devid) else: # name is the name of the queue which hal_lpadmin has set up # automatically. c = cups.Connection () try: printer = c.getPrinters ()[name] except KeyError: return try: filename = c.getPPD (name) except cups.IPPError: return del c # Check for missing packages cups.ppdSetConformance (cups.PPD_CONFORM_RELAXED) ppd = cups.PPD (filename) import os os.unlink (filename) import sys sys.path.append (APPDIR) import cupshelpers (missing_pkgs, missing_exes) = cupshelpers.missingPackagesAndExecutables (ppd) from cupshelpers.ppds import ppdMakeModelSplit (make, model) = ppdMakeModelSplit (printer['printer-make-and-model']) driver = make + " " + model if status < self.STATUS_GENERIC_DRIVER: title = _("Printer added") else: title = _("Missing printer driver") if len (missing_pkgs) > 0: pkgs = reduce (lambda x,y: x + ", " + y, missing_pkgs) title = _("Install printer driver") text = (_("`%s' requires driver installation: %s.") % (name, pkgs)) n = Notify.Notification.new (title, text, 'printer') import installpackage if "actions" in Notify.get_server_caps(): try: self.packagekit = installpackage.PackageKit () n.set_timeout (Notify.EXPIRES_NEVER) n.add_action ("install-driver", _("Install"), lambda x, y: self.install_driver (x, y, missing_pkgs)) except: pass else: try: self.packagekit = installpackage.PackageKit () self.packagekit.InstallPackageName (0, 0, missing_pkgs[0]) except: pass elif status == self.STATUS_SUCCESS: devid = "MFG:%s;MDL:%s;DES:%s;CMD:%s;" % (mfg, mdl, des, cmd) text = _("`%s' is ready for printing.") % name n = Notify.Notification.new (title, text, 'printer') if "actions" in Notify.get_server_caps(): n.set_urgency (Notify.Urgency.NORMAL) n.add_action ("test-page", _("Print test page"), lambda x, y: self.print_test_page (x, y, name)) n.add_action ("configure", _("Configure"), lambda x, y: self.configure (x, y, name)) else: # Model mismatch devid = "MFG:%s;MDL:%s;DES:%s;CMD:%s;" % (mfg, mdl, des, cmd) text = (_("`%s' has been added, using the `%s' driver.") % (name, driver)) n = Notify.Notification.new (title, text, 'printer') if "actions" in Notify.get_server_caps(): n.set_urgency (Notify.Urgency.CRITICAL) n.add_action ("test-page", _("Print test page"), lambda x, y: self.print_test_page (x, y, name, devid)) n.add_action ("find-driver", _("Find driver"), lambda x, y: self.find_driver (x, y, name, devid)) n.set_timeout (Notify.EXPIRES_NEVER) else: self.configure (None, None, name) self.timeout_ready () n.show () self.notification = n
def getServerSettings(): # Fail if auth required. cups.setPasswordCB(lambda x: '') cups.setServer('') c = cups.Connection() return c.adminGetServerSettings()
def __init__(self): self.con = cups.Connection() self.printer = self.con.getDefault() pass
def TakePictures(): global imagecounter global imagefolder global Numeral global Message global screen global background global pygame global ImageShowed global CountDownPhoto global BackgroundColor global Printing global PhotosPerCart global TotalImageCount input(pygame.event.get()) CountDownPhoto = "1 of 3" filename1 = CapturePicture() CountDownPhoto = "2 of 3" filename2 = CapturePicture() CountDownPhoto = "Last one!" filename3 = CapturePicture() CountDownPhoto = "" Message = "Saving..." UpdateDisplay() image1 = PIL.Image.open(filename1) image2 = PIL.Image.open(filename2) image3 = PIL.Image.open(filename3) TotalImageCount = TotalImageCount + 1 bgimage.paste(image1, (625, 30)) bgimage.paste(image2, (625, 410)) bgimage.paste(image3, (55, 410)) # Create the final filename ts = time.time() Final_Image_Name = os.path.join(imagefolder, "Final_" + str(TotalImageCount)+"_"+str(ts) + ".jpg") # Save it to the usb drive bgimage.save(Final_Image_Name) # Save a temp file, its faster to print from the pi than usb bgimage.save('/home/pi/Desktop/tempprint.jpg') ShowPicture('/home/pi/Desktop/tempprint.jpg',3) bgimage2 = bgimage.rotate(90) bgimage2.save('/home/pi/Desktop/tempprint.jpg') ImageShowed = False Message = "Press the button to print" UpdateDisplay() time.sleep(1) Message = "" UpdateDisplay() Printing = False WaitForPrintingEvent() Numeral = "" Message = "" print(Printing) if Printing: if (TotalImageCount <= PhotosPerCart): if os.path.isfile('/home/pi/Desktop/tempprint.jpg'): # Open a connection to cups conn = cups.Connection() # get a list of printers printers = conn.getPrinters() if len(printers.keys()) == 0: Message = "Printer not available" Numeral = "" UpdateDisplay() time.sleep(1) return # select printer 0 printer_name = printers.keys()[0] Message = "Printing in progress..." UpdateDisplay() time.sleep(1) # print the buffer file printqueuelength = len(conn.getJobs()) if printqueuelength > 1: ShowPicture('/home/pi/Desktop/tempprint.jpg',3) conn.enablePrinter(printer_name) Message = "Impression impossible" UpdateDisplay() time.sleep(1) else: conn.printFile(printer_name, '/home/pi/Desktop/tempprint.jpg', "PhotoBooth", {}) time.sleep(40) else: Message = "We will send you your photos" Numeral = "" UpdateDisplay() time.sleep(1) Message = "" Numeral = "" ImageShowed = False UpdateDisplay() time.sleep(1)
def haveDefaultPrinter(): r = True conn = cups.Connection() if conn.getDefault() == None: r = False return (r)
def generate(self): collected_printers = list() # Collect shared printers from CUPS if applicable if self.usecups: if self.verbose: sys.stderr.write('Collecting shared printers from CUPS%s' % os.linesep) if not self.host: conn = cups.Connection() else: if not self.port: self.port = 631 conn = cups.Connection(self.host, self.port) printers = conn.getPrinters() for p, v in printers.items(): if v['printer-is-shared']: if self.verbose: pprint.pprint(v) attrs = conn.getPrinterAttributes(p) uri = urlparse.urlparse(v['printer-uri-supported']) port_no = None if hasattr(uri, 'port'): port_no = uri.port if not port_no: port_no = self.port if not port_no: port_no = cups.getPort() if hasattr(uri, 'path'): rp = uri.path else: rp = uri[2] re_match = re.match(r'^//(.*):(\d+)(/.*)', rp) if re_match: rp = re_match.group(3) #Remove leading slashes from path #TODO XXX FIXME I'm worried this will match broken urlparse #results as well (for instance if they don't include a port) #the xml would be malform'd either way rp = re.sub(r'^/+', '', rp) pdl = Element('txt-record') fmts = [] defer = [] for a in attrs['document-format-supported']: if a in DOCUMENT_TYPES: if DOCUMENT_TYPES[a]: fmts.append(a) else: defer.append(a) if 'image/urf' not in fmts: sys.stderr.write( 'image/urf is not in mime types, %s may not be available on ios6 (see https://github.com/tjfontaine/airprint-generate/issues/5)%s' % (p, os.linesep)) fmts = ','.join(fmts + defer) dropped = [] # TODO XXX FIXME all fields should be checked for 255 limit while len('pdl=%s' % (fmts)) >= 255: (fmts, drop) = fmts.rsplit(',', 1) dropped.append(drop) if len(dropped) and self.verbose: sys.stderr.write('%s Losing support for: %s%s' % (p, ','.join(dropped), os.linesep)) collected_printers.append({ 'SOURCE': 'CUPS', 'name': p, 'host': None, # Could/should use self.host, but would break old behaviour 'address': None, 'port': port_no, 'domain': 'local', 'txt': { 'rp': rp, 'note': v['printer-location'], 'product': '(GPL Ghostscript)', 'ty': v['printer-make-and-model'], 'printer-state': v['printer-state'], 'printer-type': hex(v['printer-type']), 'adminurl': v['printer-uri-supported'], 'pdl': fmts, } }) # Collect networked printers using DNS-SD if applicable if (self.useavahi): if self.verbose: sys.stderr.write( 'Collecting networked printers using DNS-SD%s' % os.linesep) finder = avahisearch.AvahiPrinterFinder(verbose=self.verbose) for p in finder.Search(): p['SOURCE'] = 'DNS-SD' collected_printers.append(p) # Produce a .service file for each printer found for p in collected_printers: self.produce_settings_file(p)
class MainGui: def __init__(self): self.my_filetypes = [("Text Format", '.txt'), ('All files', '.*')] self.root = tk.Tk() # Main window and configs. self.root.configure(background="#E8E0E0") self.mainFrame = tk.Frame(self.root, width=680, height=600) self.mainFrame.grid(row=1, column=1, padx=50, pady=30) self.root.title("Raschio Office Word 2019") self.mainFrame.columnconfigure(0, weight=10) # Makes frame that holds self.texter. self.mainFrame.rowconfigure(0, weight=10) self.mainFrame.grid_propagate(False) self.texter = tk.Text(self.mainFrame, font="Times 14 bold") # Self.texter and configs. self.texter.grid(row=0, column=0, sticky="nsew") self.texter.bind('<KeyRelease>', self.get_text) # Keybinds. self.texter.bind('<Control-s>', self.saver) self.texter.bind('<Control-S>', self.super_saver) self.texter.bind("<Control-o>", self.openner) self.texter.bind("<Control-p>", self.printer) self.menu = tk.Menu(self.root, activeborderwidth=3, font="Times") # Menu. self.menu.add_command(label="Save", command=self.saver) self.menu.add_command(label="Save as...", command=self.super_saver) self.menu.add_command(label="Open", command=self.openner) self.menu.add_command(label="Help", command=self.YOU_DUMMY) self.menu.add_command(label="Print", command=self.printer) self.root.config(menu=self.menu) # Adding menu to window. self.scroll = tk.Scrollbar(self.mainFrame) # Creating the Scrollbar. self.scroll.grid(row=0, column=1, sticky="nes") self.scroll.config(command=self.texter.yview) # Attaching scroll to texter. self.texter.config(yscrollcommand=self.scroll.set) self.texter.focus() self.root.mainloop() def get_text(self, *args): self.current_text = self.texter.get("1.0", "end-1c") def saver(self, *args): global filename if filename == "unsaved.txt": filename = filedialog.asksaveasfilename(parent=self.root, initialdir=os.getcwd(), title="Please select a file name for saving:", filetypes=self.my_filetypes) tester = filename.strip() if not (tester[-4] == '.' and tester[-3] == 't' and tester[-2] == 'x' and tester[-1] == 't'): filename = filename + ".txt" self.current_text = self.texter.get("1.0", "end-1c") with open(filename, 'w') as f: f.write(self.current_text) messagebox.showinfo("Information", "Text was succsessfully saved.") def super_saver(self, *args): global filename filename = "unsaved.txt" self.saver() def openner(self, *args): global filename filename = filedialog.askopenfilename(parent=self.root, initialdir=os.getcwd(), title="Please select a file:", filetypes=self.my_filetypes) file_text = str(gettext(filename)) self.texter.delete('1.0', 'end') self.texter.insert("1.0", file_text) def printer(self, *args): global filename file = tempfile.mktemp("asdf.txt") with open(file, "w+") as f: self.current_text = self.texter.get("1.0", "end-1c") f.write(self.current_text) if (operating_system := platform.system()) == "Windows": os.startfile(file, "print") # Makes use of Notepad, since accessing printers is a @%$# on Windows. elif operating_system == "Linux": conn = cups.Connection() printers = conn.getPrinters() printer_name = list(printers.keys())[0] conn.printFile(printer_name, file, filename, {})
class Events: connection = cups.Connection() def __init__(self): self.smb = samba() self.sambastatus = "shared" def shareCups(self, buttonname, printername, parent): if buttonname == "Share": self.connection.setPrinterShared(printername, True) if parent.allowbox.isChecked(): allowedip = str(parent.customedit.text()) allowedip = allowedip.replace("*", "") allowedip = allowedip.replace(" ", "") if allowedip == "...": allowedip = "" self.shareSamba(buttonname, allowedip) else: self.connection.setPrinterShared(printername, False) if self.sambastatus == "shared": self.shareSamba(buttonname, "") def getShared(self): return self.connection.adminGetServerSettings()['_share_printers'] def serversettings(self): settings = self.connection.adminGetServerSettings() rmtad = settings['_remote_admin'] rmtan = settings['_remote_any'] dbg = settings['_debug_logging'] shr = settings['_share_printers'] cnc = settings['_user_cancel_any'] return [int(rmtad), int(rmtan), int(dbg), int(shr), int(cnc)] def applyServerSettings(self, rmtad, rmtan, dbg, shr, cnc): settings = self.connection.adminGetServerSettings() settings["_remote_admin"] = rmtad settings["_remote_any"] = rmtan settings["_debug_logging"] = dbg settings["_share_printers"] = shr settings["_user_cancel_any"] = cnc self.connection.adminSetServerSettings(settings) def shareSamba(self, buttonname, allowed): if buttonname == "Share": self.smb.edit("global", "netbios name", os.getenv("HOSTNAME")) self.smb.edit("global", "printcap name", "cups") self.smb.edit("global", "printing", "cups") self.smb.edit("global", "security", "share") self.smb.edit("global", "guest account", "pnp") self.smb.edit("printers", "hosts allow", str(allowed)) self.smb.edit("printers", "path", "/var/spool/samba") self.smb.edit("printers", "printable", "yes") self.smb.edit("printers", "writable", "no") self.smb.edit("printers", "browseable", "no") self.smb.edit("printers", "guest ok", "yes") self.smb.edit("printers", "create mode", "") self.smb.edit("share", "comment", "Samba - Linux Share") self.smb.edit("share", "path", "/home/shared-folder") self.smb.edit("share", "read only", "no") self.smb.edit("share", "guest ok", "yes") self.smb.edit("print$", "comment", "Printer Drivers") self.smb.edit("print$", "path", "/usr/share/cups/drivers") self.smb.edit("print$", "guest ok", "yes") self.smb.edit("print$", "write list", "root") self.smb.edit("print$", "browsable", "yes") self.sambastatus = "shared" self.smb.writeSections() else: self.smb.edit("global", "hosts allow", "") self.smb.edit("global", "printcap name", "") self.smb.edit("global", "printing", "") self.smb.edit("global", "security", "user") self.smb.edit("global", "guest account", "") self.smb.edit("printers", "path", "/var/spool/samba") self.smb.edit("printers", "printable", "yes") self.smb.edit("printers", "writable", "no") self.smb.edit("printers", "browseable", "no") self.smb.edit("printers", "guest ok", "no") self.smb.edit("printers", "create mode", "0700") self.sambastatus = "notshared" self.smb.writeSections()
def generate(self): if not self.host: conn = cups.Connection() else: if not self.port: self.port = 631 conn = cups.Connection(self.host, self.port) printers = conn.getPrinters() for p, v in printers.items(): if v['printer-is-shared']: attrs = conn.getPrinterAttributes(p) uri = urllib.parse.urlparse(v['printer-uri-supported']) tree = ElementTree() tree.parse( StringIO( XML_TEMPLATE.replace('\n', '').replace('\r', '').replace('\t', ''))) name = tree.find('name') name.text = 'AirPrint %s @ %%h' % (p) service = tree.find('service') port = service.find('port') port_no = None if hasattr(uri, 'port'): port_no = uri.port if not port_no: port_no = self.port if not port_no: port_no = cups.getPort() port.text = '%d' % port_no if hasattr(uri, 'path'): rp = uri.path else: rp = uri[2] re_match = re.match(r'^//(.*):(\d+)(/.*)', rp) if re_match: rp = re_match.group(3) #Remove leading slashes from path #TODO XXX FIXME I'm worried this will match broken urllib.parse #results as well (for instance if they don't include a port) #the xml would be malform'd either way rp = re.sub(r'^/+', '', rp) path = Element('txt-record') path.text = 'rp=%s' % (rp) service.append(path) desc = Element('txt-record') desc.text = 'note=%s' % (v['printer-info']) service.append(desc) product = Element('txt-record') product.text = 'product=(GPL Ghostscript)' service.append(product) state = Element('txt-record') state.text = 'printer-state=%s' % (v['printer-state']) service.append(state) ptype = Element('txt-record') ptype.text = 'printer-type=%s' % (hex(v['printer-type'])) service.append(ptype) pdl = Element('txt-record') fmts = [] defer = [] for a in attrs['document-format-supported']: if a in DOCUMENT_TYPES: if DOCUMENT_TYPES[a]: fmts.append(a) else: defer.append(a) if 'image/urf' not in fmts: sys.stderr.write( 'image/urf is not in mime types, %s may not be available on ios6 (see https://github.com/tjfontaine/airprint-generate/issues/5)%s' % (p, os.linesep)) fmts = ','.join(fmts + defer) dropped = [] # TODO XXX FIXME all fields should be checked for 255 limit while len('pdl=%s' % (fmts)) >= 255: (fmts, drop) = fmts.rsplit(',', 1) dropped.append(drop) if len(dropped) and self.verbose: sys.stderr.write('%s Losing support for: %s%s' % (p, ','.join(dropped), os.linesep)) pdl.text = 'pdl=%s' % (fmts) service.append(pdl) if self.adminurl: admin = Element('txt-record') admin.text = 'adminurl=%s' % (v['printer-uri-supported']) service.append(admin) fname = '%s%s.service' % (self.prefix, p) if self.directory: fname = os.path.join(self.directory, fname) f = open(fname, 'w') if etree: tree.write(f, pretty_print=True, xml_declaration=True, encoding="UTF-8") else: xmlstr = tostring(tree.getroot()) doc = parseString(xmlstr) dt = minidom.getDOMImplementation('').createDocumentType( 'service-group', None, 'avahi-service.dtd') doc.insertBefore(dt, doc.documentElement) doc.writexml(f) f.close() if self.verbose: sys.stderr.write('Created: %s%s' % (fname, os.linesep))
def print_image(self): conn = cups.Connection() conn.printFile(PRINTER, self.filename, 'title', {})
def main(): args = parse_args() if args.syslog_address and not args.daemon: print('syslog_address is only valid in daemon mode') sys.exit(1) # if daemon, log to syslog, otherwise log to stdout if args.daemon: if args.syslog_address: handler = logging.handlers.SysLogHandler( address=args.syslog_address) else: handler = logging.handlers.SysLogHandler() handler.setFormatter( logging.Formatter(fmt='cloudprint.py: %(message)s')) else: handler = logging.StreamHandler(sys.stdout) LOGGER.addHandler(handler) if args.verbose: LOGGER.info('Setting DEBUG-level logging') LOGGER.setLevel(logging.DEBUG) try: import http.client as httpclient except ImportError: import httplib as httpclient httpclient.HTTPConnection.debuglevel = 1 requests_log = logging.getLogger("requests.packages.urllib3") requests_log.setLevel(logging.DEBUG) requests_log.propagate = True auth = CloudPrintAuth(args.authfile) if args.logout: auth.delete() LOGGER.info('logged out') return cups_connection = cups.Connection() cpp = CloudPrintProxy(auth) cpp.sleeptime = POLL_PERIOD if args.fastpoll: cpp.sleeptime = FAST_POLL_PERIOD cpp.include = args.include cpp.exclude = args.exclude cpp.site = args.site printers = list(cups_connection.getPrinters().keys()) if not printers: LOGGER.error('No printers found') return if auth.no_auth(): authed = False for name in printers: try: ppd, description = get_printer_info(cups_connection, name) auth.login(name, description, ppd) authed = True break except (cups.IPPError): LOGGER.error('Unable to login with: ' + name) if not authed: LOGGER.error('Unable to find any valid printer.') sys.exit(-1) else: auth.load() sync_printers(cups_connection, cpp) if args.authonly: sys.exit(0) if args.daemon: try: import daemon import daemon.pidfile except ImportError: print('daemon module required for -d') print('\tyum install python-daemon, or apt-get install ' 'python-daemon, or pip install python-daemon') sys.exit(1) pidfile = daemon.pidfile.TimeoutPIDLockFile( path=os.path.abspath(args.pidfile), timeout=5, ) with daemon.DaemonContext(pidfile=pidfile): process_jobs(cups_connection, cpp) else: process_jobs(cups_connection, cpp)
def TakePictures(): global imagecounter global imagefolder global Numeral global Message global screen global background global pygame global ImageShowed global CountDownPhoto global BackgroundColor global Printing global PhotosPerCart global TotalImageCount GPIO.output(LED_PIN, GPIO.LOW) input(pygame.event.get()) CountDownPhoto = "" filename1 = CapturePicture() CountDownPhoto = "" Message = "BITTE WARTEN..." UpdateDisplay() image1 = PIL.Image.open(filename1) image1.save('/home/pi/Desktop/tempprint.jpg') ShowPicture('/home/pi/Desktop/tempprint.jpg', 8) ImageShowed = False Message = "DRUCKEN?" UpdateDisplay() time.sleep(2) Message = "" UpdateDisplay() Printing = False WaitForPrintingEvent() Numeral = "" Message = "" print(Printing) if Printing: GPIO.output(LED_PIN, GPIO.LOW) if (TotalImageCount <= PhotosPerCart): if os.path.isfile('/home/pi/Desktop/tempprint.jpg'): # Open a connection to cups conn = cups.Connection() # get a list of printers printers = conn.getPrinters() # select printer 0 if printers.keys(): printer_name = printers.keys()[0] Message = "Impression en cours..." UpdateDisplay() time.sleep(1) # print the buffer file printqueuelength = len(conn.getJobs()) if printqueuelength > 1: ShowPicture('/home/pi/Desktop/tempprint.jpg', 3) conn.enablePrinter(printer_name) Message = "Impression impossible" UpdateDisplay() time.sleep(1) else: Message = "No Printer" UpdateDisplay() time.sleep(1) else: conn.printFile(printer_name, '/home/pi/Desktop/tempprint.jpg', "PhotoBooth", {}) time.sleep(40) else: Message = "Nous vous enverrons vos photos" Numeral = "" UpdateDisplay() time.sleep(1) Message = "" Numeral = "" ImageShowed = False UpdateDisplay() time.sleep(1)
def TakePictures( ): #La fonction va passer plusieurs etapes : Afficher des images informatives (faites votre plus beau sourire) + lancer la fonction CapturePicture, ouvrir la photo prise par cette fonction et la coller sur une autre image (le template thematique) et enfin enregistrer l'image finale et proposer une impression de celle-ci global imagecounter global imagefolder #global usbfolder global Numeral global Message global screen global background global pygame global ImageShowed global CountDownPhoto global BackgroundColor global Printing global PhotosPerCart global TotalImageCount input(pygame.event.get()) show_image('images/faites_votre_plus_beau_sourire_rect.png') time.sleep(3) #Temps d'affichage de l'image #CountDownPhoto = "Prennez la pose et souriez !" #ancienne ligne de code : CountDownPhoto = "1/3" filename1 = CapturePicture( ) # La variable filename1 sera egale au resultat obtenu suite au lancement de la fonction CapturePicture, c'est a dire au nom de la photo. #A la suite de cette ligne, les operatons de placement de la photo sur le template + renommage + enregistrement de la photo vont se lancer. La partie impression de la photo est egalement proposee. #CountDownPhoto = "2/3" #filename2 = CapturePicture() #CountDownPhoto = "3/3" #filename3 = CapturePicture() CountDownPhoto = "" Message = "Attendez" UpdateDisplay() image1 = PIL.Image.open(filename1) # On ouvre la photo #image2 = PIL.Image.open(filename2) #image3 = PIL.Image.open(filename3) TotalImageCount = TotalImageCount + 1 bgimage.paste( image1, (40, 40) ) # Puis on place la photo image1 sur le template thematique (1 an Sam). Plus x est petit, plus l'image est sur la gauche ; y petit = image en haut #bgimage.paste(image1, (625, 30)) #bgimage.paste(image2, (625, 410)) #bgimage.paste(image3, (55, 410)) # Create the final filename ts = time.time() Final_Image_Name = os.path.join( imagefolder, "Final_" + str(TotalImageCount) + "_" + str(ts) + ".jpg") # Save it to the usb drive bgimage.save(Final_Image_Name) #Final_Image_Name = os.path.join(usbfolder, "Final_" + str(TotalImageCount)+"_"+str(ts) + ".jpg") # Save it to the usb drive bgimage.save(Final_Image_Name) # Save a temp file, its faster to print from the pi than usb bgimage.save('/home/pi/Desktop/tempprint.jpg') ShowPicture('/home/pi/Desktop/tempprint.jpg', 5) bgimage2 = bgimage.rotate(0) bgimage2.save('/home/pi/Desktop/tempprint.jpg') ImageShowed = False #Apres le "Appuyez pour imprimer", le compteur apparait sur fond blanc. Si "True", ca ne va pas label = myfont.render("Some text!", 10, (255, 255, 0)) #Boucle #countDown = 15 #On place un temps en secondes dans la variable countDown #while countDown > 0: #BackgroundColor = "" #Numeral = "" #Message = "Appuyez sur le bouton pour imprimer... " + str(countDown) #On affiche impression en cours + le compteur countDown #countDown = countDown - 1 #UpdateDisplay() #time.sleep(1) #Fin Boucle #Message = "Appuyez sur le bouton pour imprimer..." Message = "Vous souhaitez imprimer ? Appuyez..." UpdateDisplay() time.sleep(3) UpdateDisplay() Message = "" #UpdateDisplay() Printing = False WaitForPrintingEvent( ) #On lance la fonction. Soit le compte a rebours va jusqu'a la fin, soit un appui est detecte et donc on imprime. Numeral = "" Message = "" print(Printing) if Printing: #Si Printing = TRUE if ( TotalImageCount <= PhotosPerCart ): #Si le total d'images prises est inferieur ou egal au total d'image prevues par photos if os.path.isfile( '/home/pi/Desktop/tempprint.jpg'): #Si le fichier existe # Open a connection to cups conn = cups.Connection() # get a list of printers printers = conn.getPrinters() # select printer 0 printer_name = printers.keys()[0] #Message = "Impression en cours..." UpdateDisplay() time.sleep(1) # print the buffer file printqueuelength = len(conn.getJobs( )) #len() va retourner le nombre d'item dans un objet if printqueuelength > 1: #S'il y a + qu'un seul element dans la file d'attente ShowPicture('/home/pi/Desktop/tempprint.jpg', 5) #Alors on montre la photo conn.enablePrinter(printer_name) Message = "Impression impossible" #Et on afficbhe un message UpdateDisplay() time.sleep(1) #Et on attend une seconde else: #Sinon conn.printFile(printer_name, '/home/pi/Desktop/tempprint.jpg', "PhotoBooth", {}) countDown = 55 #On place un temps en secondes dans la variable countDown le temps que l'impression se termine while countDown > 0: BackgroundColor = "" Numeral = "" Message = "Impression en cours... " + str( countDown ) #On affiche impression en cours + le compteur UpdateDisplay() countDown = countDown - 1 time.sleep(1) else: #Sinon, donc si le total d'images prises est superieur au total d'image prevues par photos Message = "Nous vous enverrons vos photos" Numeral = "" UpdateDisplay() time.sleep(1) Message = "" Numeral = "" ImageShowed = False UpdateDisplay() time.sleep(1)
def _sync_logical_devices(self, devices): """ Synchronize logical devices (since migasfree-server >= 4.13) devices: { "logical": [{}, ...], "default": int } """ logical_devices = {} # key is id field for device in devices['logical']: if 'PRINTER' in device: dev = LogicalDevice(device['PRINTER']) logical_devices[int(dev.logical_id)] = dev try: conn = cups.Connection() except RuntimeError: conn = None if conn: # cups is running printers = conn.getPrinters() for printer in printers: # check if printer is a migasfree printer (by format) if len(printers[printer]['printer-info'].split('__')) == 5: key = int(printers[printer]['printer-info'].split('__')[4]) if key in logical_devices: # relate real devices with logical ones by id logical_devices[key].printer_name = printer logical_devices[key].printer_data = printers[printer] else: try: self._send_message(_('Removing device: %s') % printer) conn.deletePrinter(printer) self.operation_ok() logging.debug('Device removed: %s', printer) except cups.IPPError: _msg = _('Error removing device: %s') % printer self.operation_failed(_msg) logging.error(_msg) self._write_error(_msg) for key in logical_devices: _printer_name = logical_devices[key].name if logical_devices[key].driver is None: _msg = _('Error: no driver defined for device %s. Please, configure feature %s, in the model %s %s, and project %s') % ( _printer_name, logical_devices[key].info.split('__')[2], # feature logical_devices[key].info.split('__')[0], # manufacturer logical_devices[key].info.split('__')[1], # model self.migas_project ) self.operation_failed(_msg) logging.error(_msg) self._write_error(_msg) continue if logical_devices[key].is_changed(): self._send_message(_('Installing device: %s') % _printer_name) if logical_devices[key].install(): self.operation_ok() logging.debug('Device installed: %s', _printer_name) else: _msg = _('Error installing device: %s') % _printer_name self.operation_failed(_msg) logging.error(_msg) self._write_error(_msg) # System default printer if devices['default'] != 0 and devices['default'] in logical_devices: _printer_name = logical_devices[devices['default']].name if LogicalDevice.get_device_id(conn.getDefault()) != devices['default']: try: self._send_message(_('Setting default device: %s') % _printer_name) conn.setDefault(_printer_name) self.operation_ok() except cups.IPPError: _msg = _('Error setting default device: %s') % _printer_name self.operation_failed(_msg) logging.error(_msg) self._write_error(_msg)
def _main(): c = cups.Connection() #printers = getPrinters(c) for device in getDevices(c).values(): print(device.uri, device.id_dict)
def take_picture(self): """Implements the picture taking routine""" # Disable lamp self.gpio.set_output(self.lamp_channel, 0) # Show pose message self.display.clear() self.display.show_message("POSE!\n\nTaking four pictures...") self.display.apply() sleep(2) # Extract display and image sizes size = self.display.get_size() outsize = (int(size[0] / 2), int(size[1] / 2)) # Take pictures filenames = [i for i in range(4)] for x in range(4): # Countdown self.show_counter(self.pose_time) # Try each picture up to 3 times remaining_attempts = 3 while remaining_attempts > 0: remaining_attempts = remaining_attempts - 1 self.display.clear() self.display.show_message("S M I L E !!!\n\n" + str(x + 1) + " of 4") self.display.apply() tic = clock() try: filenames[x] = self.camera.take_picture( "/tmp/photobooth_%02d.jpg" % x) remaining_attempts = 0 except CameraException as e: # On recoverable errors: display message and retry if e.recoverable: if remaining_attempts > 0: self.display.clear() self.display.show_message(e.message) self.display.apply() sleep(5) else: raise CameraException( "Giving up! Please start over!", False) else: raise e # Measure used time and sleep a second if too fast toc = clock() - tic if toc < 1.0: sleep(1.0 - toc) # Show 'Wait' self.display.clear() self.display.show_message("Please wait!\n\nProcessing...") self.display.apply() # Assemble them outfile = self.assemble_pictures(filenames) # Show pictures for 10 seconds conn = cups.Connection() printers = 'Canon' #conn.getPrinters() printer_name = 'Canon' #printers.keys()[0] cups.setUser('pi') conn.printFile(printer_name, outfile, "Photo Booth", {}) self.display.clear() self.display.show_picture(outfile, size, (0, 0)) self.display.apply() sleep(self.display_time) # Reenable lamp self.gpio.set_output(self.lamp_channel, 1)
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. DESCRIPTION This script allows to get relevant information of printers managed by the CUPS printing software. It also allows to list pending printing jobs or list them ALL (together with the finished ones)!. """ import cups import datetime import argparse conn = cups.Connection () # It generates a dictionary with printers and their attirbutes. printers = conn.getPrinters () jobs_selected = '' pending_jobs='not-completed' all_jobs='all' # Function to list printers. def list_printers(): for printer in printers: shared = printers[printer]['printer-is-shared'] ip_addr = printers[printer]['printer-info'] model = printers[printer]['printer-make-and-model'] uri = printers[printer]['device-uri']
except: pass return False def isPrinterKnownToCups(cc,printer_name_startswith): pl = filter(lambda x: x.startswith(printer_name_startswith), cc.getPrinters().keys()) return (len(pl) > 0) def getPrinterPowerStatus(): return GPIO.input(relay_pin) if __name__ == "__main__": GPIO.setup(relay_pin, GPIO.OUT) print "connecting to CUPS..." cc = cups.Connection() last_highest_completed_job_id = 1 seconds_idle = 2*time_needed_to_warm_up_print_pages_in_printer_mem_and_cool_down for printers_name in printers_names: print "isPrinterKnownToCups:", isPrinterKnownToCups(cc,printers_name) print "isPrinterUsbConnected:", isPrinterUsbConnected(printer_usb_name) while True: # jobs_pending = cc.getJobs(my_jobs=False) jobs_pending = [jobid for jobid in cc.getJobs(my_jobs=False).keys() if any([cc.getJobAttributes(jobid, requested_attributes=["printer-uri"])["printer-uri"].endswith(printers_name) for printers_name in printers_names])] printer_idle = len(jobs_pending) == 0 job_ids_completed = [jobid for jobid in cc.getJobs(which_jobs="completed",first_job_id=last_highest_completed_job_id).keys() if any([cc.getJobAttributes(jobid, requested_attributes=["printer-uri"])["printer-uri"].endswith(printers_name) for printers_name in printers_names])] if job_ids_completed: last_highest_completed_job_id = max(job_ids_completed) seconds_idle = time.time() - cc.getJobAttributes(last_highest_completed_job_id,requested_attributes=["time-at-completed"])["time-at-completed"] #print "jobs_pending:", jobs_pending
#!/usr/bin/python import cups import cupshelpers import hotshot import hotshot.stats ppds = cupshelpers.ppds.PPDs(cups.Connection().getPPDs()) prof = hotshot.Profile("a.prof") prof.runcall(lambda: ppds.getPPDNameFromDeviceID('', '', '')) prof.close() stats = hotshot.stats.load("a.prof") stats.sort_stats('time') stats.print_stats(100)
def refresh(self, which_jobs=None, refresh_all=True): debugprint("refresh") self.emit('refresh') if which_jobs is not None: self.which_jobs = which_jobs user = cups.getUser() try: cups.setUser(self.user) c = cups.Connection(host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: GLib.idle_add(self.emit, 'cups-connection-error') cups.setUser(user) return if self.sub_id != -1: try: c.cancelSubscription(self.sub_id) except cups.IPPError as e: (e, m) = e.args GLib.idle_add(lambda e, m: self.emit('cups-ipp-error', e, m), e, m) if self.update_timer: GLib.source_remove(self.update_timer) self.update_timer = None debugprint("Canceled subscription %d" % self.sub_id) try: del self.sub_seq except AttributeError: pass events = [ "printer-added", "printer-modified", "printer-deleted", "printer-state-changed" ] if self.monitor_jobs: events.extend([ "job-created", "job-completed", "job-stopped", "job-state-changed", "job-progress" ]) try: self.sub_id = c.createSubscription("/", events=events) debugprint("Created subscription %d, events=%s" % (self.sub_id, repr(events))) except cups.IPPError as e: (e, m) = e.args GLib.idle_add(lambda e, m: self.emit('cups-ipp-error', e, m), e, m) cups.setUser(user) if self.sub_id != -1: if self.update_timer: GLib.source_remove(self.update_timer) self.update_timer = GLib.timeout_add_seconds( MIN_REFRESH_INTERVAL, self.get_notifications) debugprint("Next notifications fetch in %ds" % MIN_REFRESH_INTERVAL) if self.monitor_jobs: jobs = self.jobs.copy() if self.which_jobs not in ['all', 'completed']: # Filter out completed jobs. filtered = {} for jobid, job in jobs.items(): if job.get('job-state', cups.IPP_JOB_CANCELED) < cups.IPP_JOB_CANCELED: filtered[jobid] = job jobs = filtered self.fetch_first_job_id = 1 if self.fetch_jobs_timer: GLib.source_remove(self.fetch_jobs_timer) self.fetch_jobs_timer = GLib.timeout_add(5, self.fetch_jobs, refresh_all) else: jobs = {} try: r = collect_printer_state_reasons(c, self.ppdcache) self.printer_state_reasons = r dests = c.getPrinters() self.printers = set(dests.keys()) except cups.IPPError as e: (e, m) = e.args GLib.idle_add(lambda e, m: self.emit('cups-ipp-error', e, m), e, m) return except RuntimeError: GLib.idle_add(self.emit, 'cups-connection-error') return if self.specific_dests is not None: for jobid in jobs.keys(): uri = jobs[jobid].get('job-printer-uri', '/') i = uri.rfind('/') printer = uri[i + 1:] if printer not in self.specific_dests: del jobs[jobid] self.set_process_pending(False) for printer in self.printers: GLib.idle_add(lambda x: self.emit('printer-added', x), printer) for jobid, job in jobs.items(): GLib.idle_add( lambda jobid, job: self.emit('job-added', jobid, '', {}, job), jobid, job) self.update_jobs(jobs) self.jobs = jobs self.set_process_pending(True) return False