forked from platformio/platformio-core
Use package parser for package manager and LDF
This commit is contained in:
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import codecs
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -34,6 +33,7 @@ from platformio import exception, fs, util
|
|||||||
from platformio.builder.tools import platformio as piotool
|
from platformio.builder.tools import platformio as piotool
|
||||||
from platformio.compat import WINDOWS, hashlib_encode_data, string_types
|
from platformio.compat import WINDOWS, hashlib_encode_data, string_types
|
||||||
from platformio.managers.lib import LibraryManager
|
from platformio.managers.lib import LibraryManager
|
||||||
|
from platformio.package.manifest.parser import ManifestParserFactory
|
||||||
|
|
||||||
|
|
||||||
class LibBuilderFactory(object):
|
class LibBuilderFactory(object):
|
||||||
@ -456,17 +456,10 @@ class UnknownLibBuilder(LibBuilderBase):
|
|||||||
|
|
||||||
class ArduinoLibBuilder(LibBuilderBase):
|
class ArduinoLibBuilder(LibBuilderBase):
|
||||||
def load_manifest(self):
|
def load_manifest(self):
|
||||||
manifest = {}
|
|
||||||
if not isfile(join(self.path, "library.properties")):
|
|
||||||
return manifest
|
|
||||||
manifest_path = join(self.path, "library.properties")
|
manifest_path = join(self.path, "library.properties")
|
||||||
with codecs.open(manifest_path, encoding="utf-8") as fp:
|
if not isfile(manifest_path):
|
||||||
for line in fp.readlines():
|
return {}
|
||||||
if "=" not in line:
|
return ManifestParserFactory.new_from_file(manifest_path).as_dict()
|
||||||
continue
|
|
||||||
key, value = line.split("=", 1)
|
|
||||||
manifest[key.strip()] = value.strip()
|
|
||||||
return manifest
|
|
||||||
|
|
||||||
def get_include_dirs(self):
|
def get_include_dirs(self):
|
||||||
include_dirs = LibBuilderBase.get_include_dirs(self)
|
include_dirs = LibBuilderBase.get_include_dirs(self)
|
||||||
@ -510,24 +503,7 @@ class ArduinoLibBuilder(LibBuilderBase):
|
|||||||
return util.items_in_list(frameworks, ["arduino", "energia"])
|
return util.items_in_list(frameworks, ["arduino", "energia"])
|
||||||
|
|
||||||
def is_platforms_compatible(self, platforms):
|
def is_platforms_compatible(self, platforms):
|
||||||
platforms_map = {
|
items = self._manifest.get("platforms", [])
|
||||||
"avr": ["atmelavr"],
|
|
||||||
"sam": ["atmelsam"],
|
|
||||||
"samd": ["atmelsam"],
|
|
||||||
"esp8266": ["espressif8266"],
|
|
||||||
"esp32": ["espressif32"],
|
|
||||||
"arc32": ["intel_arc32"],
|
|
||||||
"stm32": ["ststm32"],
|
|
||||||
"nrf5": ["nordicnrf51", "nordicnrf52"],
|
|
||||||
}
|
|
||||||
items = []
|
|
||||||
for arch in self._manifest.get("architectures", "").split(","):
|
|
||||||
arch = arch.strip().lower()
|
|
||||||
if arch == "*":
|
|
||||||
items = "*"
|
|
||||||
break
|
|
||||||
if arch in platforms_map:
|
|
||||||
items.extend(platforms_map[arch])
|
|
||||||
if not items:
|
if not items:
|
||||||
return LibBuilderBase.is_platforms_compatible(self, platforms)
|
return LibBuilderBase.is_platforms_compatible(self, platforms)
|
||||||
return util.items_in_list(platforms, items)
|
return util.items_in_list(platforms, items)
|
||||||
@ -535,9 +511,10 @@ class ArduinoLibBuilder(LibBuilderBase):
|
|||||||
|
|
||||||
class MbedLibBuilder(LibBuilderBase):
|
class MbedLibBuilder(LibBuilderBase):
|
||||||
def load_manifest(self):
|
def load_manifest(self):
|
||||||
if not isfile(join(self.path, "module.json")):
|
manifest_path = join(self.path, "module.json")
|
||||||
|
if not isfile(manifest_path):
|
||||||
return {}
|
return {}
|
||||||
return fs.load_json(join(self.path, "module.json"))
|
return ManifestParserFactory.new_from_file(manifest_path).as_dict()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def include_dir(self):
|
def include_dir(self):
|
||||||
@ -682,20 +659,12 @@ class MbedLibBuilder(LibBuilderBase):
|
|||||||
|
|
||||||
class PlatformIOLibBuilder(LibBuilderBase):
|
class PlatformIOLibBuilder(LibBuilderBase):
|
||||||
def load_manifest(self):
|
def load_manifest(self):
|
||||||
assert isfile(join(self.path, "library.json"))
|
manifest_path = join(self.path, "library.json")
|
||||||
manifest = fs.load_json(join(self.path, "library.json"))
|
if not isfile(manifest_path):
|
||||||
assert "name" in manifest
|
return {}
|
||||||
|
return ManifestParserFactory.new_from_file(manifest_path).as_dict()
|
||||||
|
|
||||||
# replace "espressif" old name dev/platform with ESP8266
|
def _has_arduino_manifest(self):
|
||||||
if "platforms" in manifest:
|
|
||||||
manifest["platforms"] = [
|
|
||||||
"espressif8266" if p == "espressif" else p
|
|
||||||
for p in util.items_to_list(manifest["platforms"])
|
|
||||||
]
|
|
||||||
|
|
||||||
return manifest
|
|
||||||
|
|
||||||
def _is_arduino_manifest(self):
|
|
||||||
return isfile(join(self.path, "library.properties"))
|
return isfile(join(self.path, "library.properties"))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -718,7 +687,7 @@ class PlatformIOLibBuilder(LibBuilderBase):
|
|||||||
return self._manifest.get("build").get("srcFilter")
|
return self._manifest.get("build").get("srcFilter")
|
||||||
if self.env["SRC_FILTER"]:
|
if self.env["SRC_FILTER"]:
|
||||||
return self.env["SRC_FILTER"]
|
return self.env["SRC_FILTER"]
|
||||||
if self._is_arduino_manifest():
|
if self._has_arduino_manifest():
|
||||||
return ArduinoLibBuilder.src_filter.fget(self)
|
return ArduinoLibBuilder.src_filter.fget(self)
|
||||||
return LibBuilderBase.src_filter.fget(self)
|
return LibBuilderBase.src_filter.fget(self)
|
||||||
|
|
||||||
@ -789,7 +758,7 @@ class PlatformIOLibBuilder(LibBuilderBase):
|
|||||||
# backwards compatibility with PlatformIO 2.0
|
# backwards compatibility with PlatformIO 2.0
|
||||||
if (
|
if (
|
||||||
"build" not in self._manifest
|
"build" not in self._manifest
|
||||||
and self._is_arduino_manifest()
|
and self._has_arduino_manifest()
|
||||||
and not isdir(join(self.path, "src"))
|
and not isdir(join(self.path, "src"))
|
||||||
and isdir(join(self.path, "utility"))
|
and isdir(join(self.path, "utility"))
|
||||||
):
|
):
|
||||||
@ -954,9 +923,8 @@ def IsCompatibleLibBuilder(env, lb, verbose=int(ARGUMENTS.get("PIOVERBOSE", 0)))
|
|||||||
if verbose:
|
if verbose:
|
||||||
sys.stderr.write("Platform incompatible library %s\n" % lb.path)
|
sys.stderr.write("Platform incompatible library %s\n" % lb.path)
|
||||||
return False
|
return False
|
||||||
if (
|
if compat_mode in ("soft", "strict") and not lb.is_frameworks_compatible(
|
||||||
compat_mode in ("soft", "strict")
|
env.get("PIOFRAMEWORK", [])
|
||||||
and not lb.is_frameworks_compatible(env.get("PIOFRAMEWORK", []))
|
|
||||||
):
|
):
|
||||||
if verbose:
|
if verbose:
|
||||||
sys.stderr.write("Framework incompatible library %s\n" % lb.path)
|
sys.stderr.write("Framework incompatible library %s\n" % lb.path)
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
# pylint: disable=too-many-return-statements
|
# pylint: disable=too-many-return-statements
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import re
|
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from os.path import isdir, join
|
from os.path import isdir, join
|
||||||
|
|
||||||
@ -62,73 +61,6 @@ class LibraryManager(BasePkgManager):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def load_manifest(self, pkg_dir):
|
|
||||||
manifest = BasePkgManager.load_manifest(self, pkg_dir)
|
|
||||||
if not manifest:
|
|
||||||
return manifest
|
|
||||||
|
|
||||||
# if Arduino library.properties
|
|
||||||
if "sentence" in manifest:
|
|
||||||
manifest["frameworks"] = ["arduino"]
|
|
||||||
manifest["description"] = manifest["sentence"]
|
|
||||||
del manifest["sentence"]
|
|
||||||
|
|
||||||
if "author" in manifest:
|
|
||||||
if isinstance(manifest["author"], dict):
|
|
||||||
manifest["authors"] = [manifest["author"]]
|
|
||||||
else:
|
|
||||||
manifest["authors"] = [{"name": manifest["author"]}]
|
|
||||||
del manifest["author"]
|
|
||||||
|
|
||||||
if "authors" in manifest and not isinstance(manifest["authors"], list):
|
|
||||||
manifest["authors"] = [manifest["authors"]]
|
|
||||||
|
|
||||||
if "keywords" not in manifest:
|
|
||||||
keywords = []
|
|
||||||
for keyword in re.split(
|
|
||||||
r"[\s/]+", manifest.get("category", "Uncategorized")
|
|
||||||
):
|
|
||||||
keyword = keyword.strip()
|
|
||||||
if not keyword:
|
|
||||||
continue
|
|
||||||
keywords.append(keyword.lower())
|
|
||||||
manifest["keywords"] = keywords
|
|
||||||
if "category" in manifest:
|
|
||||||
del manifest["category"]
|
|
||||||
|
|
||||||
# don't replace VCS URL
|
|
||||||
if "url" in manifest and "description" in manifest:
|
|
||||||
manifest["homepage"] = manifest["url"]
|
|
||||||
del manifest["url"]
|
|
||||||
|
|
||||||
if "architectures" in manifest:
|
|
||||||
platforms = []
|
|
||||||
platforms_map = {
|
|
||||||
"avr": "atmelavr",
|
|
||||||
"sam": "atmelsam",
|
|
||||||
"samd": "atmelsam",
|
|
||||||
"esp8266": "espressif8266",
|
|
||||||
"esp32": "espressif32",
|
|
||||||
"arc32": "intel_arc32",
|
|
||||||
}
|
|
||||||
for arch in manifest["architectures"].split(","):
|
|
||||||
arch = arch.strip()
|
|
||||||
if arch == "*":
|
|
||||||
platforms = "*"
|
|
||||||
break
|
|
||||||
if arch in platforms_map:
|
|
||||||
platforms.append(platforms_map[arch])
|
|
||||||
manifest["platforms"] = platforms
|
|
||||||
del manifest["architectures"]
|
|
||||||
|
|
||||||
# convert listed items via comma to array
|
|
||||||
for key in ("keywords", "frameworks", "platforms"):
|
|
||||||
if key not in manifest or not isinstance(manifest[key], string_types):
|
|
||||||
continue
|
|
||||||
manifest[key] = [i.strip() for i in manifest[key].split(",") if i.strip()]
|
|
||||||
|
|
||||||
return manifest
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def normalize_dependencies(dependencies):
|
def normalize_dependencies(dependencies):
|
||||||
if not dependencies:
|
if not dependencies:
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import codecs
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@ -29,6 +28,10 @@ from platformio import __version__, app, exception, fs, telemetry, util
|
|||||||
from platformio.compat import hashlib_encode_data
|
from platformio.compat import hashlib_encode_data
|
||||||
from platformio.downloader import FileDownloader
|
from platformio.downloader import FileDownloader
|
||||||
from platformio.lockfile import LockFile
|
from platformio.lockfile import LockFile
|
||||||
|
from platformio.package.manifest.parser import (
|
||||||
|
ManifestParserError,
|
||||||
|
ManifestParserFactory,
|
||||||
|
)
|
||||||
from platformio.unpacker import FileUnpacker
|
from platformio.unpacker import FileUnpacker
|
||||||
from platformio.vcsclient import VCSClientFactory
|
from platformio.vcsclient import VCSClientFactory
|
||||||
|
|
||||||
@ -326,7 +329,7 @@ class PkgInstallerMixin(object):
|
|||||||
def manifest_exists(self, pkg_dir):
|
def manifest_exists(self, pkg_dir):
|
||||||
return self.get_manifest_path(pkg_dir) or self.get_src_manifest_path(pkg_dir)
|
return self.get_manifest_path(pkg_dir) or self.get_src_manifest_path(pkg_dir)
|
||||||
|
|
||||||
def load_manifest(self, pkg_dir):
|
def load_manifest(self, pkg_dir): # pylint: disable=too-many-branches
|
||||||
cache_key = "load_manifest-%s" % pkg_dir
|
cache_key = "load_manifest-%s" % pkg_dir
|
||||||
result = self.cache_get(cache_key)
|
result = self.cache_get(cache_key)
|
||||||
if result:
|
if result:
|
||||||
@ -342,15 +345,10 @@ class PkgInstallerMixin(object):
|
|||||||
if not manifest_path and not src_manifest_path:
|
if not manifest_path and not src_manifest_path:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if manifest_path and manifest_path.endswith(".json"):
|
try:
|
||||||
manifest = fs.load_json(manifest_path)
|
manifest = ManifestParserFactory.new_from_file(manifest_path).as_dict()
|
||||||
elif manifest_path and manifest_path.endswith(".properties"):
|
except ManifestParserError:
|
||||||
with codecs.open(manifest_path, encoding="utf-8") as fp:
|
pass
|
||||||
for line in fp.readlines():
|
|
||||||
if "=" not in line:
|
|
||||||
continue
|
|
||||||
key, value = line.split("=", 1)
|
|
||||||
manifest[key.strip()] = value.strip()
|
|
||||||
|
|
||||||
if src_manifest:
|
if src_manifest:
|
||||||
if "version" in src_manifest:
|
if "version" in src_manifest:
|
||||||
|
@ -46,6 +46,8 @@ class ManifestFileType(object):
|
|||||||
return ManifestFileType.MODULE_JSON
|
return ManifestFileType.MODULE_JSON
|
||||||
if uri.endswith("package.json"):
|
if uri.endswith("package.json"):
|
||||||
return ManifestFileType.PACKAGE_JSON
|
return ManifestFileType.PACKAGE_JSON
|
||||||
|
if uri.endswith("library.json"):
|
||||||
|
return ManifestFileType.LIBRARY_JSON
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -331,18 +333,16 @@ class LibraryJsonManifestParser(BaseManifestParser):
|
|||||||
class ModuleJsonManifestParser(BaseManifestParser):
|
class ModuleJsonManifestParser(BaseManifestParser):
|
||||||
def parse(self, contents):
|
def parse(self, contents):
|
||||||
data = json.loads(contents)
|
data = json.loads(contents)
|
||||||
return dict(
|
data["frameworks"] = ["mbed"]
|
||||||
name=data["name"],
|
data["platforms"] = ["*"]
|
||||||
version=data["version"],
|
data["export"] = {"exclude": ["tests", "test", "*.doxyfile", "*.pdf"]}
|
||||||
keywords=data.get("keywords"),
|
if "author" in data:
|
||||||
description=data["description"],
|
data["authors"] = self._parse_authors(data.get("author"))
|
||||||
frameworks=["mbed"],
|
del data["author"]
|
||||||
platforms=["*"],
|
if "licenses" in data:
|
||||||
homepage=data.get("homepage"),
|
data["license"] = self._parse_license(data.get("licenses"))
|
||||||
export={"exclude": ["tests", "test", "*.doxyfile", "*.pdf"]},
|
del data["licenses"]
|
||||||
authors=self._parse_authors(data.get("author")),
|
return data
|
||||||
license=self._parse_license(data.get("licenses")),
|
|
||||||
)
|
|
||||||
|
|
||||||
def _parse_authors(self, raw):
|
def _parse_authors(self, raw):
|
||||||
if not raw:
|
if not raw:
|
||||||
@ -364,23 +364,26 @@ class ModuleJsonManifestParser(BaseManifestParser):
|
|||||||
|
|
||||||
class LibraryPropertiesManifestParser(BaseManifestParser):
|
class LibraryPropertiesManifestParser(BaseManifestParser):
|
||||||
def parse(self, contents):
|
def parse(self, contents):
|
||||||
properties = self._parse_properties(contents)
|
data = self._parse_properties(contents)
|
||||||
repository = self._parse_repository(properties)
|
repository = self._parse_repository(data)
|
||||||
homepage = properties.get("url")
|
homepage = data.get("url")
|
||||||
if repository and repository["url"] == homepage:
|
if repository and repository["url"] == homepage:
|
||||||
homepage = None
|
homepage = None
|
||||||
return dict(
|
data.update(
|
||||||
|
dict(
|
||||||
frameworks=["arduino"],
|
frameworks=["arduino"],
|
||||||
homepage=homepage,
|
homepage=homepage,
|
||||||
repository=repository or None,
|
repository=repository or None,
|
||||||
name=properties.get("name"),
|
description=self._parse_description(data),
|
||||||
version=properties.get("version"),
|
platforms=self._parse_platforms(data) or ["*"],
|
||||||
description=self._parse_description(properties),
|
keywords=self._parse_keywords(data),
|
||||||
platforms=self._parse_platforms(properties) or ["*"],
|
|
||||||
keywords=self._parse_keywords(properties),
|
|
||||||
authors=self._parse_authors(properties) or None,
|
|
||||||
export=self._parse_export(),
|
export=self._parse_export(),
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
if "author" in data:
|
||||||
|
data["authors"] = self._parse_authors(data)
|
||||||
|
del data["author"]
|
||||||
|
return data
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_properties(contents):
|
def _parse_properties(contents):
|
||||||
|
@ -31,7 +31,11 @@ def test_library_json_parser():
|
|||||||
"platforms": ["atmelavr", "espressif"],
|
"platforms": ["atmelavr", "espressif"],
|
||||||
"url": "http://old.url.format",
|
"url": "http://old.url.format",
|
||||||
"exclude": [".gitignore", "tests"],
|
"exclude": [".gitignore", "tests"],
|
||||||
"include": "mylib"
|
"include": "mylib",
|
||||||
|
"build": {
|
||||||
|
"flags": ["-DHELLO"]
|
||||||
|
},
|
||||||
|
"customField": "Custom Value"
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
mp = parser.LibraryJsonManifestParser(contents)
|
mp = parser.LibraryJsonManifestParser(contents)
|
||||||
@ -43,6 +47,8 @@ def test_library_json_parser():
|
|||||||
"export": {"exclude": [".gitignore", "tests"], "include": ["mylib"]},
|
"export": {"exclude": [".gitignore", "tests"], "include": ["mylib"]},
|
||||||
"keywords": ["kw1", "kw2", "kw3"],
|
"keywords": ["kw1", "kw2", "kw3"],
|
||||||
"homepage": "http://old.url.format",
|
"homepage": "http://old.url.format",
|
||||||
|
"build": {"flags": ["-DHELLO"]},
|
||||||
|
"customField": "Custom Value",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -89,9 +95,11 @@ def test_module_json_parser():
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git@github.com:username/repo.git"
|
"url": "git@github.com:username/repo.git"
|
||||||
},
|
},
|
||||||
"version": "1.2.3"
|
"version": "1.2.3",
|
||||||
|
"customField": "Custom Value"
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
mp = parser.ModuleJsonManifestParser(contents)
|
mp = parser.ModuleJsonManifestParser(contents)
|
||||||
assert not jsondiff.diff(
|
assert not jsondiff.diff(
|
||||||
mp.as_dict(),
|
mp.as_dict(),
|
||||||
@ -106,6 +114,8 @@ def test_module_json_parser():
|
|||||||
"export": {"exclude": ["tests", "test", "*.doxyfile", "*.pdf"]},
|
"export": {"exclude": ["tests", "test", "*.doxyfile", "*.pdf"]},
|
||||||
"authors": [{"email": "name@surname.com", "name": "Name Surname"}],
|
"authors": [{"email": "name@surname.com", "name": "Name Surname"}],
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
|
"repository": {"type": "git", "url": "git@github.com:username/repo.git"},
|
||||||
|
"customField": "Custom Value",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -117,6 +127,7 @@ name=TestPackage
|
|||||||
version=1.2.3
|
version=1.2.3
|
||||||
author=SomeAuthor <info AT author.com>
|
author=SomeAuthor <info AT author.com>
|
||||||
sentence=This is Arduino library
|
sentence=This is Arduino library
|
||||||
|
customField=Custom Value
|
||||||
"""
|
"""
|
||||||
mp = parser.LibraryPropertiesManifestParser(contents)
|
mp = parser.LibraryPropertiesManifestParser(contents)
|
||||||
assert not jsondiff.diff(
|
assert not jsondiff.diff(
|
||||||
@ -125,6 +136,7 @@ sentence=This is Arduino library
|
|||||||
"name": "TestPackage",
|
"name": "TestPackage",
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"description": "This is Arduino library",
|
"description": "This is Arduino library",
|
||||||
|
"sentence": "This is Arduino library",
|
||||||
"platforms": ["*"],
|
"platforms": ["*"],
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"export": {
|
"export": {
|
||||||
@ -132,6 +144,7 @@ sentence=This is Arduino library
|
|||||||
},
|
},
|
||||||
"authors": [{"email": "info@author.com", "name": "SomeAuthor"}],
|
"authors": [{"email": "info@author.com", "name": "SomeAuthor"}],
|
||||||
"keywords": ["uncategorized"],
|
"keywords": ["uncategorized"],
|
||||||
|
"customField": "Custom Value",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user