def test_requirement_not_in_global(self):
     actions = update._process_project(common.bad_project,
                                       common.global_reqs, None, None, None,
                                       False)
     errors = [a for a in actions if type(a) is project.Error]
     msg = u"'thisisnotarealdepedency' is not in global-requirements.txt"
     self.assertEqual([project.Error(message=msg)], errors)
Beispiel #2
0
 def test_errors(self):
     stdout = io.StringIO()
     root = self.useFixture(fixtures.TempDir()).path
     proj = {'root': root}
     actions = [project.Error(u'fred')]
     with testtools.ExpectedException(Exception):
         project.write(proj, actions, stdout, True)
     self.expectThat(stdout.getvalue(), matchers.Equals('fred\n'))
Beispiel #3
0
def _sync_requirements_file(source_reqs, dest_sequence, dest_label, softupdate,
                            hacking, non_std_reqs):
    actions = []
    dest_reqs = requirement.to_dict(dest_sequence)
    changes = []
    output_requirements = []
    processed_packages = set()

    for req, req_line in dest_sequence:
        # Skip the instructions header
        if req_line in requirement._REQS_HEADER:
            continue
        elif req is None:
            # Unparsable lines.
            output_requirements.append(
                requirement.Requirement('', '', '', '', req_line.rstrip()))
            continue
        elif not req.package:
            # Comment-only lines
            output_requirements.append(req)
            continue
        elif req.package.lower() in processed_packages:
            continue

        processed_packages.add(req.package.lower())
        # Special cases:
        # projects need to align hacking version on their own time
        if req.package == "hacking" and not hacking:
            output_requirements.append(req)
            continue

        reference = source_reqs.get(req.package.lower())
        if reference:
            actual = dest_reqs.get(req.package.lower())
            for req, ref in six.moves.zip_longest(actual, reference):
                if not req:
                    # More in globals
                    changes.append(Change(ref[0].package, '', ref[1]))
                elif not ref:
                    # less in globals
                    changes.append(Change(req[0].package, req[1], ''))
                elif req[0] != ref[0]:
                    # NOTE(jamielennox): extras are allowed to be specified in
                    # a project's requirements and the version be updated and
                    # extras maintained. Create a new ref object the same as
                    # the original but with the req's extras.

                    merged_ref = requirement.Requirement(
                        ref[0].package, ref[0].location, ref[0].specifiers,
                        ref[0].markers, ref[0].comment, req[0].extras)

                    ref = (merged_ref, merged_ref.to_line())

                    if req[0] != ref[0]:
                        # A change on this entry
                        changes.append(Change(req[0].package, req[1], ref[1]))

                if ref:
                    output_requirements.append(ref[0])
        elif softupdate:
            # under softupdate we pass through anything unknown packages,
            # this is intended for ecosystem projects that want to stay in
            # sync with existing requirements, but also add their own above
            # and beyond.
            output_requirements.append(req)
        else:
            # What do we do if we find something unexpected?
            #
            # In the default cause we should die horribly, because
            # the point of global requirements was a single lever
            # to control all the pip installs in the gate.
            #
            # However, we do have other projects using
            # devstack jobs that might have legitimate reasons to
            # override. For those we support NON_STANDARD_REQS=1
            # environment variable to turn this into a warning only.
            # However this drops the unknown requirement.
            actions.append(
                project.Error("'%s' is not in global-requirements.txt" %
                              req.package))
    # always print out what we did if we did a thing
    if changes:
        actions.append(
            project.StdOut("Version change for: %s\n" %
                           ", ".join([x.name for x in changes])))
        actions.append(project.StdOut("Updated %s:\n" % dest_label))
        for change in changes:
            actions.append(project.StdOut("    %s\n" % change))
    return actions, requirement.Requirements(output_requirements)