Skip to content
This repository has been archived by the owner on Aug 27, 2021. It is now read-only.

Commit

Permalink
Merge branch 'arduino-1.5.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
nkrkv committed Apr 15, 2014
2 parents fe6e94a + ef1f6da commit 85d1768
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 46 deletions.
20 changes: 11 additions & 9 deletions ino/commands/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,20 @@ def setup_arg_parser(self, parser):
help='Verbose make output')

def discover(self, args):
self.e.find_arduino_dir('arduino_core_dir',
['hardware', 'arduino', 'cores', 'arduino'],
['Arduino.h'] if self.e.arduino_lib_version.major else ['WProgram.h'],
'Arduino core library')
board = self.e.board_model(args.board_model)

self.e.find_arduino_dir('arduino_libraries_dir', ['libraries'],
human_name='Arduino standard libraries')
core_place = os.path.join(board['_coredir'], 'cores', board['build']['core'])
core_header = 'Arduino.h' if self.e.arduino_lib_version.major else 'WProgram.h'
self.e.find_dir('arduino_core_dir', [core_header], [core_place],
human_name='Arduino core library')

if self.e.arduino_lib_version.major:
self.e.find_arduino_dir('arduino_variants_dir',
['hardware', 'arduino', 'variants'],
human_name='Arduino variants directory')
variants_place = os.path.join(board['_coredir'], 'variants')
self.e.find_dir('arduino_variants_dir', ['.'], [variants_place],
human_name='Arduino variants directory')

self.e.find_arduino_dir('arduino_libraries_dir', ['libraries'],
human_name='Arduino standard libraries')

toolset = [
('make', args.make),
Expand Down
126 changes: 90 additions & 36 deletions ino/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from ordereddict import OrderedDict

from collections import namedtuple
from glob import glob
from glob2 import glob

from ino.filters import colorize
from ino.utils import format_available_options
Expand Down Expand Up @@ -123,7 +123,19 @@ def __getattr__(self, attr):
def hex_path(self):
return os.path.join(self.build_dir, self.hex_filename)

def _find(self, key, items, places, human_name, join):
def _find(self, key, items, places, human_name, join, multi):
"""
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]

Expand All @@ -133,39 +145,54 @@ def _find(self, key, items, places, human_name, join):
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, '...',
for p in places:
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
print colorize(result, 'green')
self[key] = result
return result
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')
raise Abort("%s not found. Searched in following places: %s" %
(human_name, ''.join(['\n - ' + p for p in places])))

def find_dir(self, key, items, places, human_name=None):
return self._find(key, items or ['.'], places, human_name, join=False)
def find_dir(self, key, items, places, human_name=None, multi=False):
return self._find(key, items or ['.'], places, human_name, join=False, multi=multi)

def find_file(self, key, items=None, places=None, human_name=None):
return self._find(key, items or [key], places, human_name, join=True)
def find_file(self, key, items=None, places=None, human_name=None, multi=False):
return self._find(key, items or [key], places, human_name, join=True, multi=multi)

def find_tool(self, key, items, places=None, human_name=None):
return self.find_file(key, items, places or ['$PATH'], human_name)
def find_tool(self, key, items, places=None, human_name=None, multi=False):
return self.find_file(key, items, places or ['$PATH'], human_name, multi=multi)

def find_arduino_dir(self, key, dirname_parts, items=None, human_name=None):
return self.find_dir(key, items, self.arduino_dist_places(dirname_parts), human_name)
def find_arduino_dir(self, key, dirname_parts, items=None, human_name=None, multi=False):
return self.find_dir(key, items, self.arduino_dist_places(dirname_parts), human_name, multi=multi)

def find_arduino_file(self, key, dirname_parts, items=None, human_name=None):
return self.find_file(key, items, self.arduino_dist_places(dirname_parts), human_name)
def find_arduino_file(self, key, dirname_parts, items=None, human_name=None, multi=False):
return self.find_file(key, items, self.arduino_dist_places(dirname_parts), human_name, multi=multi)

def find_arduino_tool(self, key, dirname_parts, items=None, human_name=None):
def find_arduino_tool(self, key, dirname_parts, items=None, human_name=None, multi=False):
# if not bundled with Arduino Software the tool should be searched on PATH
places = self.arduino_dist_places(dirname_parts) + ['$PATH']
return self.find_file(key, items, places, human_name)
return self.find_file(key, items, places, human_name, multi=multi)

def arduino_dist_places(self, dirname_parts):
"""
Expand All @@ -185,26 +212,53 @@ def board_models(self):
if 'board_models' in self:
return self['board_models']

boards_txt = self.find_arduino_file('boards.txt', ['hardware', 'arduino'],
human_name='Board description file (boards.txt)')
# boards.txt can be placed in following places
# - hardware/arduino/boards.txt (Arduino IDE 0.xx, 1.0.x)
# - hardware/arduino/{chipset}/boards.txt (Arduino 1.5.x, chipset like `avr`, `sam`)
# - hardware/{platform}/boards.txt (MPIDE 0.xx, platform like `arduino`, `pic32`)
# we should find and merge them all
boards_txts = self.find_arduino_file('boards.txt', ['hardware', '**'],
human_name='Board description file (boards.txt)',
multi=True)

self['board_models'] = BoardModels()
self['board_models'].default = self.default_board_model
with open(boards_txt) as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
multikey, val = line.split('=')
multikey = multikey.split('.')

subdict = self['board_models']
for key in multikey[:-1]:
if key not in subdict:
subdict[key] = {}
subdict = subdict[key]

subdict[multikey[-1]] = val
for boards_txt in boards_txts:
with open(boards_txt) as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue

# Transform lines like:
# yun.upload.maximum_data_size=2560
# into a nested dict `board_models` so that
# self['board_models']['yun']['upload']['maximum_data_size'] == 2560
multikey, _, val = line.partition('=')
multikey = multikey.split('.')

# traverse into dictionary up to deepest level
# create nested dictionaries if they aren't exist yet
subdict = self['board_models']
for key in multikey[:-1]:
if key not in subdict:
subdict[key] = {}
elif not isinstance(subdict[key], dict):
# it happens that a particular key
# has a value and has sublevels at same time. E.g.:
# diecimila.menu.cpu.atmega168=ATmega168
# diecimila.menu.cpu.atmega168.upload.maximum_size=14336
# diecimila.menu.cpu.atmega168.upload.maximum_data_size=1024
# diecimila.menu.cpu.atmega168.upload.speed=19200
# place value `ATmega168` into a special key `_` in such case
subdict[key] = {'_': subdict[key]}
subdict = subdict[key]

subdict[multikey[-1]] = val

# store spectial `_coredir` value on top level so we later can build
# paths relative to a core directory of a specific board model
self['board_models'][multikey[0]]['_coredir'] = os.path.dirname(boards_txt)

return self['board_models']

Expand Down Expand Up @@ -293,5 +347,5 @@ def arduino_lib_version(self):

class BoardModels(OrderedDict):
def format(self):
map = [(key, val['name']) for key, val in self.iteritems()]
map = [(key, val['name']) for key, val in self.iteritems() if 'name' in val]
return format_available_options(map, head_width=12, default=self.default)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ pyserial
configobj
ordereddict
argparse
glob2
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def gen_data_files(package_dir, subdir):

setup(
name='ino',
version='0.3.6',
version='0.3.7',
description='Command line toolkit for working with Arduino hardware',
long_description=readme_content,
author='Victor Nakoryakov, Amperka Team',
Expand Down

0 comments on commit 85d1768

Please sign in to comment.