[Notes] [Git][BuildStream/buildstream][mandatory_suffix] 4 commits: loadelement.py & loader: Added file suffix check



Title: GitLab

Phillip Smyth pushed to branch mandatory_suffix at BuildStream / buildstream

Commits:

8 changed files:

Changes:

  • NEWS
    ... ... @@ -2,6 +2,10 @@
    2 2
     buildstream 1.3.1
    
    3 3
     =================
    
    4 4
     
    
    5
    +  o BREAKING CHANGE: Attempting to use an element that does not have the `.bst`
    
    6
    +    extension, will result in an error message.
    
    7
    +    All elements must now be suffixed with `.bst`
    
    8
    +
    
    5 9
       o BREAKING CHANGE: The 'manual' element lost its default 'MAKEFLAGS' and 'V'
    
    6 10
         environment variables. There is already a 'make' element with the same
    
    7 11
         variables. Note that this is a breaking change, it will require users to
    

  • buildstream/_frontend/cli.py
    ... ... @@ -109,7 +109,11 @@ def complete_target(args, incomplete):
    109 109
         if element_directory:
    
    110 110
             base_directory = os.path.join(base_directory, element_directory)
    
    111 111
     
    
    112
    -    return complete_path("File", incomplete, base_directory=base_directory)
    
    112
    +    complete_list = []
    
    113
    +    for p in complete_path("File", incomplete, base_directory=base_directory):
    
    114
    +        if p.endswith(".bst ") or p.endswith("/") or p.endswith(".conf "):
    
    115
    +            complete_list.append(p)
    
    116
    +    return complete_list
    
    113 117
     
    
    114 118
     
    
    115 119
     def override_completions(cmd, cmd_param, args, incomplete):
    

  • buildstream/_loader/loadelement.py
    ... ... @@ -145,11 +145,14 @@ def _extract_depends_from_node(node, *, key=None):
    145 145
     
    
    146 146
         depends = _yaml.node_get(node, list, key, default_value=[])
    
    147 147
         output_deps = []
    
    148
    +    invalid_elements = []
    
    148 149
     
    
    149 150
         for index, dep in enumerate(depends):
    
    150 151
             dep_provenance = _yaml.node_get_provenance(node, key=key, indices=[index])
    
    151 152
     
    
    152 153
             if isinstance(dep, str):
    
    154
    +            if not dep.endswith(".bst"):
    
    155
    +                invalid_elements.append(dep)
    
    153 156
                 dependency = Dependency(dep, provenance=dep_provenance, dep_type=default_dep_type)
    
    154 157
     
    
    155 158
             elif isinstance(dep, Mapping):
    
    ... ... @@ -182,6 +185,11 @@ def _extract_depends_from_node(node, *, key=None):
    182 185
     
    
    183 186
             output_deps.append(dependency)
    
    184 187
     
    
    188
    +    if invalid_elements:
    
    189
    +        raise LoadError(LoadErrorReason.INVALID_DATA,
    
    190
    +                        "Target elements '{}' do not have expected file extension `.bst`\n"
    
    191
    +                        "Improperly named elements will not be discoverable by commands".format(invalid_elements))
    
    192
    +
    
    185 193
         # Now delete the field, we dont want it anymore
    
    186 194
         del node[key]
    
    187 195
     
    

  • buildstream/_loader/loader.py
    ... ... @@ -97,6 +97,7 @@ class Loader():
    97 97
         # Returns: The toplevel LoadElement
    
    98 98
         def load(self, targets, rewritable=False, ticker=None, fetch_subprojects=False):
    
    99 99
     
    
    100
    +        invalid_elements = []
    
    100 101
             for filename in targets:
    
    101 102
                 if os.path.isabs(filename):
    
    102 103
                     # XXX Should this just be an assertion ?
    
    ... ... @@ -106,6 +107,13 @@ class Loader():
    106 107
                                     "path to the base project directory: {}"
    
    107 108
                                     .format(filename, self._basedir))
    
    108 109
     
    
    110
    +            if not filename.endswith(".bst") and not filename.endswith("/") and not filename.endswith(".conf"):
    
    111
    +                invalid_elements.append(filename)
    
    112
    +
    
    113
    +        if invalid_elements:
    
    114
    +            raise LoadError(LoadErrorReason.INVALID_DATA,
    
    115
    +                            "Target elements '{}' do not have expected file extension `.bst`\n"
    
    116
    +                            "Improperly named elements will not be discoverable by commands".format(invalid_elements))
    
    109 117
             # First pass, recursively load files and populate our table of LoadElements
    
    110 118
             #
    
    111 119
             deps = []
    

  • tests/completions/completions.py
    ... ... @@ -66,6 +66,16 @@ PROJECT_ELEMENTS = [
    66 66
         "target.bst"
    
    67 67
     ]
    
    68 68
     
    
    69
    +INVALID_ELEMENT = [
    
    70
    +    "target.foo"
    
    71
    +    "compose-all.bst",
    
    72
    +    "compose-exclude-dev.bst",
    
    73
    +    "compose-include-bin.bst",
    
    74
    +    "import-bin.bst",
    
    75
    +    "import-dev.bst",
    
    76
    +    "target.bst"
    
    77
    +]
    
    78
    +
    
    69 79
     
    
    70 80
     def assert_completion(cli, cmd, word_idx, expected, cwd=None):
    
    71 81
         result = cli.run(cwd=cwd, env={
    
    ... ... @@ -85,6 +95,24 @@ def assert_completion(cli, cmd, word_idx, expected, cwd=None):
    85 95
         assert words == expected
    
    86 96
     
    
    87 97
     
    
    98
    +def assert_completion_failed(cli, cmd, word_idx, expected, cwd=None):
    
    99
    +    result = cli.run(cwd=cwd, env={
    
    100
    +        '_BST_COMPLETION': 'complete',
    
    101
    +        'COMP_WORDS': cmd,
    
    102
    +        'COMP_CWORD': str(word_idx)
    
    103
    +    })
    
    104
    +    words = []
    
    105
    +    if result.output:
    
    106
    +        words = result.output.splitlines()
    
    107
    +
    
    108
    +    # The order is meaningless, bash will
    
    109
    +    # take the results and order it by its
    
    110
    +    # own little heuristics
    
    111
    +    words = sorted(words)
    
    112
    +    expected = sorted(expected)
    
    113
    +    assert words != expected
    
    114
    +
    
    115
    +
    
    88 116
     @pytest.mark.parametrize("cmd,word_idx,expected", [
    
    89 117
         ('bst', 0, []),
    
    90 118
         ('bst ', 1, MAIN_COMMANDS),
    
    ... ... @@ -226,6 +254,19 @@ def test_argument_element(datafiles, cli, project, cmd, word_idx, expected, subd
    226 254
         assert_completion(cli, cmd, word_idx, expected, cwd=cwd)
    
    227 255
     
    
    228 256
     
    
    257
    +@pytest.mark.datafiles(DATA_DIR)
    
    258
    +@pytest.mark.parametrize("project,cmd,word_idx,expected,subdir", [
    
    259
    +
    
    260
    +    # When element has invalid suffix
    
    261
    +    ('project', 'bst --directory ../ show ', 4, [e + ' ' for e in INVALID_ELEMENT], 'files')
    
    262
    +])
    
    263
    +def test_argument_element_invalid(datafiles, cli, project, cmd, word_idx, expected, subdir):
    
    264
    +    cwd = os.path.join(str(datafiles), project)
    
    265
    +    if subdir:
    
    266
    +        cwd = os.path.join(cwd, subdir)
    
    267
    +    assert_completion_failed(cli, cmd, word_idx, expected, cwd=cwd)
    
    268
    +
    
    269
    +
    
    229 270
     @pytest.mark.parametrize("cmd,word_idx,expected", [
    
    230 271
         ('bst he', 1, ['help ']),
    
    231 272
         ('bst help ', 2, MAIN_COMMANDS),
    

  • tests/frontend/buildcheckout.py
    ... ... @@ -60,6 +60,31 @@ def test_build_checkout(datafiles, cli, strict, hardlinks):
    60 60
         assert os.path.exists(filename)
    
    61 61
     
    
    62 62
     
    
    63
    +@pytest.mark.datafiles(DATA_DIR)
    
    64
    +@pytest.mark.parametrize("strict,hardlinks", [
    
    65
    +    ("non-strict", "hardlinks"),
    
    66
    +])
    
    67
    +def test_build_invalid_suffix(datafiles, cli, strict, hardlinks):
    
    68
    +    project = os.path.join(datafiles.dirname, datafiles.basename)
    
    69
    +    checkout = os.path.join(cli.directory, 'checkout')
    
    70
    +
    
    71
    +    result = cli.run(project=project, args=strict_args(['build', 'target.foo'], strict))
    
    72
    +    result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
    
    73
    +
    
    74
    +
    
    75
    +@pytest.mark.datafiles(DATA_DIR)
    
    76
    +@pytest.mark.parametrize("strict,hardlinks", [
    
    77
    +    ("non-strict", "hardlinks"),
    
    78
    +])
    
    79
    +def test_build_invalid_suffix_dep(datafiles, cli, strict, hardlinks):
    
    80
    +    project = os.path.join(datafiles.dirname, datafiles.basename)
    
    81
    +    checkout = os.path.join(cli.directory, 'checkout')
    
    82
    +
    
    83
    +    # target2.bst depends on an element called target.foo
    
    84
    +    result = cli.run(project=project, args=strict_args(['build', 'target2.bst'], strict))
    
    85
    +    result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
    
    86
    +
    
    87
    +
    
    63 88
     @pytest.mark.datafiles(DATA_DIR)
    
    64 89
     @pytest.mark.parametrize("deps", [("run"), ("none")])
    
    65 90
     def test_build_checkout_deps(datafiles, cli, deps):
    

  • tests/frontend/project/elements/target.foo
    1
    +kind: stack
    
    2
    +description: |
    
    3
    +
    
    4
    +  Main stack target for the bst build test

  • tests/frontend/project/elements/target2.bst
    1
    +kind: stack
    
    2
    +description: |
    
    3
    +
    
    4
    +  Main stack target for the bst build test
    
    5
    +
    
    6
    +depends:
    
    7
    +- target.foo



  • [Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]