Mbed LS
main.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 """
4 mbed SDK
5 Copyright (c) 2011-2015 ARM Limited
6 
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10 
11  http://www.apache.org/licenses/LICENSE-2.0
12 
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 """
19 
20 import os
21 import sys
22 import json
23 import argparse
24 import platform
25 from collections import defaultdict
26 
27 # Make sure that any global generic setup is run
28 from . import lstools_base
29 
30 import logging
31 logger = logging.getLogger("mbedls.main")
32 logger.addHandler(logging.NullHandler())
33 del logging
34 
35 
36 def create(**kwargs):
37  """! Factory used to create host OS specific mbed-lstools object
38 
39  :param kwargs: keyword arguments to pass along to the constructors
40  @return Returns MbedLsTools object or None if host OS is not supported
41 
42  """
43  result = None
44  mbed_os = mbed_os_support()
45  if mbed_os is not None:
46  if mbed_os == 'Windows7':
47  from .windows import MbedLsToolsWin7
48  result = MbedLsToolsWin7(**kwargs)
49  elif mbed_os == 'LinuxGeneric':
50  from .linux import MbedLsToolsLinuxGeneric
51  result = MbedLsToolsLinuxGeneric(**kwargs)
52  elif mbed_os == 'Darwin':
53  from .darwin import MbedLsToolsDarwin
54  result = MbedLsToolsDarwin(**kwargs)
55  return result
56 
57 
59  """! Function used to determine if host OS is supported by mbed-lstools
60 
61  @return Returns None if host OS is not supported else return OS short name
62 
63  @details This function should be ported for new OS support
64  """
65  result = None
66  os_info = mbed_lstools_os_info()
67  if (os_info[0] == 'nt' and os_info[1] == 'Windows'):
68  result = 'Windows7'
69  elif (os_info[0] == 'posix' and os_info[1] == 'Linux'):
70  result = 'LinuxGeneric'
71  elif (os_info[0] == 'posix' and os_info[1] == 'Darwin'):
72  result = 'Darwin'
73  return result
74 
75 
77  """! Returns information about host OS
78 
79  @return Returns tuple with information about OS and host platform
80  """
81  result = (os.name,
82  platform.system(),
83  platform.release(),
84  platform.version(),
85  sys.platform)
86  return result
87 
88 
90  """! Get mbed-ls Python module version string """
91  import pkg_resources # part of setuptools
92  return pkg_resources.require("mbed-ls")[0].version
93 
94 def print_version(mbeds, args):
95  print(get_version())
96 
97 def print_mbeds(mbeds, args, simple):
98  devices = mbeds.list_mbeds(unique_names=True, read_details_txt=True)
99  if devices:
100  from prettytable import PrettyTable, HEADER
101  columns = ['platform_name', 'platform_name_unique', 'mount_point',
102  'serial_port', 'target_id', 'daplink_version']
103  pt = PrettyTable(columns, junction_char="|", hrules=HEADER)
104  pt.align = 'l'
105  for d in devices:
106  pt.add_row([d.get(col, None) or 'unknown' for col in columns])
107  print(pt.get_string(border=not simple, header=not simple,
108  padding_width=1, sortby='platform_name_unique'))
109 
110 def print_table(mbeds, args):
111  return print_mbeds(mbeds, args, False)
112 
113 def print_simple(mbeds, args):
114  return print_mbeds(mbeds, args, True)
115 
116 def mock_platform(mbeds, args):
117  for token in args.mock.split(','):
118  if ':' in token:
119  oper = '+' # Default
120  mid, platform_name = token.split(':')
121  if mid and mid[0] in ['+', '-']:
122  oper = mid[0] # Operation (character)
123  mid = mid[1:] # We remove operation character
124  mbeds.mock_manufacture_id(mid, platform_name, oper=oper)
125  elif token and token[0] in ['-', '!']:
126  # Operations where do not specify data after colon: --mock=-1234,-7678
127  oper = token[0]
128  mid = token[1:]
129  mbeds.mock_manufacture_id(mid, 'dummy', oper=oper)
130  else:
131  logger.error("Could not parse mock from token: '%s'", token)
132 
133 def list_platforms(mbeds, args):
134  print(mbeds.list_manufacture_ids())
135 
136 def mbeds_as_json(mbeds, args):
137  print(json.dumps(mbeds.list_mbeds(unique_names=True,
138  read_details_txt=True),
139  indent=4, sort_keys=True))
140 
141 def json_by_target_id(mbeds, args):
142  print(json.dumps({m['target_id']: m for m
143  in mbeds.list_mbeds(unique_names=True,
144  read_details_txt=True)},
145  indent=4, sort_keys=True))
146 
147 def json_platforms(mbeds, args):
148  platforms = set()
149  for d in mbeds.list_mbeds():
150  platforms |= set([d['platform_name']])
151  print(json.dumps(list(platforms), indent=4, sort_keys=True))
152 
153 def json_platforms_ext(mbeds, args):
154  platforms = defaultdict(lambda: 0)
155  for d in mbeds.list_mbeds():
156  platforms[d['platform_name']] += 1
157  print(json.dumps(platforms, indent=4, sort_keys=True))
158 
159 def parse_cli(to_parse):
160  """! Parse the command line
161 
162  @return Retrun a namespace that contains:
163  * command - python function to run
164  * skip_retarget - bool indicting to skip retargeting
165  * list_unmounted - list boards that are not mounted
166  * debug - turn on debug logging
167  """
168  parser = argparse.ArgumentParser()
169  parser.set_defaults(command=print_table)
170 
171  commands = parser.add_argument_group('sub commands')\
172  .add_mutually_exclusive_group()
173  commands.add_argument(
174  '-s', '--simple', dest='command', action='store_const',
175  const=print_simple,
176  help='list attached targets without column headers and borders')
177  commands.add_argument(
178  '-j', '--json', dest='command', action='store_const',
179  const=mbeds_as_json,
180  help='list attached targets with detailed information in JSON format')
181  commands.add_argument(
182  '-J', '--json-by-target-id', dest='command', action='store_const',
183  const=json_by_target_id,
184  help='map attached targets from their target ID to their detailed '
185  'information in JSON format')
186  commands.add_argument(
187  '-p', '--json-platforms', dest='command', action='store_const',
188  const=json_platforms,
189  help='list attached platform names in JSON format.')
190  commands.add_argument(
191  '-P', '--json-platforms-ext', dest='command', action='store_const',
192  const=json_platforms_ext,
193  help='map attached platform names to the number of attached boards in '
194  'JSON format')
195  commands.add_argument(
196  '-l', '--list', dest='command', action='store_const',
197  const=list_platforms,
198  help='list all target IDs and their corresponding platform names '
199  'understood by mbed-ls')
200  commands.add_argument(
201  '--version', dest='command', action='store_const', const=print_version,
202  help='print package version and exit')
203  commands.add_argument(
204  '-m', '--mock', metavar='ID:NAME',
205  help='substitute or create a target ID to platform name mapping used'
206  'when invoking mbedls in the current directory')
207 
208  parser.add_argument(
209  '--skip-retarget', dest='skip_retarget', default=False,
210  action="store_true",
211  help='skip parsing and interpretation of the re-target file,'
212  ' `./mbedls.json`')
213  parser.add_argument(
214  '-u', '--list-unmounted', dest='list_unmounted', default=False,
215  action='store_true',
216  help='list mbeds, regardless of whether they are mounted or not')
217  parser.add_argument(
218  '-d', '--debug', dest='debug', default=False, action="store_true",
219  help='outputs extra debug information useful when creating issues!')
220 
221  args = parser.parse_args(to_parse)
222  if args.mock:
223  args.command = mock_platform
224  return args
225 
227  try:
228  import colorlog
229  colorlog.basicConfig(
230  format='%(log_color)s%(levelname)s%(reset)s:%(name)s:%(message)s')
231  except ImportError:
232  import logging
233  logging.basicConfig()
234  del logging
235 
237  """! Function used to drive CLI (command line interface) application
238  @return Function exits with success code
239  """
240  start_logging()
241 
242  args = parse_cli(sys.argv[1:])
243 
244  import logging
245  root_logger = logging.getLogger("mbedls")
246  if args.debug:
247  root_logger.setLevel(logging.DEBUG)
248  else:
249  root_logger.setLevel(logging.INFO)
250  del logging
251  logger.debug("mbed-ls ver. %s", get_version())
252  logger.debug("host: %s", str(mbed_lstools_os_info()))
253 
254  mbeds = create(skip_retarget=args.skip_retarget,
255  list_unmounted=args.list_unmounted,
256  force_mock=args.command is mock_platform)
257 
258  if mbeds is None:
259  logger.critical('This platform is not supported! Pull requests welcome at github.com/ARMmbed/mbed-ls')
260  sys.exit(-1)
261 
262  ret_code = args.command(mbeds, args)
263  if not ret_code:
264  ret_code = 0
265 
266  logger.debug("Return code: %d", ret_code)
267 
268  sys.exit(ret_code)
def list_platforms(mbeds, args)
Definition: main.py:133
def mbedls_main()
Function used to drive CLI (command line interface) application.
Definition: main.py:236
def print_table(mbeds, args)
Definition: main.py:110
def parse_cli(to_parse)
Parse the command line.
Definition: main.py:159
def print_mbeds(mbeds, args, simple)
Definition: main.py:97
def mbed_os_support()
Function used to determine if host OS is supported by mbed-lstools.
Definition: main.py:58
def print_simple(mbeds, args)
Definition: main.py:113
def json_platforms_ext(mbeds, args)
Definition: main.py:153
def json_by_target_id(mbeds, args)
Definition: main.py:141
def get_version()
Get mbed-ls Python module version string.
Definition: main.py:89
def create(kwargs)
Factory used to create host OS specific mbed-lstools object.
Definition: main.py:36
def mbeds_as_json(mbeds, args)
Definition: main.py:136
def json_platforms(mbeds, args)
Definition: main.py:147
def print_version(mbeds, args)
Definition: main.py:94
def start_logging()
Definition: main.py:226
def mock_platform(mbeds, args)
Definition: main.py:116
def mbed_lstools_os_info()
Returns information about host OS.
Definition: main.py:76