def getTextParams(font_size, letter_spacing, line_height): try: letter_spacing, letter_spacing_unit = parseDimension(letter_spacing) except: msg.error("There's a problem with parsing the 'letter-spacing' property with value '%s'. The format should be an integer or float followed by 'mm' (the only unit supported). For example, '0.3mm' or '-2 mm' should work." % letter_spacing) if letter_spacing_unit == None: letter_spacing_unit = 'mm' try: line_height, line_height_unit = parseDimension(line_height) except: msg.error("There's a problem parsing the 'line-height' property with value '%s'. The format should be an integer or float followed by 'mm' (the only unit supported). For example, '0.3mm' or '-2 mm' should work." % line_height) if line_height_unit == None: line_height_unit = 'mm' try: font_size, font_size_unit = parseDimension(font_size) except: throw("There's a problem parsing the 'font-size'. It's most likely missing. The format should be an integer or float followed by 'mm' (the only unit supported). For example, '0.3mm' or '2 mm' should work. Of course, it needs to be a positive figure.") if font_size_unit == None: font_size_unit = 'mm' return float(font_size), float(letter_spacing), float(line_height)
def goto(self): rel = 0 title = (self.mode==MODE_TEXT) and 'Goto line' or 'Type line number' help = (self.mode==MODE_TEXT) and 'Goto line' or 'Type byte offset' n = messages.Entry(title, help, '', True, False).run() if not n: return if n[0] in ('+', '-'): rel = 1 try: if n[rel:rel+2] == '0x': if rel != 0: n = long(n[0] + str(int(n[1:], 16))) else: n = long(n, 16) else: n = long(n) except ValueError: self.show() msg = 'Goto %s' % (self.mode==MODE_TEXT and 'line' or 'byte') messages.error(msg + '\nInvalid number: %s' % n) return if n == 0: return if self.mode == MODE_TEXT: line = (rel!=0) and (self.line+n) or n self.line = max(1, min(line, self.fc.nlines)) else: pos = (rel!=0) and (self.pos+n) or n self.pos = max(0, min(pos, self.fc.nbytes)) & 0xFFFFFFF0L
def user_has_perm(user, election, perm_n, request=None): if user_can_officiate_election(user): available_perms = Permission.all_codenames() if perm_n not in available_perms: raise PermissionDoesNotExist("You have supplied an invalid Permission codename. Please check the Permission table auth_permission for possible values."); #using filter to avoid dealing with DoesNotExist exception officer = ElectionOfficer.objects.filter(user=user, election=election) if officer: officer = officer[0] #assumption here is that, perm_needed is only present if an election view can be accessed #only by election officers if not officer: messages.error(request, "You are not an election officer of this election. You are not authorized to perform this operation.") return False #raise PermissionDenied() perms = officer.permissions if not perms: return False if perm_n not in perms: return False return True
def execute(self, cmd, tab): selected = [f for f in tab.sorted if f in tab.selections] loop = self.__check_loop(cmd, selected) if cmd[-1] == '&': mode = PowerCLI.RUN_BACKGROUND cmd_orig = cmd[:-1].strip() elif cmd[-1] == '%': mode = PowerCLI.RUN_NEEDCURSESWIN cmd_orig = cmd[:-1].strip() else: mode = PowerCLI.RUN_NORMAL cmd_orig = cmd if loop: for f in selected: try: cmd = self.__replace_cli(cmd_orig, tab, selected, f) # except Exception as msg: # python v2.6+ except Exception, msg: messages.error('Cannot execute PowerCLI command:\n %s\n\n%s' % \ (cmd_orig, str(msg))) st = -1 else: st = self.__run(cmd, tab.path, mode) if st == -1: self.app.lpane.display() self.app.rpane.display() if messages.confirm('Error running PowerCLI', 'Do you want to stop now?') == 1: break tab.selections = []
def election_admin_wrapper(request, election_uuid=None, *args, **kw): election = get_election_by_uuid(election_uuid) user = get_user(request) if 'perm_needed' in checks: perm = Permission.objects.get(codename=checks['perm_needed']) #user is an Election Officer if not user_can_officiate_election(user, election): messages.error(request, "You don't have the required permission (%s) to execute that activity." % (perm)) return HttpResponseRedirect(get_referer_view(request)) #raise PermissionDenied() #user should at least have the required permission if 'perm_needed' in checks: kw['perm_needed'] = checks['perm_needed'] if not user_has_perm(user, election, checks['perm_needed'], request=request): messages.error(request, "You don't have the required permission (%s) to execute that activity." % (perm)) return HttpResponseRedirect(get_referer_view(request)) #raise PermissionDenied() #if the view does not explicitly put any required permission, #then the view must have required an admin user by default #else: # if not user_can_admin_election(user, election): # raise PermissionDenied() # do checks, ok means it's alright to proceed with the action ok = do_election_checks(election, checks, request) if not ok: return HttpResponseRedirect(get_referer_view(request)) return func(request, election, *args, **kw)
def goto(self): rel = 0 title = (self.mode == MODE_TEXT) and 'Goto line' or 'Type line number' help = (self.mode == MODE_TEXT) and 'Goto line' or 'Type byte offset' n = messages.Entry(title, help, '', True, False).run() if not n: return if n[0] in ('+', '-'): rel = 1 try: if n[rel:rel + 2] == '0x': if rel != 0: n = long(n[0] + str(int(n[1:], 16))) else: n = long(n, 16) else: n = long(n) except ValueError: self.show() msg = 'Goto %s' % (self.mode == MODE_TEXT and 'line' or 'byte') messages.error(msg + '\nInvalid number: %s' % n) return if n == 0: return if self.mode == MODE_TEXT: line = (rel != 0) and (self.line + n) or n self.line = max(1, min(line, self.fc.nlines)) else: pos = (rel != 0) and (self.pos + n) or n self.pos = max(0, min(pos, self.fc.nbytes)) & 0xFFFFFFF0L
def __run(self, cmd, path, mode): if mode == PowerCLI.RUN_NEEDCURSESWIN: curses.endwin() try: msg = utils.get_shell_output3('cd "%s" && %s' % (path, cmd)) except KeyboardInterrupt: os.system('reset') msg = 'Stopped by user' st = -1 if msg else 0 elif mode == PowerCLI.RUN_BACKGROUND: utils.run_in_background(cmd, path) st, msg = 0, '' else: # PowerCLI.RUN_NORMAL st, msg = utils.ProcessFunc('Executing PowerCLI', cmd, utils.run_shell, cmd, path, True).run() if st == -1: messages.error('Cannot execute PowerCLI command:\n %s\n\n%s' % \ (cmd, str(msg))) elif st != -100 and msg is not None and msg != '': if self.app.prefs.options['show_output_after_exec']: curses.curs_set(0) if messages.confirm('Executing PowerCLI', 'Show output', 1): lst = [(l, 2) for l in msg.split('\n')] pyview.InternalView('Output of "%s"' % utils.encode(cmd), lst, center=0).run() return st
def dictFromJsonFile(filename, error=True): """ Open a json file and returns its content as a dict """ def checking_for_unique_keys(pairs): """ Check if there are duplicate keys defined; this is useful for any hand-edited file This SO answer was useful here: http://stackoverflow.com/questions/16172011/json-in-python-receive-check-duplicate-key-error """ result = dict() for key, value in pairs: if key in result: msg.error( "duplicate key ('%s') specified in %s" % (key, filename), KeyError) result[key] = value return result try: with open(filename, 'rb') as f: json_data = json.load(f, object_pairs_hook=checking_for_unique_keys) except IOError, OSError: if error == True: msg.error("Couldn't open JSON file: %s" % filename, IOError) else: msg.info("Couldn't open JSON file: %s" % filename, IOError)
def makePngs(): """ Creates a PNG of the board using Inkscape """ # Directory for storing the Gerbers within the build path images_path = os.path.join(config.cfg['base-dir'], config.cfg['locations']['build'], 'images') # Create it if it doesn't exist create_dir(images_path) # create individual PNG files for layers png_dpi = 600 msg.subInfo("Generating PNGs for each layer of the board") command = [ 'inkscape', '--without-gui', '--file=%s' % os.path.join(config.cfg['base-dir'], config.cfg['locations']['build'], config.cfg['name'] + '.svg'), '--export-png=%s' % os.path.join( images_path, config.cfg['name'] + '_rev_' + config.brd['config']['rev'] + '.png'), '--export-dpi=%s' % str(png_dpi), '--export-area-drawing', '--export-background=#FFFFFF' ] try: subp.call(command) except OSError as e: msg.error("Cannot find, or run, Inkscape in commandline mode") return
def getTextParams(font_size, letter_spacing, line_height): try: letter_spacing, letter_spacing_unit = parseDimension(letter_spacing) except: msg.error( "There's a problem with parsing the 'letter-spacing' property with value '%s'. The format should be an integer or float followed by 'mm' (the only unit supported). For example, '0.3mm' or '-2 mm' should work." % letter_spacing) if letter_spacing_unit == None: letter_spacing_unit = 'mm' try: line_height, line_height_unit = parseDimension(line_height) except: msg.error( "There's a problem parsing the 'line-height' property with value '%s'. The format should be an integer or float followed by 'mm' (the only unit supported). For example, '0.3mm' or '-2 mm' should work." % line_height) if line_height_unit == None: line_height_unit = 'mm' try: font_size, font_size_unit = parseDimension(font_size) except: throw( "There's a problem parsing the 'font-size'. It's most likely missing. The format should be an integer or float followed by 'mm' (the only unit supported). For example, '0.3mm' or '2 mm' should work. Of course, it needs to be a positive figure." ) if font_size_unit == None: font_size_unit = 'mm' return float(font_size), float(letter_spacing), float(line_height)
def process_response(self, result): if isinstance(result, tuple): # error st, msg = result if st == -1: self.show_parent() messages.error('Cannot %s\n' % self.action.lower() + msg) return 0
def makePngs(): """ Creates a PNG of the board using Inkscape """ # Directory for storing the Gerbers within the build path images_path = os.path.join(config.cfg['base-dir'], config.cfg['locations']['build'], 'images') # Create it if it doesn't exist create_dir(images_path) # create individual PNG files for layers png_dpi = 600 msg.subInfo("Generating PNGs for each layer of the board") command = ['inkscape', '--without-gui', '--file=%s' % os.path.join(config.cfg['base-dir'], config.cfg['locations']['build'], config.cfg['name'] + '.svg'), '--export-png=%s' % os.path.join(images_path, config.cfg['name'] + '_rev_' + config.brd['config']['rev'] + '.png'), '--export-dpi=%s' % str(png_dpi), '--export-area-drawing', '--export-background=#FFFFFF'] try: subp.call(command) except OSError as e: msg.error("Cannot find, or run, Inkscape in commandline mode") return
def init(tab, filename, vfstype): """initiliaze vfs stuff""" tempdir = files.mkdtemp() # uncompress st, msg = utils.ProcessFunc('Creating vfs', filename, utils.do_uncompress_dir, filename, tab.path, tempdir, True).run() if st == -1: # error app.display() messages.error('Cannot create vfs (opening compressed file)\n' + msg) app.display() return # temppdir deleted by previous call, so we just return elif st == -100: # stopped by user try: files.delete_bulk(tempdir) except OSError: pass return # update vfs vars vpath = tab.path tab.init(tempdir) tab.vfs = vfstype tab.base = tempdir tab.vbase = os.path.join(vpath, filename) + '#vfs' # refresh the other panel app.regenerate()
def __find(self, title): self.pattern = messages.Entry(title, 'Type search string', '', True, False).run() if self.pattern is None or self.pattern == '': return -1 filename = os.path.abspath(self.fc.filename) mode = (self.mode==MODE_TEXT) and 'n' or 'b' try: cmd = '%s -i%c \"%s\" \"%s\"' % (sysprogs['grep'], mode, self.pattern, filename) st, buf = run_shell(encode(cmd), path=u'.', return_output=True) except OSError: self.show() messages.error('Find error: Can\'t open file') return -1 if st == -1: self.show() messages.error('Find error\n' + buf) self.matches = [] return -1 else: try: self.matches = [int(l.split(':')[0]) for l in buf.split('\n') if l] except (ValueError, TypeError): self.matches = [] return 0
def dictFromJsonFile(filename, error=True): """ Open a json file and returns its content as a dict """ def checking_for_unique_keys(pairs): """ Check if there are duplicate keys defined; this is useful for any hand-edited file This SO answer was useful here: http://stackoverflow.com/questions/16172011/json-in-python-receive-check-duplicate-key-error """ result = dict() for key,value in pairs: if key in result: msg.error("duplicate key ('%s') specified in %s" % (key, filename), KeyError) result[key] = value return result try: with open(filename, 'rb') as f: json_data = json.load(f, object_pairs_hook=checking_for_unique_keys) except IOError, OSError: if error == True: msg.error("Couldn't open JSON file: %s" % filename, IOError) else: msg.info("Couldn't open JSON file: %s" % filename, IOError)
def run(self): self.c2p = IPC() self.pid_child = os.fork() if self.pid_child < 0: # error messages.error('Cannot run function') return elif self.pid_child == 0: # child self.child_process(self.func, *self.args) os._exit(0) # parent status = 0 while True: if self.check_finish(): break self.process_result() status = self.check_keys() if status == -100: # stopped by user self.status = status break self.animate_cursor() # finish and return self.c2p.close() try: os.wait() except OSError: pass self.end_gui() if self.status == -100: # stopped by user return -100, 'Stopped by user' try: st, buf = self.ret except: st, buf = 0, None return st, buf
def do_election_checks(election, props, request=None): # frozen if props.has_key('frozen'): frozen = props['frozen'] else: frozen = None # newvoters (open for registration) if props.has_key('newvoters'): newvoters = props['newvoters'] else: newvoters = None # frozen check if frozen != None: if frozen and not election.frozen_at: messages.error(request, "You can only perform this when the election has started.") return False #raise PermissionDenied("You can only perform this when the election has started.") if not frozen and election.frozen_at: messages.error(request, "The election has already started. You are no longer allowed to perform this activity.") return False #raise PermissionDenied("The election has already started. You are no longer allowed to perform this activity.") # open for new voters check if newvoters != None: # where is this can_add_voter? if election.can_add_voters() != newvoters: raise PermissionDenied() #everything alright return True
def process_response(self, result): if isinstance(result, tuple): # error from child self.dlg.ishidden = True self.show_parent() messages.error('Cannot %s\n' % self.action.lower() + self.filename + ': %s (%s)' % result) return 0
def __find(self, title): self.pattern = messages.Entry(title, 'Type search string', '', True, False).run() if self.pattern is None or self.pattern == '': return -1 filename = os.path.abspath(self.fc.filename) mode = (self.mode == MODE_TEXT) and 'n' or 'b' try: cmd = '%s -i%c \"%s\" \"%s\"' % (sysprogs['grep'], mode, self.pattern, filename) st, buf = run_shell(encode(cmd), path=u'.', return_output=True) except OSError: self.show() messages.error('Find error: Can\'t open file') return -1 if st == -1: self.show() messages.error('Find error\n' + buf) self.matches = [] return -1 else: try: self.matches = [ int(l.split(':')[0]) for l in buf.split('\n') if l ] except (ValueError, TypeError): self.matches = [] return 0
def extractDocs(svg_in): """ Extracts the position of the documentation elements and updates the board's json """ # Get copper refdef shape groups from SVG data xpath_expr = '//svg:g[@pcbmode:sheet="documentation"]//svg:g[@pcbmode:type="module-shapes"]' docs = svg_in.findall(xpath_expr, namespaces={ 'pcbmode': config.cfg['ns']['pcbmode'], 'svg': config.cfg['ns']['svg'] }) for doc in docs: doc_key = doc.get('{' + config.cfg['ns']['pcbmode'] + '}doc-key') translate_data = utils.parseTransform(doc.get('transform')) location = translate_data['location'] location.y *= config.cfg['invert-y'] current_location = utils.toPoint( config.brd['documentation'][doc_key]['location']) if current_location != location: config.brd['documentation'][doc_key]['location'] = [ location.x, location.y ] msg.subInfo("Found new location ([%s, %s]) for '%s'" % (location.x, location.y, doc_key)) # Extract drill index location xpath_expr = '//svg:g[@pcbmode:sheet="drills"]//svg:g[@pcbmode:type="drill-index"]' drill_index = svg_in.find(xpath_expr, namespaces={ 'pcbmode': config.cfg['ns']['pcbmode'], 'svg': config.cfg['ns']['svg'] }) transform_dict = utils.parseTransform(drill_index.get('transform')) location = transform_dict['location'] location.y *= config.cfg['invert-y'] # Modify the location in the board's config file. If a # 'drill-index' field doesn't exist, create it drill_index_dict = config.brd.get('drill-index') if drill_index_dict == None: config.brd['drill-index'] = {} config.brd['drill-index']['location'] = [location.x, location.y] # Save board config to file (everything is saved, not only the # component data) filename = os.path.join(config.cfg['locations']['boards'], config.cfg['name'], config.cfg['name'] + '.json') try: with open(filename, 'wb') as f: f.write(json.dumps(config.brd, sort_keys=True, indent=2)) except: msg.error("Cannot save file %s" % filename)
def create(request): if request.method == 'POST': valid, response = Blog.objects.Validate_andCreate_post(request.POST) if not valid: messages.error(error) return redirect('/new') do blabla return redirect('/') Blog.Validate_andCreate_post return render(request, 'blogs_app/create.html')
def run_pre(self): self.p2c = IPC() self.c2p = IPC() self.pid_child = os.fork() if self.pid_child < 0: # error messages.error('Cannot %s\n' % self.action.lower() + 'Can\'t run function') return -1 elif self.pid_child == 0: # child self.child_process() os._exit(0)
def process_result(self): code, buf = self.c2p.receive() if code == 1: self.ret = buf elif code == -1: self.show_parent() messages.error('Cannot %s\n' % self.action.lower() + 'Parent: ' + buf) self.show_parent() self.show_win() else: pass
def __calculate_dims(self): if self.mode == PANE_MODE_HIDDEN: return (self.maxh-2, self.maxw, 0, 0) # h, w, y0, x0 elif self.mode == PANE_MODE_LEFT: return (self.maxh-2, int(self.maxw/2), 1, 0) elif self.mode == PANE_MODE_RIGHT: return (self.maxh-2, self.maxw-int(self.maxw/2), 1, int(self.maxw/2)) elif self.mode == PANE_MODE_FULL: return (self.maxh-2, self.maxw, 1, 0) # h, w, y0, x0 else: # error messages.error('Cannot initialize panes\nReport bug if you can see this.') return (self.maxh-2, int(self.maxw/2), 1, int(self.maxw/2))
def extractDocs(svg_in): """ Extracts the position of the documentation elements and updates the board's json """ # Get copper refdef shape groups from SVG data xpath_expr = '//svg:g[@pcbmode:sheet="documentation"]//svg:g[@pcbmode:type="module-shapes"]' docs = svg_in.findall(xpath_expr, namespaces={'pcbmode':config.cfg['ns']['pcbmode'], 'svg':config.cfg['ns']['svg']}) for doc in docs: doc_key = doc.get('{'+config.cfg['ns']['pcbmode']+'}doc-key') translate_data = utils.parseTransform(doc.get('transform')) location = translate_data['location'] location.y *= config.cfg['invert-y'] current_location = utils.toPoint(config.brd['documentation'][doc_key]['location']) if current_location != location: config.brd['documentation'][doc_key]['location'] = [location.x, location.y] msg.subInfo("Found new location ([%s, %s]) for '%s'" % (location.x, location.y, doc_key)) # Extract drill index location xpath_expr = '//svg:g[@pcbmode:sheet="drills"]//svg:g[@pcbmode:type="drill-index"]' drill_index = svg_in.find(xpath_expr, namespaces={'pcbmode':config.cfg['ns']['pcbmode'], 'svg':config.cfg['ns']['svg']}) transform_dict = utils.parseTransform(drill_index.get('transform')) location = transform_dict['location'] location.y *= config.cfg['invert-y'] # Modify the location in the board's config file. If a # 'drill-index' field doesn't exist, create it drill_index_dict = config.brd.get('drill-index') if drill_index_dict == None: config.brd['drill-index'] = {} config.brd['drill-index']['location'] = [location.x, location.y] # Save board config to file (everything is saved, not only the # component data) filename = os.path.join(config.cfg['locations']['boards'], config.cfg['name'], config.cfg['name'] + '.json') try: with open(filename, 'wb') as f: f.write(json.dumps(config.brd, sort_keys=True, indent=2)) except: msg.error("Cannot save file %s" % filename)
def print_document(self, document): if not tools.has_database(document): messages.error(document.CurrentController.Frame.ContainerWindow, str("Merci de configurer l'étude."), "Etude non configurée") return """ if path.endswith("PC.odt"): self.insert_project_manager_data(document) self.insert_methodology(document) """ stg = document.createInstance("com.sun.star.text.DocumentSettings") db_name = stg.CurrentDatabaseDataSource table_name = stg.CurrentDatabaseCommand output_folder = os.path.join( os.path.dirname(tools.get_document_path(document)), config.PDF_DIRNAME) if not os.path.exists(output_folder): os.makedirs(output_folder) self.update_indexes(document) document.store() # For the index update to be taken into account # Fill field from db and export as PDF mail_merge = self.smgr.createInstanceWithContext( "com.sun.star.text.MailMerge", self.ctx) mail_merge.DocumentURL = document.URL mail_merge.DataSourceName = db_name mail_merge.CommandType = uno.getConstantByName( "com.sun.star.sdb.CommandType.TABLE") mail_merge.Command = table_name mail_merge.OutputType = uno.getConstantByName( "com.sun.star.text.MailMergeType.FILE") mail_merge.OutputURL = uno.systemPathToFileUrl(output_folder) mail_merge.SaveFilter = "writer_pdf_Export" mail_merge.SaveFilterData = tuple([]) mail_merge.execute(()) # Rename PDF file pdf_path = os.path.join(output_folder, tools.get_document_name(document) + "0.pdf") new_path = pdf_path.replace("0.pdf", ".pdf") try: os.rename(pdf_path, new_path) except OSError: # (Windows) The file already exists os.remove(new_path) os.rename(pdf_path, new_path) self.open_document(new_path, hidden=False, read_only=True)
def copy(tab_org, tab_new): """copy vfs""" tempdir = files.mkdtemp() # copy contents dir_src = tab_org.base for f in glob(os.path.join(dir_src, '*')): f = os.path.basename(f) try: files.copy_bulk(os.path.join(dir_src, f), os.path.join(tempdir, f)) except (IOError, os.error), (errno, strerror): app.display() messages.error('Cannot copy vfs (compressed file)\n%s (%s)' % (strerror, errno))
def init(self, path, old_file='', check_oldfile=True): err = self.init_dir(path) if err: messages.error('Cannot change directory\n%s: %s (%d)' % (path, err[0], err[1])) if (check_oldfile and old_file) or (old_file and err): try: self.file_i = self.sorted.index(old_file) except ValueError: self.file_i = 0 else: self.file_i = 0 self.fix_limits() return err
def __find_prev(self): pos = (self.mode==MODE_TEXT) and self.line-1 or \ self.pos - self.__calc_hex_charsperline() # start in prev line for prev in sorted(self.matches, reverse=True): if prev <= pos: break else: self.show() messages.error('Cannot find "%s"\nNo more matches' % self.pattern) return if self.mode == MODE_TEXT: self.line, self.col = prev, 0 else: self.pos = prev
def __calculate_dims(self): if self.mode == PANE_MODE_HIDDEN: return (self.maxh - 2, self.maxw, 0, 0) # h, w, y0, x0 elif self.mode == PANE_MODE_LEFT: return (self.maxh - 2, int(self.maxw / 2), 1, 0) elif self.mode == PANE_MODE_RIGHT: return (self.maxh - 2, self.maxw - int(self.maxw / 2), 1, int(self.maxw / 2)) elif self.mode == PANE_MODE_FULL: return (self.maxh - 2, self.maxw, 1, 0) # h, w, y0, x0 else: # error messages.error( 'Cannot initialize panes\nReport bug if you can see this.') return (self.maxh - 2, int(self.maxw / 2), 1, int(self.maxw / 2))
def __find_next(self): pos = (self.mode==MODE_TEXT) and self.line+1 or \ self.pos+self.__calc_hex_charsperline() # start in next line for next in self.matches: if next >= pos: break else: self.show() messages.error('Cannot find "%s"\nNo more matches' % self.pattern) return if self.mode == MODE_TEXT: self.line, self.col = next, 0 else: self.pos = next
def checking_for_unique_keys(pairs): """ Check if there are duplicate keys defined; this is useful for any hand-edited file This SO answer was useful here: http://stackoverflow.com/questions/16172011/json-in-python-receive-check-duplicate-key-error """ result = dict() for key,value in pairs: if key in result: msg.error("duplicate key ('%s') specified in %s" % (key, filename), KeyError) result[key] = value return result
def openBoardSVG(): """ Opens the built PCBmodE board SVG. Returns an ElementTree object """ filename = os.path.join(config.cfg['base-dir'], config.cfg['locations']['build'], config.cfg['name'] + '.svg') try: data = et.ElementTree(file=filename) except IOError as e: msg.error("Cannot open %s; has the board been made using the '-m' option yet?" % filename) return data
def getSurfaceLayers(): """ Returns a list of sorface layer names """ board_stackup = config.brd['physical'].get('stackup') if board_stackup is not None: if len(board_stackup) == 1: surface_layers = ['top'] elif len(board_stackup) == 2: surface_layers = ['top', 'bottom'] else: msg.error("PCBmodE currently only supports two layers, found %s." % len(board_stackup)) return surface_layers
class FileView(object): """Main application class""" def __init__(self, win, filename, line, mode, stdin_flag): global app app, messages.app = self, self self.win = win # root window, need for resizing self.mode = mode self.wrap = False self.stdin_flag = stdin_flag self.line, self.col, self.col_max, self.pos = 1, 0, 0, 0 self.pattern = '' self.matches = [] self.bookmarks = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] self.init_curses() try: self.fc = FileCache(filename) except (IOError, os.error), (errno, strerror): messages.error('Cannot view file\n%s: %s (%s)' % (filename, strerror, errno)) sys.exit(-1) if self.fc.isempty(): messages.error('Cannot view file\n%s: File is empty' % filename) sys.exit(-1) if line != 0: if mode == MODE_TEXT: self.line = max(0, min(line, self.fc.nlines)) else: self.pos = max(0, min(line, self.fc.nbytes)) & 0xFFFFFFF0L
def _placePours(self): """ """ try: pours = self._module_dict['shapes']['pours'] except: return shape_group = {} for pcb_layer in utils.getSurfaceLayers(): svg_layer = self._layers[pcb_layer]['copper']['pours']['layer'] shape_group[pcb_layer] = et.SubElement(svg_layer, 'g', mask='url(#mask-%s)' % pcb_layer) for pour_dict in pours: try: pour_type = pour_dict['type'] except: msg.error( "Cannot find a 'type' for a pour shape. Pours can be any 'shape', or simply 'type':'layer' to cover the entire layer." ) layers = pour_dict.get('layers') or ['top'] if pour_type == 'layer': # Get the outline shape dict new_pour_dict = self._module_dict['outline'].get( 'shape').copy() new_pour_dict['style'] = 'fill' shape = Shape(new_pour_dict) # Get the appropriate style from copper->pours style = Style(new_pour_dict, layer_name='copper', sub_item='pours') shape.setStyle(style) else: shape = Shape(pour_dict) # Get the appropriate style from copper->pours style = Style(pour_dict, layer_name='copper', sub_item='pours') shape.setStyle(style) # Place on all specified layers for layer in layers: place.placeShape(shape, shape_group[layer])
def pan_regenerate(tab): """regenerate vfs pan file: copy files""" dir_src = tab.path dir_dest = tab.vbase.replace('#vfs', '') # check if can copy files out = utils.get_shell_output('touch ' + utils.encode(dir_dest)) if out: return ''.join(out.split(':')[1:])[1:] # copy files for f in glob(os.path.join(dir_src, '*')): f = os.path.basename(f) try: files.copy_bulk(os.path.join(dir_src, f), os.path.join(dir_dest, f)) except (IOError, os.error), (errno, strerror): app.display() messages.error('Cannot regenerating vfs (closing panelize)\n%s (%s)' % (strerror, errno))
def parseTransform(transform): """ Returns a Point() for the input transform """ data = {} if 'translate' in transform.lower(): regex = r".*?translate\s?\(\s?(?P<x>-?[0-9]*\.?[0-9]+)\s?[\s,]\s?(?P<y>-?[0-9]*\.?[0-9]+\s?)\s?\).*" coord = re.match(regex, transform) data['type'] = 'translate' data['location'] = Point(coord.group('x'),coord.group('y')) elif 'matrix' in transform.lower(): data['type'] = 'matrix' data['location'], data['rotate'], data['scale'] = parseSvgMatrix(transform) else: msg.error("Found a path transform that cannot be handled, %s. SVG stansforms shouls be in the form of 'translate(num,num)' or 'matric(num,num,num,num,num,num)" % transform) return data
def __init__(self, win, filename, line, mode, stdin_flag): global app app, messages.app = self, self self.win = win # root window, need for resizing self.mode = mode self.wrap = False self.stdin_flag = stdin_flag self.line, self.col, self.col_max, self.pos = 1, 0, 0, 0 self.pattern = '' self.matches = [] self.bookmarks = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] self.init_curses() try: self.fc = FileCache(filename) except (IOError, os.error), (errno, strerror): messages.error('Cannot view file\n%s: %s (%s)' % (filename, strerror, errno)) sys.exit(-1)
def pan_init(tab, fs): """initiliaze panelize vfs stuff""" vfstype = 'pan' tempdir = files.mkdtemp() # copy files for f in fs: f_orig = os.path.join(tab.path, f) f_dest = os.path.join(tempdir, f) d = os.path.join(tempdir, os.path.dirname(f)) try: os.makedirs(d) except (IOError, os.error), (errno, strerror): pass try: if os.path.isfile(f_orig): files.copy_bulk(f_orig, f_dest) elif os.path.isdir(f_orig): os.mkdir(f_dest) except (IOError, os.error), (errno, strerror): messages.error('Cannot create vfs (starting panelize)\n%s (%s)' % (strerror, errno))
def _placePours(self): """ """ try: pours = self._module_dict['shapes']['pours'] except: return shape_group = {} for pcb_layer in utils.getSurfaceLayers(): svg_layer = self._layers[pcb_layer]['copper']['pours']['layer'] shape_group[pcb_layer] = et.SubElement(svg_layer, 'g', mask='url(#mask-%s)' % pcb_layer) for pour_dict in pours: try: pour_type = pour_dict['type'] except: msg.error("Cannot find a 'type' for a pour shape. Pours can be any 'shape', or simply 'type':'layer' to cover the entire layer.") layers = pour_dict.get('layers') or ['top'] if pour_type == 'layer': # Get the outline shape dict new_pour_dict = self._module_dict['outline'].get('shape').copy() new_pour_dict['style'] = 'fill' shape = Shape(new_pour_dict) # Get the appropriate style from copper->pours style = Style(new_pour_dict, layer_name='copper', sub_item='pours') shape.setStyle(style) else: shape = Shape(pour_dict) # Get the appropriate style from copper->pours style = Style(pour_dict, layer_name='copper', sub_item='pours') shape.setStyle(style) # Place on all specified layers for layer in layers: place.placeShape(shape, shape_group[layer])
def regenerate_file(tab): """regenerate vfs file: compress new file""" vfs_file = tab.vbase.replace('#vfs', '') # compress file tmpfile = files.mktemp() c = compress.check_compressed_file(vfs_file) cmd = c.build_compressXXX_cmd('*', tmpfile) f = os.path.basename(vfs_file) st, buf = utils.ProcessFunc('Compressing Directory', '\'%s\'' % f, utils.run_shell, cmd, tab.base).run() if st == -1: # error app.display() messages.error('Creating vfs', buf) messages.error('Cannot regenerate vfs (closing compressed file)\n' + buf) app.display() try: files.delete_bulk(tmpfile) except OSError: pass elif st == -100: # stopped by user try: files.delete_bulk(tmpfile) except OSError: pass else: # compress process always create filename with extension, # so we have 2 files now tmpfile_ext = tmpfile + c.exts[0] try: files.copy_bulk(tmpfile_ext, vfs_file) except (IOError, os.error), (errno, strerror): files.delete_bulk(tmpfile_ext) files.delete_bulk(tmpfile) return '%s (%s)' % (strerror, errno) files.delete_bulk(tmpfile_ext, ignore_errors=True) files.delete_bulk(tmpfile, ignore_errors=True)
def __init__(self, shape_dict, layer_name, sub_item=None): default_style = config.stl['layout']['defaults']['style'][layer_name] if sub_item == None: layer_style = config.stl['layout'][layer_name] else: layer_style = config.stl['layout'][layer_name][sub_item] # Unless specified, 'text' will default to 'fill' on all layers. # Other 'types' depend on the layers they are on. if shape_dict.get('style') == None: if shape_dict['type'] in ['text', 'refdef']: self._style = 'fill' else: self._style = default_style else: self._style = shape_dict['style'] try: self._style_dict = layer_style.get(self._style).copy() except: self._style_dict = None # Apply defaults if style dict wasn't found if self._style_dict == None: if self._style == 'fill': self._style_dict = {"stroke": "none"} elif self._style == 'stroke': self._style_dict = {"fill": "none"} else: msg.error("Encountered an unknown 'style' type, %s" % self._style) # If the style is 'stroke' we need to override the default 'stroke-width' # setting with a possible custom definition if self._style == 'stroke': self._style_dict['stroke-width'] = (shape_dict.get('stroke-width') or layer_style[self._style].get('stroke-width')) self._style_dict['fill'] = "none"
def __init__(self, shape): gerber_lp = None mirror = False # Invert rotation so it's clock-wise. Inkscape is counter-clockwise and # it's unclear to ma what's the "right" direction. clockwise makse more # sense to me. This should be the only place to make the change. self._inv_rotate = -1 self._rotate = shape.get('rotate') or 0 self._rotate *= self._inv_rotate self._rotate_point = shape.get('rotate-point') or Point(0,0) self._scale = shape.get('scale') or 1 self._pour_buffer = shape.get('buffer-to-pour') try: self._type = shape.get('type') except: msg.error("Shapes must have a 'type' defined") if self._type in ['rect', 'rectangle']: path = svg.width_and_height_to_path(shape['width'], shape['height'], shape.get('radii')) elif self._type in ['circ', 'circle', 'round']: path = svg.circle_diameter_to_path(shape['diameter']) elif self._type in ['drill']: self._diameter = shape['diameter'] path = svg.drillPath(self._diameter) elif self._type in ['text', 'string']: try: self._text = shape['value'] except KeyError: msg.error("Could not find the text to display. The text to be displayed should be defined in the 'value' field, for example, 'value': 'DEADBEEF\\nhar\\nhar'") # Get the fon'ts name font = shape.get('font-family') or config.stl['layout']['defaults']['font-family'] # Search for the font SVG in these paths paths = [os.path.join(config.cfg['base-dir']), os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')] font_filename = "%s.svg" % font filenames = '' font_data = None for path in paths: filename = os.path.join(path, config.cfg['locations']['fonts'], font_filename) filenames += " %s \n" % filename if os.path.isfile(filename): font_data = et.ElementTree(file=filename) break if font_data == None: msg.error("Couldn't find style file %s. Looked for it here:\n%s" % (font_filename, filenames)) try: fs = shape['font-size'] except: msg.error("A 'font-size' attribute must be specified for a 'text' type") ls = shape.get('letter-spacing') or '0mm' lh = shape.get('line-height') or fs font_size, letter_spacing, line_height = utils.getTextParams(fs, ls, lh) # With the units-per-em we can figure out the scale factor # to use for the desired font size units_per_em = float(font_data.find("//n:font-face", namespaces={'n': config.cfg['namespace']['svg']}).get('units-per-em')) or 1000 self._scale = font_size/units_per_em # Get the path to use. This returns the path without # scaling, which will be applied later, in the same manner # as to the other shape types path, gerber_lp = utils.textToPath(font_data, self._text, letter_spacing, line_height, self._scale) # In the case where the text is an outline/stroke instead # of a fill we get rid of the gerber_lp if shape.get('style') == 'stroke': gerber_lp = None self._rotate += 180 elif self._type in ['path']: path = shape.get('value') else: msg.error("'%s' is not a recongnised shape type" % self._type) self._path = SvgPath(path, gerber_lp) self._path.transform(self._scale, self._rotate, self._rotate_point, True) self._gerber_lp = (shape.get('gerber-lp') or shape.get('gerber_lp') or gerber_lp or None) self._location = utils.toPoint(shape.get('location', [0, 0]))
def _makeCoordList(self, path, steps, length): """ """ # absolute position ap = Point() # path origin po = Point() points = [] p = [] # TODO: legacy pd = path last_bezier_control_point = Point() for i in range(0, len(pd)): cmd = pd[i][0] # 'move to' command if re.match('m', cmd): if i == 0: coord = Point(pd[i][1][0], pd[i][1][1]) ap.assign(coord.x, coord.y) p.append(ap) po.assign(coord.x, coord.y) else: coord_tmp = Point(pd[i][1][0], pd[i][1][1]) ap += coord_tmp # a marker that a new path is starting after a previous one closed points.append(p) p = [] p.append(ap) po = ap for coord_tmp in pd[i][2:]: coord = Point(coord_tmp[0], coord_tmp[1]) ap += coord p.append(ap) # cubic (two control points) Bezier curve command elif re.match('c', cmd): bezier_curve_path = [] for n in range(1, len(pd[i])-1, 3): bezier_curve_path.append(ap) for m in range(0, 3): coord = pd[i][n+m] point = Point(coord[0], coord[1]) bezier_curve_path.append(ap + point) new_point = Point(pd[i][n+m][0], pd[i][n+m][1]) ap += new_point for n in range(0, len(bezier_curve_path), 4): # clear bezier point arrays bezier_points_x = [] bezier_points_y = [] # split points of bezier into 'x' and 'y' coordinate arrays # as this is what the point array function expects for m in range(0, 4): bezier_points_x.append(bezier_curve_path[n+m].x) bezier_points_y.append(bezier_curve_path[n+m].y) # caluclate the individual points along the bezier curve for 'x' # and 'y' points_x = self._linearizeCubicBezier(bezier_points_x, steps) points_y = self._linearizeCubicBezier(bezier_points_y, steps) path_length = self._getCubicBezierLength(points_x, points_y) if path_length == 0: steps_tmp = 1 else: steps_tmp = ceil(path_length / length) skip = int(ceil(steps / steps_tmp)) bezier_point_array = [] # put thos points back into a Point type array for n in range(0, len(points_x), skip): bezier_point_array.append(Point(points_x[n], points_y[n])) bezier_point_array.append(Point(points_x[len(points_x)-1], points_y[len(points_x)-1])) p += bezier_point_array # quadratic (single control point) Bezier curve command elif re.match('q', cmd): bezier_curve_path = [] for n in range(1, len(pd[i])-1, 2): bezier_curve_path.append(ap) for m in range(0, 2): coord = pd[i][n+m] point = Point(coord[0], coord[1]) bezier_curve_path.append(ap + point) # inject a second, identical control point so this quadratic # bezier looks like a cubic one if m == 1: bezier_curve_path.append(ap+point) if m == 0: last_bezier_control_point = ap + point new_point = Point(pd[i][n+m][0], pd[i][n+m][1]) ap += new_point for n in range(0, len(bezier_curve_path), 4): # clear bezier point arrays bezier_points_x = [] bezier_points_y = [] # split points of bezier into 'x' and 'y' coordinate arrays # as this is what the point array function expects for m in range(0, 4): bezier_points_x.append(bezier_curve_path[n+m].x) bezier_points_y.append(bezier_curve_path[n+m].y) # caluclate the individual points along the bezier curve for 'x' # and 'y' points_x = self._linearizeCubicBezier(bezier_points_x, steps) points_y = self._linearizeCubicBezier(bezier_points_y, steps) path_length = self._getCubicBezierLength(points_x, points_y) skip = int(ceil(steps / (path_length / length))) bezier_point_array = [] # put those points back into a Point type array for n in range(0, len(points_x), skip): bezier_point_array.append(Point(points_x[n], points_y[n])) bezier_point_array.append(Point(points_x[len(points_x)-1], points_y[len(points_x)-1])) p += bezier_point_array # simple cubic Bezier curve command elif re.match('t', cmd): bezier_curve_path = [] for n in range(1, len(pd[i])): bezier_curve_path.append(ap) coord = pd[i][n] point = Point(coord[0], coord[1]) end_point = ap + point diff = Point(ap.x - last_bezier_control_point.x, ap.y - last_bezier_control_point.y) control_point = ap + diff bezier_curve_path.append(control_point) bezier_curve_path.append(end_point) bezier_curve_path.append(end_point) last_bezier_control_point = control_point new_point = Point(pd[i][n][0], pd[i][n][1]) ap += new_point for n in range(0, len(bezier_curve_path), 4): # clear bezier point arrays bezier_points_x = [] bezier_points_y = [] # split points of bezier into 'x' and 'y' coordinate arrays # as this is what the point array function expects for m in range(0, 4): bezier_points_x.append(bezier_curve_path[n+m].x) bezier_points_y.append(bezier_curve_path[n+m].y) # caluclate the individual points along the bezier curve for 'x' # and 'y' points_x = self._linearizeCubicBezier(bezier_points_x, steps) points_y = self._linearizeCubicBezier(bezier_points_y, steps) path_length = self._getCubicBezierLength(points_x, points_y) skip = int(ceil(steps / (path_length / length))) bezier_point_array = [] # put those points back into a Point type array for m in range(0, len(points_x), skip): bezier_point_array.append(Point(points_x[m], points_y[m])) bezier_point_array.append(Point(points_x[len(points_x)-1], points_y[len(points_x)-1])) p += bezier_point_array # elif re.match('s', cmd): # pass # 'line to' command elif re.match('l', cmd): for coord_tmp in pd[i][1:]: coord = Point(coord_tmp[0], coord_tmp[1]) ap += coord p.append(ap) # 'horizontal line' command elif re.match('h', cmd): for coord_tmp in pd[i][1:]: coord = Point(coord_tmp[0], 0) ap += coord p.append(ap) # 'vertical line' command elif re.match('v', cmd): for coord_tmp in pd[i][1:]: coord = Point(0, coord_tmp[0]) ap += coord p.append(ap) # 'close shape' command elif re.match('z', cmd): ap = ap + (po - ap) else: msg.error("Found an unsupported SVG path command, '%s'" % cmd) points.append(p) return points
def _makeRelative(self, path): """ """ p = '' # This variable stores the absolute coordinates as the path is converted; abspos = Point() patho = Point() for i in range(0, len(path)): # 'move to' command if re.match('M', path[i][0], re.I): # TODO: write this code more concisely coord = Point(path[i][1][0], path[i][1][1]) p += 'm ' # if this is the start of the path, the first M/m coordinate is # always absolute if i == 0: abspos.assign(coord.x, coord.y) p += str(abspos.x) + ',' + str(abspos.y) + ' ' patho.assign(coord.x, coord.y) else: if path[i][0] == 'm': p += str(coord.x) + ',' + str(coord.y) + ' ' abspos += coord patho = abspos else: p += str(coord.x - abspos.x) + ',' + str(coord.y - abspos.y) + ' ' abspos.assign(coord.x, coord.y) patho.assign(coord.x, coord.y) # do the rest of the coordinates for coord_tmp in path[i][2:]: coord.assign(coord_tmp[0], coord_tmp[1]) if path[i][0] == 'm': p += str(coord.x) + ',' + str(coord.y) + ' ' abspos += coord else: p += str(coord.x - abspos.x) + ',' + str(coord.y - abspos.y) + ' ' abspos.assign(coord.x, coord.y) # cubic Bezier (PCCP) curve command elif re.match('C', path[i][0], re.I): p += path[i][0].lower()+' ' if path[i][0] == 'c': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(coord.x) + ',' + str(coord.y) +' ' # for keeping track of the absolute position, we need to add up every # *third* coordinate of the cubic Bezier curve for coord_tmp in path[i][3::3]: coord.assign(coord_tmp[0], coord_tmp[1]) abspos += coord if path[i][0] == 'C': for n in range(1, len(path[i])-1, 3): for m in range(0, 3): coord.assign(path[i][n+m][0], path[i][n+m][1]) p += str(coord.x - abspos.x) + ',' + str(coord.y - abspos.y)+' ' abspos.assign(coord.x, coord.y) # quadratic Bezier (PCP) curve command elif re.match('Q', path[i][0], re.I): p += path[i][0].lower() + ' ' if path[i][0] == 'q': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(coord.x) + ',' + str(coord.y) +' ' # for keeping track of the absolute position, we need to add up every # *third* coordinate of the cubic Bezier curve for coord_tmp in path[i][2::2]: coord.assign(coord_tmp[0], coord_tmp[1]) abspos += coord if path[i][0] == 'Q': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(coord.x - abspos.x) + ',' + str(coord.y - abspos.y) + ' ' abspos.assign(coord.x, coord.y) # simple cubic Bezier curve command elif re.match('T', path[i][0], re.I): p += path[i][0].lower()+' ' if path[i][0] == 't': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(coord.x) + ',' + str(coord.y) + ' ' # for keeping track of the absolute position, we need to add up every # *third* coordinate of the cubic Bezier curve #for coord in path[i][2::2]: abspos += coord if path[i][0] == 'T': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(float(coord[0]) - abspos['x']) + ',' + str(float(coord[1]) - abspos['y']) + ' ' abspos.assign(coord.x, coord.y) elif re.match('S', path[i][0], re.I): p += path[i][0].lower()+' ' if path[i][0] == 's': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(coord.x)+','+str(coord.y)+' ' abspos += coord if path[i][0] == 'S': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(coord.x - abspos.x) + ',' + str(coord.y - abspos.y) + ' ' abspos.assign(coord.x, coord.y) # 'line to' command elif re.match('L', path[i][0], re.I): p += path[i][0].lower()+' ' if path[i][0] == 'l': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(coord.x) + ',' + str(coord.y) + ' ' abspos += coord if path[i][0] == 'L': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(coord.x - abspos.x) + ',' + str(coord.y - abspos.y) + ' ' abspos.assign(coord.x, coord.y) # 'horizontal line' command elif re.match('H', path[i][0], re.I): p += path[i][0].lower()+' ' if path[i][0] == 'h': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], 0) p += str(coord.x) + ' ' abspos.x += coord.x if path[i][0] == 'H': for coord_tmp in path[i][1:]: coord.assign(coord_tmp[0], coord_tmp[1]) p += str(coord.x - abspos.x) + ' ' abspos.x = coord.x # 'vertical line' command elif re.match('V', path[i][0], re.I): p += path[i][0].lower() + ' ' if path[i][0] == 'v': for coord_tmp in path[i][1:]: coord.assign(0, coord_tmp[0]) p += str(coord.y) + ' ' abspos.y += coord.y if path[i][0] == 'V': for coord_tmp in path[i][1:]: coord.assign(0, coord_tmp[0]) p += str(coord.y - abspos.y) + ' ' abspos.y = coord.y # 'close shape' command elif re.match('Z', path[i][0], re.I): p += path[i][0].lower() + ' ' abspos = abspos + (patho - abspos) else: msg.error("Found an unsupported SVG path command '%s'" % path[i][0]) return p