summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Ennis <james.ennis@codethink.co.uk>2019-03-07 11:09:27 +0000
committerJames Ennis <james.ennis@codethink.co.uk>2019-03-07 12:26:29 +0000
commit26284f7fc2ea9ae4121a37e4fc57093f6edc8448 (patch)
tree053a661a6d4345372de20c0157246808abfb56f8
parent5370740fc1eef6daf144831b148f13f883ebcd42 (diff)
downloadbuildstream-jennis/move_node_get_project_path.tar.gz
_yaml.py: Move node_get_project_path to project.pyjennis/move_node_get_project_path
_yaml.node_get_project_path() is currently only used by Project and by Plugin. This function has been moved to Project._get_path_from_node() and no longers requires a project directory as argument.
-rw-r--r--buildstream/_project.py105
-rw-r--r--buildstream/_yaml.py97
-rw-r--r--buildstream/plugin.py7
3 files changed, 103 insertions, 106 deletions
diff --git a/buildstream/_project.py b/buildstream/_project.py
index 6df54f70f..6cbba497f 100644
--- a/buildstream/_project.py
+++ b/buildstream/_project.py
@@ -20,8 +20,10 @@
import gc
import os
+import sys
from collections import OrderedDict
from collections.abc import Mapping
+from pathlib import Path
from pluginbase import PluginBase
from . import utils
from . import _cachekey
@@ -227,6 +229,100 @@ class Project():
return self._cache_key
+ # get_path_from_node()
+ #
+ # Fetches the project path from a dictionary node and validates it
+ #
+ # Paths are asserted to never lead to a directory outside of the project
+ # directory. In addition, paths can not point to symbolic links, fifos,
+ # sockets and block/character devices.
+ #
+ # The `check_is_file` and `check_is_dir` parameters can be used to
+ # perform additional validations on the path. Note that an exception
+ # will always be raised if both parameters are set to ``True``.
+ #
+ # Args:
+ # node (dict): A dictionary loaded from YAML
+ # key (str): The key whose value contains a path to validate
+ # check_is_file (bool): If ``True`` an error will also be raised
+ # if path does not point to a regular file.
+ # Defaults to ``False``
+ # check_is_dir (bool): If ``True`` an error will be also raised
+ # if path does not point to a directory.
+ # Defaults to ``False``
+ # Returns:
+ # (str): The project path
+ #
+ # Raises:
+ # (LoadError): In case that the project path is not valid or does not
+ # exist
+ #
+ def get_path_from_node(self, node, key, *,
+ check_is_file=False, check_is_dir=False):
+ path_str = _yaml.node_get(node, str, key)
+ path = Path(path_str)
+ project_dir_path = Path(self.directory)
+
+ provenance = _yaml.node_get_provenance(node, key=key)
+
+ if (project_dir_path / path).is_symlink():
+ raise LoadError(LoadErrorReason.PROJ_PATH_INVALID_KIND,
+ "{}: Specified path '{}' must not point to "
+ "symbolic links "
+ .format(provenance, path_str))
+
+ if path.parts and path.parts[0] == '..':
+ raise LoadError(LoadErrorReason.PROJ_PATH_INVALID,
+ "{}: Specified path '{}' first component must "
+ "not be '..'"
+ .format(provenance, path_str))
+
+ try:
+ full_path = (project_dir_path / path)
+ if sys.version_info[0] == 3 and sys.version_info[1] < 6:
+ full_resolved_path = full_path.resolve()
+ else:
+ full_resolved_path = full_path.resolve(strict=True) # pylint: disable=unexpected-keyword-arg
+ except FileNotFoundError:
+ raise LoadError(LoadErrorReason.MISSING_FILE,
+ "{}: Specified path '{}' does not exist"
+ .format(provenance, path_str))
+
+ is_inside = project_dir_path.resolve() in full_resolved_path.parents or (
+ full_resolved_path == project_dir_path)
+
+ if not is_inside:
+ raise LoadError(LoadErrorReason.PROJ_PATH_INVALID,
+ "{}: Specified path '{}' must not lead outside of the "
+ "project directory"
+ .format(provenance, path_str))
+
+ if path.is_absolute():
+ raise LoadError(LoadErrorReason.PROJ_PATH_INVALID,
+ "{}: Absolute path: '{}' invalid.\n"
+ "Please specify a path relative to the project's root."
+ .format(provenance, path))
+
+ if full_resolved_path.is_socket() or (
+ full_resolved_path.is_fifo() or
+ full_resolved_path.is_block_device()):
+ raise LoadError(LoadErrorReason.PROJ_PATH_INVALID_KIND,
+ "{}: Specified path '{}' points to an unsupported "
+ "file kind"
+ .format(provenance, path_str))
+
+ if check_is_file and not full_resolved_path.is_file():
+ raise LoadError(LoadErrorReason.PROJ_PATH_INVALID_KIND,
+ "{}: Specified path '{}' is not a regular file"
+ .format(provenance, path_str))
+
+ if check_is_dir and not full_resolved_path.is_dir():
+ raise LoadError(LoadErrorReason.PROJ_PATH_INVALID_KIND,
+ "{}: Specified path '{}' is not a directory"
+ .format(provenance, path_str))
+
+ return path_str
+
def _validate_node(self, node):
_yaml.node_validate(node, [
'format-version',
@@ -508,8 +604,8 @@ class Project():
self.element_path = os.path.join(
self.directory,
- _yaml.node_get_project_path(pre_config_node, 'element-path', self.directory,
- check_is_dir=True)
+ self.get_path_from_node(pre_config_node, 'element-path',
+ check_is_dir=True)
)
self.config.options = OptionPool(self.element_path)
@@ -857,9 +953,8 @@ class Project():
if group in origin_dict:
del origin_dict[group]
if origin_dict['origin'] == 'local':
- path = _yaml.node_get_project_path(origin, 'path',
- self.directory,
- check_is_dir=True)
+ path = self.get_path_from_node(origin, 'path',
+ check_is_dir=True)
# paths are passed in relative to the project, but must be absolute
origin_dict['path'] = os.path.join(self.directory, path)
destination.append(origin_dict)
diff --git a/buildstream/_yaml.py b/buildstream/_yaml.py
index 74ed1bbf8..fc24a223b 100644
--- a/buildstream/_yaml.py
+++ b/buildstream/_yaml.py
@@ -22,7 +22,6 @@ import collections
import string
from copy import deepcopy
from contextlib import ExitStack
-from pathlib import Path
from ruamel import yaml
from ruamel.yaml.representer import SafeRepresenter, RoundTripRepresenter
@@ -414,102 +413,6 @@ def node_get(node, expected_type, key, indices=None, *, default_value=_sentinel,
return value
-# node_get_project_path()
-#
-# Fetches a project path from a dictionary node and validates it
-#
-# Paths are asserted to never lead to a directory outside of the project
-# directory. In addition, paths can not point to symbolic links, fifos,
-# sockets and block/character devices.
-#
-# The `check_is_file` and `check_is_dir` parameters can be used to
-# perform additional validations on the path. Note that an exception
-# will always be raised if both parameters are set to ``True``.
-#
-# Args:
-# node (dict): A dictionary loaded from YAML
-# key (str): The key whose value contains a path to validate
-# project_dir (str): The project directory
-# check_is_file (bool): If ``True`` an error will also be raised
-# if path does not point to a regular file.
-# Defaults to ``False``
-# check_is_dir (bool): If ``True`` an error will be also raised
-# if path does not point to a directory.
-# Defaults to ``False``
-# Returns:
-# (str): The project path
-#
-# Raises:
-# (LoadError): In case that the project path is not valid or does not
-# exist
-#
-def node_get_project_path(node, key, project_dir, *,
- check_is_file=False, check_is_dir=False):
- path_str = node_get(node, str, key)
- path = Path(path_str)
- project_dir_path = Path(project_dir)
-
- provenance = node_get_provenance(node, key=key)
-
- if (project_dir_path / path).is_symlink():
- raise LoadError(LoadErrorReason.PROJ_PATH_INVALID_KIND,
- "{}: Specified path '{}' must not point to "
- "symbolic links "
- .format(provenance, path_str))
-
- if path.parts and path.parts[0] == '..':
- raise LoadError(LoadErrorReason.PROJ_PATH_INVALID,
- "{}: Specified path '{}' first component must "
- "not be '..'"
- .format(provenance, path_str))
-
- try:
- full_path = (project_dir_path / path)
- if sys.version_info[0] == 3 and sys.version_info[1] < 6:
- full_resolved_path = full_path.resolve()
- else:
- full_resolved_path = full_path.resolve(strict=True) # pylint: disable=unexpected-keyword-arg
- except FileNotFoundError:
- raise LoadError(LoadErrorReason.MISSING_FILE,
- "{}: Specified path '{}' does not exist"
- .format(provenance, path_str))
-
- is_inside = project_dir_path.resolve() in full_resolved_path.parents or (
- full_resolved_path == project_dir_path)
-
- if not is_inside:
- raise LoadError(LoadErrorReason.PROJ_PATH_INVALID,
- "{}: Specified path '{}' must not lead outside of the "
- "project directory"
- .format(provenance, path_str))
-
- if path.is_absolute():
- raise LoadError(LoadErrorReason.PROJ_PATH_INVALID,
- "{}: Absolute path: '{}' invalid.\n"
- "Please specify a path relative to the project's root."
- .format(provenance, path))
-
- if full_resolved_path.is_socket() or (
- full_resolved_path.is_fifo() or
- full_resolved_path.is_block_device()):
- raise LoadError(LoadErrorReason.PROJ_PATH_INVALID_KIND,
- "{}: Specified path '{}' points to an unsupported "
- "file kind"
- .format(provenance, path_str))
-
- if check_is_file and not full_resolved_path.is_file():
- raise LoadError(LoadErrorReason.PROJ_PATH_INVALID_KIND,
- "{}: Specified path '{}' is not a regular file"
- .format(provenance, path_str))
-
- if check_is_dir and not full_resolved_path.is_dir():
- raise LoadError(LoadErrorReason.PROJ_PATH_INVALID_KIND,
- "{}: Specified path '{}' is not a directory"
- .format(provenance, path_str))
-
- return path_str
-
-
# node_items()
#
# A convenience generator for iterating over loaded key/value
diff --git a/buildstream/plugin.py b/buildstream/plugin.py
index c21ae939e..f5daf31bf 100644
--- a/buildstream/plugin.py
+++ b/buildstream/plugin.py
@@ -420,10 +420,9 @@ class Plugin():
"""
- return _yaml.node_get_project_path(node, key,
- self.__project.directory,
- check_is_file=check_is_file,
- check_is_dir=check_is_dir)
+ return self.__project.get_path_from_node(node, key,
+ check_is_file=check_is_file,
+ check_is_dir=check_is_dir)
def node_validate(self, node, valid_keys):
"""This should be used in :func:`~buildstream.plugin.Plugin.configure`