[Notes] [Git][BuildStream/buildstream][tpollard/483] 22 commits: setup.py: Add more metadata useful for PyPI



Title: GitLab

Tom Pollard pushed to branch tpollard/483 at BuildStream / buildstream

Commits:

17 changed files:

Changes:

  • .gitlab-ci.yml
    ... ... @@ -84,25 +84,25 @@ source_dist:
    84 84
         - coverage-linux/
    
    85 85
     
    
    86 86
     tests-debian-9:
    
    87
    -  image: buildstream/testsuite-debian:9-master-114-4cab18e3
    
    87
    +  image: buildstream/testsuite-debian:9-master-117-aa3a33b3
    
    88 88
       <<: *linux-tests
    
    89 89
     
    
    90 90
     tests-fedora-27:
    
    91
    -  image: buildstream/testsuite-fedora:27-master-114-4cab18e3
    
    91
    +  image: buildstream/testsuite-fedora:27-master-117-aa3a33b3
    
    92 92
       <<: *linux-tests
    
    93 93
     
    
    94 94
     tests-fedora-28:
    
    95
    -  image: buildstream/testsuite-fedora:28-master-114-4cab18e3
    
    95
    +  image: buildstream/testsuite-fedora:28-master-117-aa3a33b3
    
    96 96
       <<: *linux-tests
    
    97 97
     
    
    98 98
     tests-ubuntu-18.04:
    
    99
    -  image: buildstream/testsuite-ubuntu:18.04-master-114-4cab18e3
    
    99
    +  image: buildstream/testsuite-ubuntu:18.04-master-117-aa3a33b3
    
    100 100
       <<: *linux-tests
    
    101 101
     
    
    102 102
     tests-unix:
    
    103 103
       # Use fedora here, to a) run a test on fedora and b) ensure that we
    
    104 104
       # can get rid of ostree - this is not possible with debian-8
    
    105
    -  image: buildstream/testsuite-fedora:27-master-114-4cab18e3
    
    105
    +  image: buildstream/testsuite-fedora:27-master-117-aa3a33b3
    
    106 106
       stage: test
    
    107 107
       variables:
    
    108 108
         BST_FORCE_BACKEND: "unix"
    

  • buildstream/_artifactcache/cascache.py
    ... ... @@ -249,6 +249,13 @@ class CASCache(ArtifactCache):
    249 249
                     if e.code() != grpc.StatusCode.NOT_FOUND:
    
    250 250
                         raise ArtifactError("Failed to pull artifact {}: {}".format(
    
    251 251
                             element._get_brief_display_key(), e)) from e
    
    252
    +                else:
    
    253
    +                    self.context.message(Message(
    
    254
    +                        None,
    
    255
    +                        MessageType.SKIPPED,
    
    256
    +                        "Remote ({}) does not have {} cached".format(
    
    257
    +                            remote.spec.url, element._get_brief_display_key())
    
    258
    +                    ))
    
    252 259
     
    
    253 260
             return False
    
    254 261
     
    

  • buildstream/_exceptions.py
    ... ... @@ -217,6 +217,9 @@ class LoadErrorReason(Enum):
    217 217
         # A recursive include has been encountered.
    
    218 218
         RECURSIVE_INCLUDE = 21
    
    219 219
     
    
    220
    +    # A recursive variable has been encountered
    
    221
    +    RECURSIVE_VARIABLE = 22
    
    222
    +
    
    220 223
     
    
    221 224
     # LoadError
    
    222 225
     #
    

  • buildstream/_variables.py
    ... ... @@ -61,7 +61,7 @@ class Variables():
    61 61
         #    LoadError, if the string contains unresolved variable references.
    
    62 62
         #
    
    63 63
         def subst(self, string):
    
    64
    -        substitute, unmatched = self._subst(string, self.variables)
    
    64
    +        substitute, unmatched, _ = self._subst(string, self.variables)
    
    65 65
             unmatched = list(set(unmatched))
    
    66 66
             if unmatched:
    
    67 67
                 if len(unmatched) == 1:
    
    ... ... @@ -82,6 +82,7 @@ class Variables():
    82 82
             def subst_callback(match):
    
    83 83
                 nonlocal variables
    
    84 84
                 nonlocal unmatched
    
    85
    +            nonlocal matched
    
    85 86
     
    
    86 87
                 token = match.group(0)
    
    87 88
                 varname = match.group(1)
    
    ... ... @@ -91,6 +92,7 @@ class Variables():
    91 92
                     # We have to check if the inner string has variables
    
    92 93
                     # and return unmatches for those
    
    93 94
                     unmatched += re.findall(_VARIABLE_MATCH, value)
    
    95
    +                matched += [varname]
    
    94 96
                 else:
    
    95 97
                     # Return unmodified token
    
    96 98
                     unmatched += [varname]
    
    ... ... @@ -98,10 +100,11 @@ class Variables():
    98 100
     
    
    99 101
                 return value
    
    100 102
     
    
    103
    +        matched = []
    
    101 104
             unmatched = []
    
    102 105
             replacement = re.sub(_VARIABLE_MATCH, subst_callback, string)
    
    103 106
     
    
    104
    -        return (replacement, unmatched)
    
    107
    +        return (replacement, unmatched, matched)
    
    105 108
     
    
    106 109
         # Variable resolving code
    
    107 110
         #
    
    ... ... @@ -131,7 +134,15 @@ class Variables():
    131 134
                     # Ensure stringness of the value before substitution
    
    132 135
                     value = _yaml.node_get(variables, str, key)
    
    133 136
     
    
    134
    -                resolved_var, item_unmatched = self._subst(value, variables)
    
    137
    +                resolved_var, item_unmatched, matched = self._subst(value, variables)
    
    138
    +
    
    139
    +                if _wrap_variable(key) in resolved_var:
    
    140
    +                    referenced_through = find_recursive_variable(key, matched, variables)
    
    141
    +                    raise LoadError(LoadErrorReason.RECURSIVE_VARIABLE,
    
    142
    +                                    "{}: ".format(_yaml.node_get_provenance(variables, key)) +
    
    143
    +                                    ("Variable '{}' expands to contain a reference to itself. " +
    
    144
    +                                     "Perhaps '{}' contains '{}").format(key, referenced_through, _wrap_variable(key)))
    
    145
    +
    
    135 146
                     resolved[key] = resolved_var
    
    136 147
                     unmatched += item_unmatched
    
    137 148
     
    
    ... ... @@ -168,8 +179,21 @@ class Variables():
    168 179
         # Helper function to fetch information about the node referring to a variable
    
    169 180
         #
    
    170 181
         def _find_references(self, varname):
    
    171
    -        fullname = '%{' + varname + '}'
    
    182
    +        fullname = _wrap_variable(varname)
    
    172 183
             for key, value in _yaml.node_items(self.original):
    
    173 184
                 if fullname in value:
    
    174 185
                     provenance = _yaml.node_get_provenance(self.original, key)
    
    175 186
                     yield (key, provenance)
    
    187
    +
    
    188
    +
    
    189
    +def find_recursive_variable(variable, matched_variables, all_vars):
    
    190
    +    matched_values = (_yaml.node_get(all_vars, str, key) for key in matched_variables)
    
    191
    +    for key, value in zip(matched_variables, matched_values):
    
    192
    +        if _wrap_variable(variable) in value:
    
    193
    +            return key
    
    194
    +    else:
    
    195
    +        return None
    
    196
    +
    
    197
    +
    
    198
    +def _wrap_variable(var):
    
    199
    +    return "%{" + var + "}"

  • buildstream/plugins/sources/git.py
    ... ... @@ -74,6 +74,9 @@ This plugin provides the following configurable warnings:
    74 74
     
    
    75 75
     - 'git:inconsistent-submodule' - A submodule was found to be missing from the underlying git repository.
    
    76 76
     
    
    77
    +This plugin also utilises the following configurable core plugin warnings:
    
    78
    +
    
    79
    +- 'ref-not-in-track' - The provided ref was not found in the provided track in the element's git repository.
    
    77 80
     """
    
    78 81
     
    
    79 82
     import os
    
    ... ... @@ -87,6 +90,7 @@ from configparser import RawConfigParser
    87 90
     
    
    88 91
     from buildstream import Source, SourceError, Consistency, SourceFetcher
    
    89 92
     from buildstream import utils
    
    93
    +from buildstream.plugin import CoreWarnings
    
    90 94
     
    
    91 95
     GIT_MODULES = '.gitmodules'
    
    92 96
     
    
    ... ... @@ -199,7 +203,7 @@ class GitMirror(SourceFetcher):
    199 203
                 cwd=self.mirror)
    
    200 204
             return output.rstrip('\n')
    
    201 205
     
    
    202
    -    def stage(self, directory):
    
    206
    +    def stage(self, directory, track=None):
    
    203 207
             fullpath = os.path.join(directory, self.path)
    
    204 208
     
    
    205 209
             # Using --shared here avoids copying the objects into the checkout, in any
    
    ... ... @@ -213,10 +217,14 @@ class GitMirror(SourceFetcher):
    213 217
                              fail="Failed to checkout git ref {}".format(self.ref),
    
    214 218
                              cwd=fullpath)
    
    215 219
     
    
    220
    +        # Check that the user specified ref exists in the track if provided & not already tracked
    
    221
    +        if track:
    
    222
    +            self.assert_ref_in_track(fullpath, track)
    
    223
    +
    
    216 224
             # Remove .git dir
    
    217 225
             shutil.rmtree(os.path.join(fullpath, ".git"))
    
    218 226
     
    
    219
    -    def init_workspace(self, directory):
    
    227
    +    def init_workspace(self, directory, track=None):
    
    220 228
             fullpath = os.path.join(directory, self.path)
    
    221 229
             url = self.source.translate_url(self.url)
    
    222 230
     
    
    ... ... @@ -232,6 +240,10 @@ class GitMirror(SourceFetcher):
    232 240
                              fail="Failed to checkout git ref {}".format(self.ref),
    
    233 241
                              cwd=fullpath)
    
    234 242
     
    
    243
    +        # Check that the user specified ref exists in the track if provided & not already tracked
    
    244
    +        if track:
    
    245
    +            self.assert_ref_in_track(fullpath, track)
    
    246
    +
    
    235 247
         # List the submodules (path/url tuples) present at the given ref of this repo
    
    236 248
         def submodule_list(self):
    
    237 249
             modules = "{}:{}".format(self.ref, GIT_MODULES)
    
    ... ... @@ -296,6 +308,28 @@ class GitMirror(SourceFetcher):
    296 308
     
    
    297 309
                 return None
    
    298 310
     
    
    311
    +    # Assert that ref exists in track, if track has been specified.
    
    312
    +    def assert_ref_in_track(self, fullpath, track):
    
    313
    +        _, branch = self.source.check_output([self.source.host_git, 'branch', '--list', track,
    
    314
    +                                              '--contains', self.ref],
    
    315
    +                                             cwd=fullpath,)
    
    316
    +        if branch:
    
    317
    +            return True
    
    318
    +        else:
    
    319
    +            _, tag = self.source.check_output([self.source.host_git, 'tag', '--list', track,
    
    320
    +                                               '--contains', self.ref],
    
    321
    +                                              cwd=fullpath,)
    
    322
    +            if tag:
    
    323
    +                return True
    
    324
    +
    
    325
    +        detail = "The ref provided for the element does not exist locally in the provided track branch / tag " + \
    
    326
    +                 "'{}'.\nYou may wish to track the element to update the ref from '{}' ".format(track, track) + \
    
    327
    +                 "with `bst track`,\nor examine the upstream at '{}' for the specific ref.".format(self.url)
    
    328
    +
    
    329
    +        self.source.warn("{}: expected ref '{}' was not found in given track '{}' for staged repository: '{}'\n"
    
    330
    +                         .format(self.source, self.ref, track, self.url),
    
    331
    +                         detail=detail, warning_token=CoreWarnings.REF_NOT_IN_TRACK)
    
    332
    +
    
    299 333
     
    
    300 334
     class GitSource(Source):
    
    301 335
         # pylint: disable=attribute-defined-outside-init
    
    ... ... @@ -333,6 +367,7 @@ class GitSource(Source):
    333 367
                     self.submodule_checkout_overrides[path] = checkout
    
    334 368
     
    
    335 369
             self.mark_download_url(self.original_url)
    
    370
    +        self.tracked = False
    
    336 371
     
    
    337 372
         def preflight(self):
    
    338 373
             # Check if git is installed, get the binary at the same time
    
    ... ... @@ -387,8 +422,10 @@ class GitSource(Source):
    387 422
                                       detail=detail, reason="track-attempt-no-track")
    
    388 423
                 return None
    
    389 424
     
    
    425
    +        # Resolve the URL for the message
    
    426
    +        resolved_url = self.translate_url(self.mirror.url)
    
    390 427
             with self.timed_activity("Tracking {} from {}"
    
    391
    -                                 .format(self.tracking, self.mirror.url),
    
    428
    +                                 .format(self.tracking, resolved_url),
    
    392 429
                                      silent_nested=True):
    
    393 430
                 self.mirror.ensure()
    
    394 431
                 self.mirror._fetch()
    
    ... ... @@ -396,6 +433,8 @@ class GitSource(Source):
    396 433
                 # Update self.mirror.ref and node.ref from the self.tracking branch
    
    397 434
                 ret = self.mirror.latest_commit(self.tracking)
    
    398 435
     
    
    436
    +        # Set tracked attribute, parameter for if self.mirror.assert_ref_in_track is needed
    
    437
    +        self.tracked = True
    
    399 438
             return ret
    
    400 439
     
    
    401 440
         def init_workspace(self, directory):
    
    ... ... @@ -403,7 +442,7 @@ class GitSource(Source):
    403 442
             self.refresh_submodules()
    
    404 443
     
    
    405 444
             with self.timed_activity('Setting up workspace "{}"'.format(directory), silent_nested=True):
    
    406
    -            self.mirror.init_workspace(directory)
    
    445
    +            self.mirror.init_workspace(directory, track=(self.tracking if not self.tracked else None))
    
    407 446
                 for mirror in self.submodules:
    
    408 447
                     mirror.init_workspace(directory)
    
    409 448
     
    
    ... ... @@ -419,7 +458,7 @@ class GitSource(Source):
    419 458
             # Stage the main repo in the specified directory
    
    420 459
             #
    
    421 460
             with self.timed_activity("Staging {}".format(self.mirror.url), silent_nested=True):
    
    422
    -            self.mirror.stage(directory)
    
    461
    +            self.mirror.stage(directory, track=(self.tracking if not self.tracked else None))
    
    423 462
                 for mirror in self.submodules:
    
    424 463
                     if mirror.path in self.submodule_checkout_overrides:
    
    425 464
                         checkout = self.submodule_checkout_overrides[mirror.path]
    

  • buildstream/source.py
    ... ... @@ -219,10 +219,7 @@ class SourceFetcher():
    219 219
             Args:
    
    220 220
                url (str): The url used to download.
    
    221 221
             """
    
    222
    -        # Not guaranteed to be a valid alias yet.
    
    223
    -        # Ensuring it's a valid alias currently happens in Project.get_alias_uris
    
    224
    -        alias, _ = url.split(utils._ALIAS_SEPARATOR, 1)
    
    225
    -        self.__alias = alias
    
    222
    +        self.__alias = _extract_alias(url)
    
    226 223
     
    
    227 224
         #############################################################
    
    228 225
         #            Private Methods used in BuildStream            #
    
    ... ... @@ -448,20 +445,6 @@ class Source(Plugin):
    448 445
             """
    
    449 446
             self.stage(directory)
    
    450 447
     
    
    451
    -    def mark_download_url(self, url):
    
    452
    -        """Identifies the URL that this Source uses to download
    
    453
    -
    
    454
    -        This must be called during :func:`~buildstream.plugin.Plugin.configure` if
    
    455
    -        :func:`~buildstream.source.Source.translate_url` is not called.
    
    456
    -
    
    457
    -        Args:
    
    458
    -           url (str): The url used to download
    
    459
    -
    
    460
    -        *Since: 1.2*
    
    461
    -        """
    
    462
    -        alias, _ = url.split(utils._ALIAS_SEPARATOR, 1)
    
    463
    -        self.__expected_alias = alias
    
    464
    -
    
    465 448
         def get_source_fetchers(self):
    
    466 449
             """Get the objects that are used for fetching
    
    467 450
     
    
    ... ... @@ -525,12 +508,24 @@ class Source(Plugin):
    525 508
             else:
    
    526 509
                 # Sneakily store the alias if it hasn't already been stored
    
    527 510
                 if not self.__expected_alias and url and utils._ALIAS_SEPARATOR in url:
    
    528
    -                url_alias, _ = url.split(utils._ALIAS_SEPARATOR, 1)
    
    529
    -                self.__expected_alias = url_alias
    
    511
    +                self.mark_download_url(url)
    
    530 512
     
    
    531 513
                 project = self._get_project()
    
    532 514
                 return project.translate_url(url, first_pass=self.__first_pass)
    
    533 515
     
    
    516
    +    def mark_download_url(self, url):
    
    517
    +        """Identifies the URL that this Source uses to download
    
    518
    +
    
    519
    +        This must be called during :func:`~buildstream.plugin.Plugin.configure` if
    
    520
    +        :func:`~buildstream.source.Source.translate_url` is not called.
    
    521
    +
    
    522
    +        Args:
    
    523
    +           url (str): The url used to download
    
    524
    +
    
    525
    +        *Since: 1.2*
    
    526
    +        """
    
    527
    +        self.__expected_alias = _extract_alias(url)
    
    528
    +
    
    534 529
         def get_project_directory(self):
    
    535 530
             """Fetch the project base directory
    
    536 531
     
    
    ... ... @@ -774,7 +769,8 @@ class Source(Plugin):
    774 769
             #
    
    775 770
             # Step 2 - Set the ref in memory, and determine changed state
    
    776 771
             #
    
    777
    -        changed = self._set_ref(new_ref, node)
    
    772
    +        if not self._set_ref(new_ref, node):
    
    773
    +            return False
    
    778 774
     
    
    779 775
             def do_save_refs(refs):
    
    780 776
                 try:
    
    ... ... @@ -811,7 +807,7 @@ class Source(Plugin):
    811 807
                                       .format(provenance.filename.shortname),
    
    812 808
                                       reason="tracking-junction-fragment")
    
    813 809
     
    
    814
    -        return changed
    
    810
    +        return True
    
    815 811
     
    
    816 812
         # Wrapper for track()
    
    817 813
         #
    
    ... ... @@ -869,10 +865,12 @@ class Source(Plugin):
    869 865
         def __do_fetch(self, **kwargs):
    
    870 866
             project = self._get_project()
    
    871 867
             source_fetchers = self.get_source_fetchers()
    
    868
    +
    
    869
    +        # Use the source fetchers if they are provided
    
    870
    +        #
    
    872 871
             if source_fetchers:
    
    873 872
                 for fetcher in source_fetchers:
    
    874 873
                     alias = fetcher._get_alias()
    
    875
    -                success = False
    
    876 874
                     for uri in project.get_alias_uris(alias, first_pass=self.__first_pass):
    
    877 875
                         try:
    
    878 876
                             fetcher.fetch(uri)
    
    ... ... @@ -881,10 +879,16 @@ class Source(Plugin):
    881 879
                         except BstError as e:
    
    882 880
                             last_error = e
    
    883 881
                             continue
    
    884
    -                    success = True
    
    882
    +
    
    883
    +                    # No error, we're done with this fetcher
    
    885 884
                         break
    
    886
    -                if not success:
    
    885
    +
    
    886
    +                else:
    
    887
    +                    # No break occurred, raise the last detected error
    
    887 888
                         raise last_error
    
    889
    +
    
    890
    +        # Default codepath is to reinstantiate the Source
    
    891
    +        #
    
    888 892
             else:
    
    889 893
                 alias = self._get_alias()
    
    890 894
                 if self.__first_pass:
    
    ... ... @@ -908,18 +912,22 @@ class Source(Plugin):
    908 912
                     except BstError as e:
    
    909 913
                         last_error = e
    
    910 914
                         continue
    
    915
    +
    
    916
    +                # No error, we're done here
    
    911 917
                     return
    
    918
    +
    
    919
    +            # Re raise the last detected error
    
    912 920
                 raise last_error
    
    913 921
     
    
    914 922
         # Tries to call track for every mirror, stopping once it succeeds
    
    915 923
         def __do_track(self, **kwargs):
    
    916 924
             project = self._get_project()
    
    917
    -        # If there are no mirrors, or no aliases to replace, there's nothing to do here.
    
    918 925
             alias = self._get_alias()
    
    919 926
             if self.__first_pass:
    
    920 927
                 mirrors = project.first_pass_config.mirrors
    
    921 928
             else:
    
    922 929
                 mirrors = project.config.mirrors
    
    930
    +        # If there are no mirrors, or no aliases to replace, there's nothing to do here.
    
    923 931
             if not mirrors or not alias:
    
    924 932
                 return self.track(**kwargs)
    
    925 933
     
    
    ... ... @@ -988,3 +996,11 @@ class Source(Plugin):
    988 996
     
    
    989 997
                 if src.get_consistency() == Consistency.RESOLVED:
    
    990 998
                     src._fetch(previous_sources[0:index])
    
    999
    +
    
    1000
    +
    
    1001
    +def _extract_alias(url):
    
    1002
    +    parts = url.split(utils._ALIAS_SEPARATOR, 1)
    
    1003
    +    if len(parts) > 1 and not parts[0].lower() in utils._URI_SCHEMES:
    
    1004
    +        return parts[0]
    
    1005
    +    else:
    
    1006
    +        return ""

  • buildstream/utils.py
    ... ... @@ -47,6 +47,7 @@ _magic_timestamp = calendar.timegm([2011, 11, 11, 11, 11, 11])
    47 47
     
    
    48 48
     # The separator we use for user specified aliases
    
    49 49
     _ALIAS_SEPARATOR = ':'
    
    50
    +_URI_SCHEMES = ["http", "https", "ftp", "file", "git", "sftp", "ssh"]
    
    50 51
     
    
    51 52
     
    
    52 53
     class UtilError(BstError):
    

  • dev-requirements.txt
    ... ... @@ -8,3 +8,4 @@ pytest-env
    8 8
     pytest-pep8
    
    9 9
     pytest-pylint
    
    10 10
     pytest-xdist
    
    11
    +pytest-timeout

  • setup.py
    ... ... @@ -25,7 +25,14 @@ import subprocess
    25 25
     import sys
    
    26 26
     import versioneer
    
    27 27
     
    
    28
    -if sys.version_info[0] != 3 or sys.version_info[1] < 5:
    
    28
    +
    
    29
    +##################################################################
    
    30
    +# Python requirements
    
    31
    +##################################################################
    
    32
    +REQUIRED_PYTHON_MAJOR = 3
    
    33
    +REQUIRED_PYTHON_MINOR = 5
    
    34
    +
    
    35
    +if sys.version_info[0] != REQUIRED_PYTHON_MAJOR or sys.version_info[1] < REQUIRED_PYTHON_MINOR:
    
    29 36
         print("BuildStream requires Python >= 3.5")
    
    30 37
         sys.exit(1)
    
    31 38
     
    
    ... ... @@ -242,11 +249,28 @@ setup(name='BuildStream',
    242 249
     
    
    243 250
           author='BuildStream Developers',
    
    244 251
           author_email='buildstream-list gnome org',
    
    252
    +      classifiers=[
    
    253
    +          'Environment :: Console',
    
    254
    +          'Intended Audience :: Developers',
    
    255
    +          'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)',
    
    256
    +          'Operating System :: POSIX',
    
    257
    +          'Programming Language :: Python :: 3',
    
    258
    +          'Programming Language :: Python :: 3.5',
    
    259
    +          'Programming Language :: Python :: 3.6',
    
    260
    +          'Programming Language :: Python :: 3.7',
    
    261
    +          'Topic :: Software Development :: Build Tools'
    
    262
    +      ],
    
    245 263
           description='A framework for modelling build pipelines in YAML',
    
    246 264
           license='LGPL',
    
    247 265
           long_description=long_description,
    
    248 266
           long_description_content_type='text/x-rst; charset=UTF-8',
    
    249 267
           url='https://gitlab.com/BuildStream/buildstream',
    
    268
    +      project_urls={
    
    269
    +          'Documentation': 'https://buildstream.gitlab.io/buildstream/',
    
    270
    +          'Tracker': 'https://gitlab.com/BuildStream/buildstream/issues',
    
    271
    +          'Mailing List': 'https://mail.gnome.org/mailman/listinfo/buildstream-list'
    
    272
    +      },
    
    273
    +      python_requires='~={}.{}'.format(REQUIRED_PYTHON_MAJOR, REQUIRED_PYTHON_MINOR),
    
    250 274
           packages=find_packages(exclude=('tests', 'tests.*')),
    
    251 275
           package_data={'buildstream': ['plugins/*/*.py', 'plugins/*/*.yaml',
    
    252 276
                                         'data/*.yaml', 'data/*.sh.in']},
    

  • tests/format/variables.py
    1 1
     import os
    
    2 2
     import pytest
    
    3
    +import sys
    
    3 4
     from buildstream import _yaml
    
    4 5
     from buildstream._exceptions import ErrorDomain, LoadErrorReason
    
    5 6
     from tests.testutils.runcli import cli
    
    ... ... @@ -72,3 +73,20 @@ def test_missing_variable(cli, datafiles, tmpdir):
    72 73
         ])
    
    73 74
         result.assert_main_error(ErrorDomain.LOAD,
    
    74 75
                                  LoadErrorReason.UNRESOLVED_VARIABLE)
    
    76
    +
    
    77
    +
    
    78
    +@pytest.mark.timeout(3, method="signal")
    
    79
    +@pytest.mark.datafiles(os.path.join(DATA_DIR, 'cyclic_variables'))
    
    80
    +def test_cyclic_variables(cli, datafiles):
    
    81
    +    print_warning("Performing cyclic test, if this test times out it will " +
    
    82
    +                  "exit the test sequence")
    
    83
    +    project = os.path.join(datafiles.dirname, datafiles.basename)
    
    84
    +    result = cli.run(project=project, silent=True, args=[
    
    85
    +        "build", "cyclic.bst"
    
    86
    +    ])
    
    87
    +    result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.RECURSIVE_VARIABLE)
    
    88
    +
    
    89
    +
    
    90
    +def print_warning(msg):
    
    91
    +    RED, END = "\033[91m", "\033[0m"
    
    92
    +    print(("\n{}{}{}").format(RED, msg, END), file=sys.stderr)

  • tests/format/variables/cyclic_variables/cyclic.bst
    1
    +kind: manual
    
    2
    +
    
    3
    +variables:
    
    4
    +  a: "%{prefix}/a"
    
    5
    +  prefix: "%{a}/some_prefix/"
    \ No newline at end of file

  • tests/format/variables/cyclic_variables/project.conf
    1
    +name: test

  • tests/frontend/mirror.py
    ... ... @@ -142,10 +142,6 @@ def test_mirror_fetch(cli, tmpdir, datafiles, kind):
    142 142
     @pytest.mark.datafiles(DATA_DIR)
    
    143 143
     @pytest.mark.parametrize("kind", [(kind) for kind in ALL_REPO_KINDS])
    
    144 144
     def test_mirror_fetch_upstream_absent(cli, tmpdir, datafiles, kind):
    
    145
    -    if kind == 'ostree':
    
    146
    -        # FIXME: Mirroring fallback fails with ostree
    
    147
    -        pytest.skip("Bug #538 - ostree mirror fallback breaks assertion")
    
    148
    -
    
    149 145
         bin_files_path = os.path.join(str(datafiles), 'files', 'bin-files', 'usr')
    
    150 146
         dev_files_path = os.path.join(str(datafiles), 'files', 'dev-files', 'usr')
    
    151 147
         upstream_repodir = os.path.join(str(tmpdir), 'upstream')
    

  • tests/frontend/pull.py
    ... ... @@ -338,3 +338,22 @@ def test_pull_missing_blob(cli, tmpdir, datafiles):
    338 338
     
    
    339 339
             # Assert that no artifacts were pulled
    
    340 340
             assert len(result.get_pulled_elements()) == 0
    
    341
    +
    
    342
    +
    
    343
    +@pytest.mark.datafiles(DATA_DIR)
    
    344
    +def test_pull_missing_notifies_user(caplog, cli, tmpdir, datafiles):
    
    345
    +    project = os.path.join(datafiles.dirname, datafiles.basename)
    
    346
    +    caplog.set_level(1)
    
    347
    +
    
    348
    +    with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare')) as share:
    
    349
    +
    
    350
    +        cli.configure({
    
    351
    +            'artifacts': {'url': share.repo}
    
    352
    +        })
    
    353
    +        result = cli.run(project=project, args=['build', 'target.bst'])
    
    354
    +
    
    355
    +        result.assert_success()
    
    356
    +        assert not result.get_pulled_elements(), \
    
    357
    +            "No elements should have been pulled since the cache was empty"
    
    358
    +
    
    359
    +        assert "SKIPPED Remote ({}) does not have".format(share.repo) in result.stderr

  • tests/plugins/filter.py
    ... ... @@ -174,9 +174,8 @@ def test_filter_workspace_reset(datafiles, cli, tmpdir):
    174 174
     
    
    175 175
     
    
    176 176
     @pytest.mark.datafiles(os.path.join(DATA_DIR, 'basic'))
    
    177
    -@pytest.mark.parametrize("kind", [(kind) for kind in ALL_REPO_KINDS if kind not in ("patch", "local")])
    
    178
    -def test_filter_track(datafiles, cli, tmpdir, kind):
    
    179
    -    repo = create_repo(kind, str(tmpdir))
    
    177
    +def test_filter_track(datafiles, cli, tmpdir):
    
    178
    +    repo = create_repo('git', str(tmpdir))
    
    180 179
         ref = repo.create(os.path.join(str(datafiles), "files"))
    
    181 180
         elements_dir = os.path.join(str(tmpdir), "elements")
    
    182 181
         project = str(tmpdir)
    
    ... ... @@ -228,9 +227,8 @@ def test_filter_track(datafiles, cli, tmpdir, kind):
    228 227
     
    
    229 228
     
    
    230 229
     @pytest.mark.datafiles(os.path.join(DATA_DIR, 'basic'))
    
    231
    -@pytest.mark.parametrize("kind", [(kind) for kind in ALL_REPO_KINDS if kind not in ("patch", "local")])
    
    232
    -def test_filter_track_excepted(datafiles, cli, tmpdir, kind):
    
    233
    -    repo = create_repo(kind, str(tmpdir))
    
    230
    +def test_filter_track_excepted(datafiles, cli, tmpdir):
    
    231
    +    repo = create_repo('git', str(tmpdir))
    
    234 232
         ref = repo.create(os.path.join(str(datafiles), "files"))
    
    235 233
         elements_dir = os.path.join(str(tmpdir), "elements")
    
    236 234
         project = str(tmpdir)
    
    ... ... @@ -282,9 +280,8 @@ def test_filter_track_excepted(datafiles, cli, tmpdir, kind):
    282 280
     
    
    283 281
     
    
    284 282
     @pytest.mark.datafiles(os.path.join(DATA_DIR, 'basic'))
    
    285
    -@pytest.mark.parametrize("kind", [(kind) for kind in ALL_REPO_KINDS if kind not in ("patch", "local")])
    
    286
    -def test_filter_track_multi_to_one(datafiles, cli, tmpdir, kind):
    
    287
    -    repo = create_repo(kind, str(tmpdir))
    
    283
    +def test_filter_track_multi_to_one(datafiles, cli, tmpdir):
    
    284
    +    repo = create_repo('git', str(tmpdir))
    
    288 285
         ref = repo.create(os.path.join(str(datafiles), "files"))
    
    289 286
         elements_dir = os.path.join(str(tmpdir), "elements")
    
    290 287
         project = str(tmpdir)
    
    ... ... @@ -336,9 +333,8 @@ def test_filter_track_multi_to_one(datafiles, cli, tmpdir, kind):
    336 333
     
    
    337 334
     
    
    338 335
     @pytest.mark.datafiles(os.path.join(DATA_DIR, 'basic'))
    
    339
    -@pytest.mark.parametrize("kind", [(kind) for kind in ALL_REPO_KINDS if kind not in ("patch", "local")])
    
    340
    -def test_filter_track_multi(datafiles, cli, tmpdir, kind):
    
    341
    -    repo = create_repo(kind, str(tmpdir))
    
    336
    +def test_filter_track_multi(datafiles, cli, tmpdir):
    
    337
    +    repo = create_repo('git', str(tmpdir))
    
    342 338
         ref = repo.create(os.path.join(str(datafiles), "files"))
    
    343 339
         elements_dir = os.path.join(str(tmpdir), "elements")
    
    344 340
         project = str(tmpdir)
    
    ... ... @@ -398,9 +394,8 @@ def test_filter_track_multi(datafiles, cli, tmpdir, kind):
    398 394
     
    
    399 395
     
    
    400 396
     @pytest.mark.datafiles(os.path.join(DATA_DIR, 'basic'))
    
    401
    -@pytest.mark.parametrize("kind", [(kind) for kind in ALL_REPO_KINDS if kind not in ("patch", "local")])
    
    402
    -def test_filter_track_multi_exclude(datafiles, cli, tmpdir, kind):
    
    403
    -    repo = create_repo(kind, str(tmpdir))
    
    397
    +def test_filter_track_multi_exclude(datafiles, cli, tmpdir):
    
    398
    +    repo = create_repo('git', str(tmpdir))
    
    404 399
         ref = repo.create(os.path.join(str(datafiles), "files"))
    
    405 400
         elements_dir = os.path.join(str(tmpdir), "elements")
    
    406 401
         project = str(tmpdir)
    

  • tests/sources/git.py
    ... ... @@ -25,6 +25,7 @@ import pytest
    25 25
     
    
    26 26
     from buildstream._exceptions import ErrorDomain
    
    27 27
     from buildstream import _yaml
    
    28
    +from buildstream.plugin import CoreWarnings
    
    28 29
     
    
    29 30
     from tests.testutils import cli, create_repo
    
    30 31
     from tests.testutils.site import HAVE_GIT
    
    ... ... @@ -408,3 +409,70 @@ def test_submodule_track_no_ref_or_track(cli, tmpdir, datafiles):
    408 409
         result = cli.run(project=project, args=['show', 'target.bst'])
    
    409 410
         result.assert_main_error(ErrorDomain.SOURCE, "missing-track-and-ref")
    
    410 411
         result.assert_task_error(None, None)
    
    412
    +
    
    413
    +
    
    414
    +@pytest.mark.skipif(HAVE_GIT is False, reason="git is not available")
    
    415
    +@pytest.mark.datafiles(os.path.join(DATA_DIR, 'template'))
    
    416
    +def test_ref_not_in_track_warn(cli, tmpdir, datafiles):
    
    417
    +    project = os.path.join(datafiles.dirname, datafiles.basename)
    
    418
    +
    
    419
    +    # Create the repo from 'repofiles', create a branch without latest commit
    
    420
    +    repo = create_repo('git', str(tmpdir))
    
    421
    +    ref = repo.create(os.path.join(project, 'repofiles'))
    
    422
    +
    
    423
    +    gitsource = repo.source_config(ref=ref)
    
    424
    +
    
    425
    +    # Overwrite the track value to the added branch
    
    426
    +    gitsource['track'] = 'foo'
    
    427
    +
    
    428
    +    # Write out our test target
    
    429
    +    element = {
    
    430
    +        'kind': 'import',
    
    431
    +        'sources': [
    
    432
    +            gitsource
    
    433
    +        ]
    
    434
    +    }
    
    435
    +    _yaml.dump(element, os.path.join(project, 'target.bst'))
    
    436
    +
    
    437
    +    # Assert the warning is raised as ref is not in branch foo.
    
    438
    +    # Assert warning not error to the user, when not set as fatal.
    
    439
    +    result = cli.run(project=project, args=['build', 'target.bst'])
    
    440
    +    assert "The ref provided for the element does not exist locally" in result.stderr
    
    441
    +
    
    442
    +
    
    443
    +@pytest.mark.skipif(HAVE_GIT is False, reason="git is not available")
    
    444
    +@pytest.mark.datafiles(os.path.join(DATA_DIR, 'template'))
    
    445
    +def test_ref_not_in_track_warn_error(cli, tmpdir, datafiles):
    
    446
    +    project = os.path.join(datafiles.dirname, datafiles.basename)
    
    447
    +
    
    448
    +    # Add fatal-warnings ref-not-in-track to project.conf
    
    449
    +    project_template = {
    
    450
    +        "name": "foo",
    
    451
    +        "fatal-warnings": [CoreWarnings.REF_NOT_IN_TRACK]
    
    452
    +    }
    
    453
    +
    
    454
    +    _yaml.dump(project_template, os.path.join(project, 'project.conf'))
    
    455
    +
    
    456
    +    # Create the repo from 'repofiles', create a branch without latest commit
    
    457
    +    repo = create_repo('git', str(tmpdir))
    
    458
    +    ref = repo.create(os.path.join(project, 'repofiles'))
    
    459
    +
    
    460
    +    gitsource = repo.source_config(ref=ref)
    
    461
    +
    
    462
    +    # Overwrite the track value to the added branch
    
    463
    +    gitsource['track'] = 'foo'
    
    464
    +
    
    465
    +    # Write out our test target
    
    466
    +    element = {
    
    467
    +        'kind': 'import',
    
    468
    +        'sources': [
    
    469
    +            gitsource
    
    470
    +        ]
    
    471
    +    }
    
    472
    +    _yaml.dump(element, os.path.join(project, 'target.bst'))
    
    473
    +
    
    474
    +    # Assert that build raises a warning here that is captured
    
    475
    +    # as plugin error, due to the fatal warning being set
    
    476
    +    result = cli.run(project=project, args=['build', 'target.bst'])
    
    477
    +    result.assert_main_error(ErrorDomain.STREAM, None)
    
    478
    +    result.assert_task_error(ErrorDomain.PLUGIN, CoreWarnings.REF_NOT_IN_TRACK)

  • tests/testutils/runcli.py
    ... ... @@ -94,14 +94,28 @@ class Result():
    94 94
         #    error_reason (any): The reason field of the error which occurred
    
    95 95
         #    fail_message (str): An optional message to override the automatic
    
    96 96
         #                        assertion error messages
    
    97
    +    #    debug (bool): If true, prints information regarding the exit state of the result()
    
    97 98
         # Raises:
    
    98 99
         #    (AssertionError): If any of the assertions fail
    
    99 100
         #
    
    100 101
         def assert_main_error(self,
    
    101 102
                               error_domain,
    
    102 103
                               error_reason,
    
    103
    -                          fail_message=''):
    
    104
    -
    
    104
    +                          fail_message='',
    
    105
    +                          *, debug=False):
    
    106
    +        if debug:
    
    107
    +            print(
    
    108
    +                """
    
    109
    +                Exit code: {}
    
    110
    +                Exception: {}
    
    111
    +                Domain:    {}
    
    112
    +                Reason:    {}
    
    113
    +                """.format(
    
    114
    +                    self.exit_code,
    
    115
    +                    self.exception,
    
    116
    +                    self.exception.domain,
    
    117
    +                    self.exception.reason
    
    118
    +                ))
    
    105 119
             assert self.exit_code == -1, fail_message
    
    106 120
             assert self.exc is not None, fail_message
    
    107 121
             assert self.exception is not None, fail_message
    



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