platform_database.py
Go to the documentation of this file.
"""
mbed SDK
Copyright (c) 2017 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
"""Functions that manage a platform database"""
import datetime
import json
import re
from collections import OrderedDict, defaultdict
from copy import copy
from io import open
from os import makedirs
from os.path import join, dirname, getmtime
from appdirs import user_data_dir
from fasteners import InterProcessLock
try:
unicode
except NameError:
unicode = str
import logging
logger = logging.getLogger("mbedls.platform_database")
logger.addHandler(logging.NullHandler())
del logging
LOCAL_PLATFORM_DATABASE = join(user_data_dir("mbedls"), "platforms.json")
LOCAL_MOCKS_DATABASE = join(user_data_dir("mbedls"), "mock.json")
DEFAULT_PLATFORM_DB = {
u'daplink': {
u'0001': u'LPC2368',
u'0002': u'LPC2368',
u'0003': u'LPC2368',
u'0004': u'LPC2368',
u'0005': u'LPC2368',
u'0006': u'LPC2368',
u'0007': u'LPC2368',
u'0100': u'LPC2368',
u'0183': u'UBLOX_C027',
u'0200': u'KL25Z',
u'0201': u'KW41Z',
u'0210': u'KL05Z',
u'0214': u'HEXIWEAR',
u'0217': u'K82F',
u'0218': u'KL82Z',
u'0220': u'KL46Z',
u'0227': u'MIMXRT1050_EVK',
u'0228': u'RAPIDIOT_K64F',
u'0230': u'K20D50M',
u'0231': u'K22F',
u'0234': u'RAPIDIOT_KW41Z',
u'0240': u'K64F',
u'0245': u'K64F',
u'0250': u'KW24D',
u'0261': u'KL27Z',
u'0262': u'KL43Z',
u'0300': u'MTS_GAMBIT',
u'0305': u'MTS_MDOT_F405RG',
u'0310': u'MTS_DRAGONFLY_F411RE',
u'0311': u'K66F',
u'0312': u'MTS_DRAGONFLY_L471QG',
u'0315': u'MTS_MDOT_F411RE',
u'0350': u'XDOT_L151CC',
u'0400': u'MAXWSNENV',
u'0405': u'MAX32600MBED',
u'0406': u'MAX32620MBED',
u'0407': u'MAX32620HSP',
u'0408': u'MAX32625NEXPAQ',
u'0409': u'MAX32630FTHR',
u'0410': u'ETTEPLAN_LORA',
u'0415': u'MAX32625MBED',
u'0416': u'MAX32625PICO',
u'0417': u'MAX32630MBED',
u'0418': u'MAX32620FTHR',
u'0419': u'MAX35103EVKIT2',
u'0420': u'MAX32630HSP3',
u'0450': u'MTB_UBLOX_ODIN_W2',
u'0451': u'MTB_MXCHIP_EMW3166',
u'0452': u'MTB_LAIRD_BL600',
u'0453': u'MTB_MTS_XDOT',
u'0454': u'MTB_MTS_DRAGONFLY',
u'0455': u'MTB_UBLOX_NINA_B1',
u'0456': u'MTB_MURATA_ABZ',
u'0457': u'MTB_RAK811',
u'0458': u'MTB_ADV_WISE_1510',
u'0459': u'MTB_ADV_WISE_1530',
u'0460': u'MTB_ADV_WISE_1570',
u'0461': u'MTB_LAIRD_BL652',
u'0462': u'MTB_USI_WM_BN_BM_22',
u'0465': u'MTB_LAIRD_BL654',
u'0466': u'MTB_MURATA_WSM_BL241',
u'0472': u'MTB_ACONNO_ACN52832',
u'0500': u'SPANSION_PLACEHOLDER',
u'0505': u'SPANSION_PLACEHOLDER',
u'0510': u'SPANSION_PLACEHOLDER',
u'0602': u'EV_COG_AD3029LZ',
u'0603': u'EV_COG_AD4050LZ',
u'0700': u'NUCLEO_F103RB',
u'0705': u'NUCLEO_F302R8',
u'0710': u'NUCLEO_L152RE',
u'0715': u'NUCLEO_L053R8',
u'0720': u'NUCLEO_F401RE',
u'0725': u'NUCLEO_F030R8',
u'0730': u'NUCLEO_F072RB',
u'0735': u'NUCLEO_F334R8',
u'0740': u'NUCLEO_F411RE',
u'0742': u'NUCLEO_F413ZH',
u'0743': u'DISCO_F413ZH',
u'0744': u'NUCLEO_F410RB',
u'0745': u'NUCLEO_F303RE',
u'0746': u'DISCO_F303VC',
u'0747': u'NUCLEO_F303ZE',
u'0750': u'NUCLEO_F091RC',
u'0755': u'NUCLEO_F070RB',
u'0760': u'NUCLEO_L073RZ',
u'0764': u'DISCO_L475VG_IOT01A',
u'0765': u'NUCLEO_L476RG',
u'0766': u'SILICA_SENSOR_NODE',
u'0770': u'NUCLEO_L432KC',
u'0774': u'DISCO_L4R9I',
u'0775': u'NUCLEO_F303K8',
u'0776': u'NUCLEO_L4R5ZI',
u'0777': u'NUCLEO_F446RE',
u'0778': u'NUCLEO_F446ZE',
u'0779': u'NUCLEO_L433RC_P',
u'0780': u'NUCLEO_L011K4',
u'0781': u'NUCLEO_L4R5ZI_P',
u'0785': u'NUCLEO_F042K6',
u'0788': u'DISCO_F469NI',
u'0790': u'NUCLEO_L031K6',
u'0791': u'NUCLEO_F031K6',
u'0795': u'DISCO_F429ZI',
u'0796': u'NUCLEO_F429ZI',
u'0797': u'NUCLEO_F439ZI',
u'0799': u'ST_PLACEHOLDER',
u'0805': u'DISCO_L053C8',
u'0810': u'DISCO_F334C8',
u'0812': u'NUCLEO_F722ZE',
u'0813': u'NUCLEO_H743ZI',
u'0815': u'DISCO_F746NG',
u'0816': u'NUCLEO_F746ZG',
u'0817': u'DISCO_F769NI',
u'0818': u'NUCLEO_F767ZI',
u'0820': u'DISCO_L476VG',
u'0821': u'NUCLEO_L452RE',
u'0822': u'DISCO_L496AG',
u'0823': u'NUCLEO_L496ZG',
u'0824': u'LPC824',
u'8012': u'TT_M3HQ',
u'0826': u'NUCLEO_F412ZG',
u'0827': u'NUCLEO_L486RG',
u'0828': u'NUCLEO_L496ZG_P',
u'0829': u'NUCLEO_L452RE_P',
u'0830': u'DISCO_F407VG',
u'0833': u'DISCO_L072CZ_LRWAN1',
u'0835': u'NUCLEO_F207ZG',
u'0839': u'NUCLEO_WB55RG',
u'0840': u'B96B_F446VE',
u'0879': u'NUCLEO_F756ZG',
u'0900': u'XPRO_SAMR21',
u'0905': u'XPRO_SAMW25',
u'0910': u'XPRO_SAML21',
u'0915': u'XPRO_SAMD21',
u'1000': u'LPC2368',
u'1001': u'LPC2368',
u'1010': u'LPC1768',
u'1017': u'HRM1017',
u'1018': u'SSCI824',
u'1019': u'TY51822R3',
u'1022': u'RO359B',
u'1034': u'LPC11U34',
u'1040': u'LPC11U24',
u'1045': u'LPC11U24',
u'1050': u'LPC812',
u'1054': u'LPC54114',
u'1056': u'LPC546XX',
u'1060': u'LPC4088',
u'1061': u'LPC11U35_401',
u'1062': u'LPC4088_DM',
u'1070': u'NRF51822',
u'1075': u'NRF51822_OTA',
u'1080': u'OC_MBUINO',
u'1090': u'RBLAB_NRF51822',
u'1093': u'RBLAB_BLENANO2',
u'1095': u'RBLAB_BLENANO',
u'1100': u'NRF51_DK',
u'1101': u'NRF52_DK',
u'1102': u'NRF52840_DK',
u'1105': u'NRF51_DK_OTA',
u'1114': u'LPC1114',
u'1120': u'NRF51_DONGLE',
u'1130': u'NRF51822_SBK',
u'1140': u'WALLBOT_BLE',
u'1168': u'LPC11U68',
u'1200': u'NCS36510',
u'1234': u'UBLOX_C027',
u'1235': u'UBLOX_C027',
u'1236': u'UBLOX_EVK_ODIN_W2',
u'1237': u'UBLOX_EVK_NINA_B1',
u'1300': u'NUC472-NUTINY',
u'1301': u'NUMBED',
u'1302': u'NUMAKER_PFM_NUC472',
u'1303': u'NUMAKER_PFM_M453',
u'1304': u'NUMAKER_PFM_M487',
u'1305': u'NUMAKER_PFM_M2351',
u'1306': u'NUMAKER_PFM_NANO130',
u'1307': u'NUMAKER_PFM_NUC240',
u'1308': u'NUMAKER_IOT_M487',
u'1549': u'LPC1549',
u'1600': u'LPC4330_M4',
u'1605': u'LPC4330_M4',
u'1701': u'GD32_F307VG',
u'1702': u'GD32_F450ZI',
u'2000': u'EFM32_G8XX_STK',
u'2005': u'EFM32HG_STK3400',
u'2010': u'EFM32WG_STK3800',
u'2015': u'EFM32GG_STK3700',
u'2020': u'EFM32LG_STK3600',
u'2025': u'EFM32TG_STK3300',
u'2030': u'EFM32ZG_STK3200',
u'2035': u'EFM32PG_STK3401',
u'2040': u'EFM32PG12_STK3402',
u'2041': u'TB_SENSE_12',
u'2045': u'TB_SENSE_1',
u'2100': u'XBED_LPC1768',
u'2201': u'WIZWIKI_W7500',
u'2202': u'WIZWIKI_W7500ECO',
u'2203': u'WIZWIKI_W7500P',
u'2500': u'ADV_WISE_1570',
u'3001': u'LPC11U24',
u'3101': u'SDT32620B',
u'3102': u'SDT32625B',
u'3103': u'SDT51822B',
u'3104': u'SDT52832B',
u'3105': u'SDT64B',
u'3106': u'SDT8195B',
u'3108': u'SDT32429B',
u'3110': u'SDT32439B',
u'3300': u'CC3220SF',
u'4000': u'LPC11U35_Y5_MBUG',
u'4005': u'NRF51822_Y5_MBUG',
u'4100': u'MOTE_L152RC',
u'4337': u'LPC4337',
u'4500': u'DELTA_DFCM_NNN40',
u'4501': u'DELTA_DFBM_NQ620',
u'4502': u'DELTA_DFCM_NNN50',
u'4600': u'REALTEK_RTL8195AM',
u'5000': u'ARM_MPS2',
u'5001': u'ARM_MPS2_M0',
u'5002': u'ARM_BEETLE_SOC',
u'5003': u'ARM_MPS2_M0P',
u'5005': u'ARM_MPS2_M0DS',
u'5006': u'ARM_MUSCA_A1',
u'5007': u'ARM_MPS2_M1',
u'5009': u'ARM_MPS2_M3',
u'5011': u'ARM_MPS2_M4',
u'5015': u'ARM_MPS2_M7',
u'5020': u'HOME_GATEWAY_6LOWPAN',
u'5500': u'RZ_A1H',
u'5501': u'GR_LYCHEE',
u'6000': u'FUTURE_SEQUANA',
u'6660': u'NZ32_SC151',
u'7010': u'BLUENINJA_CDP_TZ01B',
u'7011': u'TMPM066',
u'7013': u'TMPM46B',
u'7402': u'MBED_BR_HAT',
u'7778': u'TEENSY3_1',
u'8001': u'UNO_91H',
u'8002': u'UNO_81C',
u'8003': u'UNO_81AM',
u'8004': u'UNO_81A',
u'8080': u'FF1705_L151CC',
u'8081': u'FF_LPC546XX',
u'9001': u'LPC1347',
u'9002': u'LPC11U24',
u'9003': u'LPC1347',
u'9004': u'ARCH_PRO',
u'9006': u'LPC11U24',
u'9007': u'LPC11U35_501',
u'9008': u'XADOW_M0',
u'9009': u'ARCH_BLE',
u'9010': u'ARCH_GPRS',
u'9011': u'ARCH_MAX',
u'9012': u'SEEED_TINY_BLE',
u'9014': u'WIO_3G',
u'9015': u'WIO_BG96',
u'9900': u'NRF51_MICROBIT',
u'C002': u'VK_RZ_A1H',
u'C005': u'MTM_MTCONNECT04S',
u'C006': u'VBLUNO51',
u'C008': u'SAKURAIO_EVB_01',
u'C030': u'UBLOX_C030_U201',
u'C031': u'UBLOX_C030_N211',
u'C032': u'UBLOX_C030_R404M',
u'C033': u'UBLOX_C030_R410M',
u'C034': u'UBLOX_C030_S200',
u'C035': u'UBLOX_C030_R3121',
u'FFFF': u'K20 BOOTLOADER',
u'RIOT': u'RIOT',
},
u'jlink': {
u'X729475D28G': {
u'platform_name': u'NRF51_DK',
u'jlink_device_name': u'nRF51422_xxAC'
},
u'X349858SLYN': {
u'platform_name': u'NRF52_DK',
u'jlink_device_name': u'nRF52832_xxaa'
},
u'FRDM-KL25Z': {
u'platform_name': u'KL25Z',
u'jlink_device_name': u'MKL25Z128xxx4'
},
u'FRDM-KL27Z': {
u'platform_name': u'KL27Z',
u'jlink_device_name': u'MKL27Z64xxx4'
},
u'FRDM-KL43Z': {
u'platform_name': u'KL43Z',
u'jlink_device_name': u'MKL43Z256xxx4'
}
},
u'atmel': {
u'2241': 'SAML21J18A'
}
}
def _get_modified_time(path):
try:
mtime = getmtime(path)
except OSError:
mtime = 0
return datetime.datetime.fromtimestamp(mtime)
def _older_than_me(path):
return _get_modified_time(path) < _get_modified_time(__file__)
def _modify_data_format(data, verbose_data, simple_data_key='platform_name'):
if isinstance(data, dict):
if verbose_data:
return data
return data[simple_data_key]
else:
if verbose_data:
return {
simple_data_key: data
}
return data
def _overwrite_or_open(db):
try:
if db is LOCAL_PLATFORM_DATABASE and _older_than_me(db):
raise ValueError("Platform Database is out of date")
with open(db, encoding="utf-8") as db_in:
return json.load(db_in)
except (IOError, ValueError) as exc:
if db is LOCAL_PLATFORM_DATABASE:
logger.warning(
"Error loading database %s: %s; Recreating", db, str(exc))
try:
makedirs(dirname(db))
except OSError:
pass
try:
with open(db, "w", encoding="utf-8") as out:
out.write(unicode(json.dumps(DEFAULT_PLATFORM_DB)))
except IOError:
pass
return copy(DEFAULT_PLATFORM_DB)
else:
return {}
class PlatformDatabase(object):
"""Represents a union of multiple platform database files.
Handles inter-process synchronization of database files.
"""
target_id_pattern = re.compile(r'^[a-fA-F0-9]{4}$')
def __init__(self, database_files, primary_database=None):
"""Construct a PlatformDatabase object from a series of platform database files"""
self._prim_db_prim_db = primary_database
if not self._prim_db_prim_db and len(database_files) == 1:
self._prim_db_prim_db = database_files[0]
self._dbs_dbs = OrderedDict()
self._keys_keys = defaultdict(set)
for db in database_files:
new_db = _overwrite_or_open(db)
first_value = None
if new_db.values():
first_value = next(iter(new_db.values()))
if not isinstance(first_value, dict):
new_db = {
'daplink': new_db
}
if new_db:
for device_type in new_db:
duplicates = self._keys_keys[device_type].intersection(set(new_db[device_type].keys()))
duplicates = set(["%s.%s" % (device_type, k) for k in duplicates])
if duplicates:
logger.warning(
"Duplicate platform ids found: %s,"
" ignoring the definitions from %s",
" ".join(duplicates), db)
self._dbs_dbs[db] = new_db
self._keys_keys[device_type] = self._keys_keys[device_type].union(new_db[device_type].keys())
else:
self._dbs_dbs[db] = new_db
def items(self, device_type='daplink'):
for db in self._dbs_dbs.values():
for entry in db.get(device_type, {}).items():
yield entry
def all_ids(self, device_type='daplink'):
return iter(self._keys_keys[device_type])
def get(self, index, default=None, device_type='daplink', verbose_data=False):
"""Standard lookup function. Works exactly like a dict. If 'verbose_data'
is True, all data for the platform is returned as a dict."""
for db in self._dbs_dbs.values():
if device_type in db:
maybe_answer = db[device_type].get(index, None)
if maybe_answer:
return _modify_data_format(maybe_answer, verbose_data)
return default
def _update_db(self):
if self._prim_db_prim_db:
lock = InterProcessLock("%s.lock" % self._prim_db_prim_db)
acquired = lock.acquire(blocking=False)
if not acquired:
logger.debug("Waiting 60 seconds for file lock")
acquired = lock.acquire(blocking=True, timeout=60)
if acquired:
try:
with open(self._prim_db_prim_db, "w", encoding="utf-8") as out:
out.write(unicode(
json.dumps(self._dbs_dbs[self._prim_db_prim_db])))
return True
finally:
lock.release()
else:
logger.error("Could not update platform database: "
"Lock acquire failed after 60 seconds")
return False
else:
logger.error("Can't update platform database: "
"destination database is ambiguous")
return False
def add(self, id, platform_name, permanent=False, device_type='daplink'):
"""Add a platform to this database, optionally updating an origin
database
"""
if self.target_id_patterntarget_id_pattern.match(id):
if self._prim_db_prim_db:
if device_type not in self._dbs_dbs[self._prim_db_prim_db]:
self._dbs_dbs[self._prim_db_prim_db][device_type] = {}
self._dbs_dbs[self._prim_db_prim_db][device_type][id] = platform_name
else:
cur_db = next(iter(self._dbs_dbs.values()))
if device_type not in cur_db:
cur_db[device_type] = {}
cur_db[device_type][id] = platform_name
self._keys_keys[device_type].add(id)
if permanent:
self._update_db_update_db()
else:
raise ValueError("Invald target id: %s" % id)
def remove(self, id, permanent=False, device_type='daplink', verbose_data=False):
"""Remove a platform from this database, optionally updating an origin
database. If 'verbose_data' is True, all data for the platform is returned
as a dict.
"""
logger.debug("Trying remove of %s", id)
if id == '*' and device_type in self._dbs_dbs[self._prim_db_prim_db]:
self._dbs_dbs[self._prim_db_prim_db][device_type] = {}
for db in self._dbs_dbs.values():
if device_type in db and id in db[device_type]:
logger.debug("Removing id...")
removed = db[device_type][id]
del db[device_type][id]
self._keys_keys[device_type].remove(id)
if permanent:
self._update_db_update_db()
return _modify_data_format(removed, verbose_data)
mbed_lstools.platform_database.PlatformDatabase
Definition: platform_database.py:396
mbed_lstools.platform_database.PlatformDatabase.remove
def remove(self, id, permanent=False, device_type='daplink', verbose_data=False)
Definition: platform_database.py:498
mbed_lstools.platform_database.PlatformDatabase._prim_db
_prim_db
Definition: platform_database.py:405
mbed_lstools.platform_database.PlatformDatabase.target_id_pattern
target_id_pattern
Definition: platform_database.py:401
mbed_lstools.platform_database.PlatformDatabase.all_ids
def all_ids(self, device_type='daplink')
Definition: platform_database.py:440
mbed_lstools.platform_database.PlatformDatabase.items
def items(self, device_type='daplink')
Definition: platform_database.py:435
mbed_lstools.platform_database.PlatformDatabase._update_db
def _update_db(self)
Definition: platform_database.py:454
mbed_lstools.platform_database.PlatformDatabase.get
def get(self, index, default=None, device_type='daplink', verbose_data=False)
Definition: platform_database.py:443
mbed_lstools.platform_database.PlatformDatabase._dbs
_dbs
Definition: platform_database.py:408
mbed_lstools.platform_database.PlatformDatabase.add
def add(self, id, platform_name, permanent=False, device_type='daplink')
Definition: platform_database.py:478
mbed_lstools.platform_database.PlatformDatabase._keys
_keys
Definition: platform_database.py:409
mbed_lstools.platform_database.PlatformDatabase.__init__
def __init__(self, database_files, primary_database=None)
Definition: platform_database.py:403
object
mbed_lstools.platform_database.unicode
unicode
Definition: platform_database.py:34