def run(self, args): try: copytree(os.path.join(self.e['templates_dir'], args.template), '.', ignore=lambda *args: ['manifest.ini']) except shutil.Error as e: raise Abort(str(e))
def parse(cls, s): # Version could have various forms # 0022 # 0022ubuntu0.1 # 0022-macosx-20110822 # 1.0 # 1:1.0.5+dfsg2-1 # We have to extract a 3-int-tuple (major, minor, build) match = cls.regex.match(s) if not match: raise Abort("Could not parse Arduino library version: %s" % s) # v is numbers possibly split by dots without a trash v = match.group(2) if v.startswith('0'): # looks like old 0022 or something like that return cls(0, int(v), 0) parts = map(int, v.split('.')) # append nulls if they were not explicit while len(parts) < 3: parts.append(0) return cls(*parts)
def _find(self, key, items, places, human_name, join, multi, optional): """ Search for file-system entry with any name passed in `items` on all paths provided in `places`. Use `key` as a cache key. If `join` is True result will be a path join of place/item, otherwise only place is taken as result. Return first found match unless `multi` is True. In that case a list with all fount matches is returned. Raise `Abort` if no matches were found. """ if key in self: return self[key] human_name = human_name or key # expand env variables in `places` and split on colons places = itertools.chain.from_iterable( os.path.expandvars(p).split(os.pathsep) for p in places) places = map(os.path.expanduser, places) glob_places = itertools.chain.from_iterable(glob(p) for p in places) print 'Searching for', human_name, '...', results = [] for p in glob_places: for i in items: path = os.path.join(p, i) if os.path.exists(path): result = path if join else p if not multi: print colorize(result, 'green') self[key] = result return result results.append(result) if results: if len(results) > 1: formatted_results = ''.join(['\n - ' + x for x in results]) print colorize('found multiple: %s' % formatted_results, 'green') else: print colorize(results[0], 'green') self[key] = results return results print colorize('FAILED', 'red') if not optional: raise Abort("%s not found. Searched in following places: %s" % (human_name, ''.join(['\n - ' + p for p in places]))) else: self[key] = None return results
def guess_serial_port(self): print 'Guessing serial port ...', ports = self.list_serial_ports() if ports: result = ports[0] print colorize(result, 'yellow') return result print colorize('FAILED', 'red') raise Abort( "No device matching following was found: %s" % (''.join(['\n - ' + p for p in self.serial_port_patterns()])))
def process_args(self, args): arduino_dist = getattr(args, 'arduino_dist', None) if arduino_dist: self['arduino_dist_dir'] = arduino_dist board_model = getattr(args, 'board_model', None) if board_model: all_models = self.board_models() if board_model not in all_models: print "Supported Arduino board models are:" print all_models.format() raise Abort('%s is not a valid board model' % board_model) # Build artifacts for each Arduino distribution / Board model # pair should go to a separate subdirectory build_dirname = board_model or self.default_board_model if arduino_dist: distHash = hashlib.md5(arduino_dist).hexdigest()[:8] build_dirname = '%s-%s' % (build_dirname, distHash) self['build_dir'] = os.path.join(self.output_dir, build_dirname)
def run(self, args): self.discover() port = args.serial_port or self.e.guess_serial_port() board = self.e.board_model(args.board_model) protocol = board['upload']['protocol'] if protocol == 'stk500': # if v1 is not specifid explicitly avrdude will # try v2 first and fail protocol = 'stk500v1' if not os.path.exists(port): raise Abort("%s doesn't exist. Is Arduino connected?" % port) # send a hangup signal when the last process closes the tty file_switch = '-f' if platform.system() == 'Darwin' else '-F' ret = subprocess.call([self.e['stty'], file_switch, port, 'hupcl']) if ret: raise Abort("stty failed") # pulse on DTR try: s = Serial(port, 115200) except SerialException as e: raise Abort(str(e)) s.setDTR(False) sleep(0.1) s.setDTR(True) s.close() # Need to do a little dance for Leonardo and derivatives: # open then close the port at the magic baudrate (usually 1200 bps) first # to signal to the sketch that it should reset into bootloader. after doing # this wait a moment for the bootloader to enumerate. On Windows, also must # deal with the fact that the COM port number changes from bootloader to # sketch. touch_port = \ board['upload'].get('use_1200bps_touch') == 'true' or \ board['upload']['protocol'] == 'avr109' if touch_port: new_port = None before = self.e.list_serial_ports() if port in before: ser = Serial() ser.port = port ser.baudrate = 1200 ser.open() ser.close() # Scanning for available ports seems to open the port or # otherwise assert DTR, which would cancel the WDT reset if # it happened within 250 ms. So we wait until the reset should # have already occured before we start scanning. if platform.system() != 'Darwin': sleep(0.3) elapsed = 0 enum_delay = 0.25 while elapsed < 10: now = self.e.list_serial_ports() diff = list(set(now) - set(before)) if diff: new_port = diff[0] break before = now sleep(enum_delay) elapsed += enum_delay if not new_port: raise Abort("Couldn’t find a board on the selected port. " "Check that you have the correct port selected. " "If it is correct, try pressing the board's reset " "button after initiating the upload.") port = new_port # call avrdude to upload .hex subprocess.call([ self.e['avrdude'], '-C', self.e['avrdude.conf'], '-p', board['build']['mcu'], '-P', port, '-c', protocol, '-b', board['upload']['speed'], '-D', '-U', 'flash:w:%s:i' % self.e['hex_path'], ])
def make(self, makefile, **kwargs): makefile = self.render_template(makefile + '.jinja', makefile, **kwargs) ret = subprocess.call([self.e.make, '-f', makefile, 'all']) if ret != 0: raise Abort("Make failed with code %s" % ret)
def main(): e = Environment() e.load() conf = configure() try: current_command = sys.argv[1] except IndexError: current_command = None parser = argparse.ArgumentParser(prog='ano', formatter_class=FlexiFormatter, description=__doc__) subparsers = parser.add_subparsers() is_command = lambda x: inspect.isclass(x) and issubclass(x, Command ) and x != Command commands = [ cls(e) for _, cls in inspect.getmembers(ano.commands, is_command) ] for cmd in commands: p = subparsers.add_parser(cmd.name, formatter_class=FlexiFormatter, help=cmd.help_line) if current_command != cmd.name: continue cmd.setup_arg_parser(p) p.set_defaults(func=cmd.run, **conf.as_dict(cmd.name)) args = parser.parse_args() try: run_anywhere = "init clean list-models serial version" e.process_args(args) if current_command not in run_anywhere: if os.path.isdir(e.output_dir): # we have an output dir so we'll pretend this is a project folder None elif e.src_dir is None or not os.path.isdir(e.src_dir): raise Abort("No project found in this directory.") if current_command not in run_anywhere: # For valid projects create .build & lib if not os.path.isdir(e.build_dir): os.makedirs(e.build_dir) if not os.path.isdir(e.lib_dir): os.makedirs(e.lib_dir) with open('lib/.holder', 'w') as f: f.write("") args.func(args) except Abort as exc: print colorize(str(exc), 'red') sys.exit(1) except KeyboardInterrupt: print 'Terminated by user' finally: e.dump()