def test_multiple_lines_separated_in_project(self):
     global_content = textwrap.dedent("""\
         foo<2;python_version=='2.7'
         foo>1;python_version!='2.7'
         """)
     project_content = textwrap.dedent("""\
         foo<1.8;python_version=='2.7'
         # mumbo gumbo
         foo>0.9;python_version!='2.7'
         """)
     global_reqs = requirement.parse(global_content)
     project_reqs = list(requirement.to_reqs(project_content))
     actions, reqs = update._sync_requirements_file(global_reqs,
                                                    project_reqs, 'f',
                                                    False, False, False)
     self.assertEqual(
         requirement.Requirements([
             requirement.Requirement('foo', '', '<2',
                                     "python_version=='2.7'", ''),
             requirement.Requirement('foo', '', '>1',
                                     "python_version!='2.7'", ''),
             requirement.Requirement('', '', '', '', "# mumbo gumbo")
         ]), reqs)
     self.assertEqual(
         project.StdOut("    foo<1.8;python_version=='2.7'  ->   "
                        "foo<2;python_version=='2.7'\n"), actions[2])
     self.assertEqual(
         project.StdOut("    foo>0.9;python_version!='2.7'  ->   "
                        "foo>1;python_version!='2.7'\n"), actions[3])
     self.assertThat(actions, matchers.HasLength(4))
Beispiel #2
0
 def test_stdout(self):
     stdout = io.StringIO()
     root = self.useFixture(fixtures.TempDir()).path
     proj = {'root': root}
     actions = [project.StdOut(u'fred\n')]
     project.write(proj, actions, stdout, True)
     self.expectThat(stdout.getvalue(), matchers.Equals('fred\n'))
Beispiel #3
0
 def test_single_global_multiple_in_project(self):
     global_content = textwrap.dedent("""\
         foo>1
         """)
     project_content = textwrap.dedent("""\
         foo<2;python_version=='2.7'
         foo>1;python_version!='2.7'
         """)
     global_reqs = requirement.parse(global_content)
     project_reqs = list(requirement.to_reqs(project_content))
     actions, reqs = update._sync_requirements_file(
         global_reqs, project_reqs, 'f', False, False, False)
     self.assertEqual(requirement.Requirements([
         requirement.Requirement('foo', '', '>1', "", '')]),
         reqs)
     self.assertEqual(project.StdOut(
         "    foo<2;python_version=='2.7'    ->   foo>1\n"), actions[2])
     self.assertEqual(project.StdOut(
         "    foo>1;python_version!='2.7'    ->   \n"), actions[3])
     self.assertThat(actions, matchers.HasLength(4))
Beispiel #4
0
 def test_extras_kept(self):
     global_content = textwrap.dedent("""\
         oslo.db>1.4.1
         """)
     project_content = textwrap.dedent("""\
         oslo.db[fixture,mysql]>1.3
         """)
     global_reqs = requirement.parse(global_content)
     project_reqs = list(requirement.to_reqs(project_content))
     actions, reqs = update._sync_requirements_file(
         global_reqs, project_reqs, 'f', False, False, False)
     self.assertEqual(requirement.Requirements([
         requirement.Requirement(
             'oslo.db', '', '>1.4.1', '', '', ['fixture', 'mysql'])]),
         reqs)
     self.assertThat(actions, matchers.HasLength(3))
     self.assertEqual(project.StdOut(
         "    oslo.db[fixture,mysql]>1.3     ->   "
         "oslo.db[fixture,mysql]>1.4.1\n"), actions[2])
Beispiel #5
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)