def _check_solution(self, filename, prefer_installed=True):
        # Test that the solution described in the scenario file matches with
        # what the SAT solver computes.

        # Given
        scenario = Scenario.from_yaml(
            os.path.join(os.path.dirname(__file__), filename)
        )
        request = scenario.request

        # When
        pool = Pool(scenario.remote_repositories)
        pool.add_repository(scenario.installed_repository)
        policy = InstalledFirstPolicy(pool, scenario.installed_repository,
                                      prefer_installed=prefer_installed)
        solver = DependencySolver(
            pool, scenario.remote_repositories, scenario.installed_repository,
            policy=policy,
        )

        # Then
        try:
            transaction = solver.solve(request)
        except SatisfiabilityError as failure:
            if not scenario.failed:
                msg = "Solver unexpectedly failed"
                if failure.reason:
                    msg += " because {0}".format(failure.reason)
                self.fail(msg)
        else:
            if scenario.failed:
                msg = "Solver unexpectedly succeeded, but {0}."
                self.fail(msg.format(scenario.failure))
            self.assertEqualOperations(transaction.operations,
                                       scenario.operations)
示例#2
0
    def _check_solution(self, filename, prefer_installed=True):
        # Test that the solution described in the scenario file matches with
        # what the SAT solver computes.

        # Given
        scenario = Scenario.from_yaml(
            os.path.join(os.path.dirname(__file__), filename)
        )
        request = scenario.request

        # When
        pool = Pool(scenario.remote_repositories)
        pool.add_repository(scenario.installed_repository)

        solver = DependencySolver(
            pool, scenario.remote_repositories, scenario.installed_repository,
        )

        # Then
        try:
            transaction = solver.solve(request)
        except SatisfiabilityError as failure:
            self.assertFailureEqual(pool, failure, scenario)
        else:
            if scenario.failed:
                msg = "Solver unexpectedly succeeded, but {0}"
                self.fail(msg.format(scenario.failure['raw']))
            self.assertEqualOperations(transaction.operations,
                                       scenario.operations)
            if (scenario.pretty_operations or
                    transaction.operations != transaction.pretty_operations):
                self.assertEqualOperations(transaction.pretty_operations,
                                           scenario.pretty_operations)
示例#3
0
    def test_requirements_are_not_complete(self):
        # Given
        scenario = Scenario.from_yaml(io.StringIO(u"""
            packages:
                - MKL 10.3-1
                - numpy 1.8.1-1; depends (MKL == 10.3-1)

            request:
                - operation: install
                  requirement: numpy
        """))
        r_msg = textwrap.dedent("""\
        Conflicting requirements:
        Requirements: 'numpy' <- 'MKL == 10.3-1'
            +numpy-1.8.1-1 was ignored because it depends on missing packages
        Requirements: 'numpy'
            Install command rule (+numpy-1.8.1-1)
        """)
        packages = tuple(p for r in scenario.remote_repositories for p in r)

        # When
        requirements = [job.requirement for job in scenario.request.jobs]
        result = requirements_are_complete(packages, requirements)

        # Then
        self.assertFalse(result.is_satisfiable)
        self.assertMultiLineEqual(result.message, r_msg)
示例#4
0
    def test_requirements_are_not_complete(self):
        # Given
        scenario = Scenario.from_yaml(
            io.StringIO(u"""
            packages:
                - MKL 10.3-1
                - numpy 1.8.1-1; depends (MKL == 10.3-1)

            request:
                - operation: install
                  requirement: numpy
        """))
        r_msg = textwrap.dedent("""\
        Conflicting requirements:
        Requirements: 'numpy' <- 'MKL == 10.3-1'
            +numpy-1.8.1-1 was ignored because it depends on missing packages
        Requirements: 'numpy'
            Install command rule (+numpy-1.8.1-1)
        """)
        packages = tuple(p for r in scenario.remote_repositories for p in r)

        # When
        requirements = [job.requirement for job in scenario.request.jobs]
        result = requirements_are_complete(packages, requirements)

        # Then
        self.assertFalse(result.is_satisfiable)
        self.assertMultiLineEqual(result.message, r_msg)
示例#5
0
    def test_requirements_are_not_satisfiable(self):
        # Given
        scenario = Scenario.from_yaml(io.StringIO(u"""
            packages:
                - MKL 10.2-1
                - MKL 10.3-1
                - numpy 1.7.1-1; depends (MKL == 10.3-1)
                - numpy 1.8.1-1; depends (MKL == 10.3-1)

            request:
                - operation: "install"
                  requirement: "numpy"
                - operation: "install"
                  requirement: "MKL != 10.3-1"
        """))
        r_msg = textwrap.dedent("""\
        Conflicting requirements:
        Requirements: 'numpy' <- 'MKL == 10.3-1' <- 'MKL'
            Can only install one of: (+MKL-10.3-1 | +MKL-10.2-1)
        Requirements: 'numpy' <- 'MKL == 10.3-1'
            numpy-1.8.1-1 requires (+MKL-10.3-1)
        Requirements: 'numpy'
            Install command rule (+numpy-1.7.1-1 | +numpy-1.8.1-1)
        """)
        packages = tuple(p for r in scenario.remote_repositories for p in r)
        requirements = [job.requirement for job in scenario.request.jobs]

        # When
        result = requirements_are_satisfiable(packages, requirements)

        # Then
        self.assertFalse(result.is_satisfiable)
        self.assertMultiLineEqual(result.message, r_msg)
示例#6
0
def main(argv=None):
    argv = argv or sys.argv[1:]

    p = argparse.ArgumentParser()
    p.add_argument("scenario", help="Path to the YAML scenario file.")
    p.add_argument("--print-ids", action="store_true")
    p.add_argument("--no-prune", dest="prune", action="store_false")
    p.add_argument("--no-prefer-installed", dest="prefer_installed",
                   action="store_false")
    p.add_argument("-d", "--debug", default=0, action="count")
    p.add_argument("--simple", action="store_true",
                   help="Show a simpler description of the transaction.")
    p.add_argument("--strict", action="store_true",
                   help="Use stricter error checking for package metadata.")

    ns = p.parse_args(argv)

    logging.basicConfig(
        format=('%(asctime)s %(levelname)-8.8s [%(name)s:%(lineno)s]'
                ' %(message)s'),
        datefmt='%Y-%m-%d %H:%M:%S',
        level=('INFO', 'WARNING', 'DEBUG')[ns.debug])

    scenario = Scenario.from_yaml(ns.scenario)
    solve_and_print(scenario.request, scenario.remote_repositories,
                    scenario.installed_repository, ns.print_ids,
                    prune=ns.prune, prefer_installed=ns.prefer_installed,
                    debug=ns.debug, simple=ns.simple, strict=ns.strict)
示例#7
0
    def test_requirements_are_not_satisfiable(self):
        # Given
        scenario = Scenario.from_yaml(
            io.StringIO(u"""
            packages:
                - MKL 10.2-1
                - MKL 10.3-1
                - numpy 1.7.1-1; depends (MKL == 10.3-1)
                - numpy 1.8.1-1; depends (MKL == 10.3-1)

            request:
                - operation: "install"
                  requirement: "numpy"
                - operation: "install"
                  requirement: "MKL != 10.3-1"
        """))
        r_msg = textwrap.dedent("""\
        Conflicting requirements:
        Requirements: 'numpy' <- 'MKL == 10.3-1' <- 'MKL'
            Can only install one of: (+MKL-10.3-1 | +MKL-10.2-1)
        Requirements: 'numpy' <- 'MKL == 10.3-1'
            numpy-1.8.1-1 requires (+MKL-10.3-1)
        Requirements: 'numpy'
            Install command rule (+numpy-1.7.1-1 | +numpy-1.8.1-1)
        """)
        packages = tuple(p for r in scenario.remote_repositories for p in r)
        requirements = [job.requirement for job in scenario.request.jobs]

        # When
        result = requirements_are_satisfiable(packages, requirements)

        # Then
        self.assertFalse(result.is_satisfiable)
        self.assertMultiLineEqual(result.message, r_msg)
示例#8
0
def main(argv=None):
    argv = argv or sys.argv[1:]

    p = argparse.ArgumentParser()
    p.add_argument("scenario", help="Path to the YAML scenario file.")

    ns = p.parse_args(argv)

    scenario = Scenario.from_yaml(ns.scenario)
    print_rules(scenario.request, scenario.remote_repositories,
                scenario.installed_repository)
示例#9
0
def main(argv=None):
    argv = argv or sys.argv[1:]

    p = argparse.ArgumentParser()
    p.add_argument("scenario", help="Path to the YAML scenario file.")

    ns = p.parse_args(argv)

    scenario = Scenario.from_yaml(ns.scenario)
    print_rules(scenario.request, scenario.remote_repositories,
                scenario.installed_repository)
示例#10
0
    def test_packages_are_consistent(self):
        # Given
        scenario = Scenario.from_yaml(io.StringIO(u"""
            packages:
                - MKL 10.3-1
                - numpy 1.8.1-1; depends (MKL == 10.3-1)
        """))

        # When
        packages = tuple(p for r in scenario.remote_repositories for p in r)
        result = packages_are_consistent(packages)

        # Then
        self.assertTrue(result)
示例#11
0
    def test_packages_are_consistent(self):
        # Given
        scenario = Scenario.from_yaml(
            io.StringIO(u"""
            packages:
                - MKL 10.3-1
                - numpy 1.8.1-1; depends (MKL == 10.3-1)
        """))

        # When
        packages = tuple(p for r in scenario.remote_repositories for p in r)
        result = packages_are_consistent(packages)

        # Then
        self.assertTrue(result)
示例#12
0
def main(argv=None):
    argv = argv or sys.argv[1:]

    p = argparse.ArgumentParser()
    p.add_argument("scenario", help="Path to the YAML scenario file.")
    p.add_argument("--solve",
                   action="store_true",
                   help=("Feed the solution to './minisat' and"
                         " show the resulting solution."))
    p.add_argument("--debug",
                   action="count",
                   help="increase the logging verbosity.")

    ns = p.parse_args(argv)

    fmt = '%(asctime)s %(levelname)-8.8s [%(name)s:%(lineno)s] %(message)s'
    logging.basicConfig(format=fmt,
                        datefmt='%Y-%m-%d %H:%M:%S',
                        level='INFO' if ns.debug else 'WARNING')

    scenario = Scenario.from_yaml(ns.scenario)
    pool, solver, requirement_ids = initialize(scenario.request,
                                               scenario.remote_repositories,
                                               scenario.installed_repository,
                                               debug=ns.debug)

    dimacs = '\n'.join(to_dimacs(pool, solver.clauses))

    if ns.solve:
        PIPE = subprocess.PIPE
        try:
            cmd = ['./minisat', '-strict', '/dev/stdin', '/dev/stdout']
            proc = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
        except OSError as e:
            msg = str(e) + ": {!r}".format(' '.join(cmd))
            raise OSError(msg)
        output, stderr = proc.communicate(dimacs.encode('ascii'))
        output = output.decode('ascii')
        output = [l.strip() for l in output.splitlines()]
        SAT, model = output[:2]
        if SAT == 'SAT' and model[-2:] == ' 0':
            solution_ids = set(int(i) for i in model.split()[:-1])
            transaction = from_dimacs_solution(pool,
                                               scenario.installed_repository,
                                               requirement_ids, solution_ids)
            print(transaction)
    else:
        print(dimacs)
示例#13
0
def main(argv=None):
    argv = argv or sys.argv[1:]

    p = argparse.ArgumentParser()
    p.add_argument("scenario", help="Path to the YAML scenario file.")
    p.add_argument("--solve", action="store_true",
                   help=("Feed the solution to './minisat' and"
                         " show the resulting solution."))
    p.add_argument("--debug", action="count",
                   help="increase the logging verbosity.")

    ns = p.parse_args(argv)

    fmt = '%(asctime)s %(levelname)-8.8s [%(name)s:%(lineno)s] %(message)s'
    logging.basicConfig(
        format=fmt,
        datefmt='%Y-%m-%d %H:%M:%S',
        level='INFO' if ns.debug else 'WARNING'
    )

    scenario = Scenario.from_yaml(ns.scenario)
    pool, solver, requirement_ids = initialize(
        scenario.request, scenario.remote_repositories,
        scenario.installed_repository,
        debug=ns.debug)

    dimacs = '\n'.join(to_dimacs(pool, solver.clauses))

    if ns.solve:
        PIPE = subprocess.PIPE
        try:
            cmd = ['./minisat', '-strict', '/dev/stdin', '/dev/stdout']
            proc = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
        except OSError as e:
            msg = str(e) + ": {!r}".format(' '.join(cmd))
            raise OSError(msg)
        output, stderr = proc.communicate(dimacs.encode('ascii'))
        output = output.decode('ascii')
        output = [l.strip() for l in output.splitlines()]
        SAT, model = output[:2]
        if SAT == 'SAT' and model[-2:] == ' 0':
            solution_ids = set(int(i) for i in model.split()[:-1])
            transaction = from_dimacs_solution(
                pool, scenario.installed_repository, requirement_ids,
                solution_ids)
            print(transaction)
    else:
        print(dimacs)
示例#14
0
def main(argv=None):
    argv = argv or sys.argv[1:]

    p = argparse.ArgumentParser()
    p.add_argument("scenario", help="Path to the YAML scenario file.")
    p.add_argument("--print-ids", action="store_true")
    p.add_argument("--no-prune", dest="prune", action="store_false")
    p.add_argument("--no-prefer-installed", dest="prefer_installed",
                   action="store_false")
    p.add_argument("--debug", action="store_true")

    ns = p.parse_args(argv)

    scenario = Scenario.from_yaml(ns.scenario)
    solve_and_print(scenario.request, scenario.remote_repositories,
                    scenario.installed_repository, ns.print_ids,
                    prune=ns.prune, prefer_installed=ns.prefer_installed,
                    debug=ns.debug)
示例#15
0
    def test_repository_is_not_consistent(self):
        # Given
        scenario = Scenario.from_yaml(io.StringIO(u"""
            packages:
                - numpy 1.8.1-1; depends (MKL == 10.3-1)
        """))
        r_msg = textwrap.dedent("""\
        Conflicting requirements:
        Requirements: 'numpy == 1.8.1-1' <- 'MKL == 10.3-1'
            +numpy-1.8.1-1 was ignored because it depends on missing packages
        Requirements: 'numpy == 1.8.1-1'
            Install command rule (+numpy-1.8.1-1)
        """)

        # When
        packages = tuple(p for r in scenario.remote_repositories for p in r)
        result = packages_are_consistent(packages)

        # Then
        self.assertFalse(result.is_satisfiable)
        self.assertMultiLineEqual(result.message, r_msg)
示例#16
0
    def test_repository_is_not_consistent(self):
        # Given
        scenario = Scenario.from_yaml(
            io.StringIO(u"""
            packages:
                - numpy 1.8.1-1; depends (MKL == 10.3-1)
        """))
        r_msg = textwrap.dedent("""\
        Conflicting requirements:
        Requirements: 'numpy == 1.8.1-1' <- 'MKL == 10.3-1'
            +numpy-1.8.1-1 was ignored because it depends on missing packages
        Requirements: 'numpy == 1.8.1-1'
            Install command rule (+numpy-1.8.1-1)
        """)

        # When
        packages = tuple(p for r in scenario.remote_repositories for p in r)
        result = packages_are_consistent(packages)

        # Then
        self.assertFalse(result.is_satisfiable)
        self.assertMultiLineEqual(result.message, r_msg)
示例#17
0
    def test_requirements_are_complete(self):
        # Given
        scenario = Scenario.from_yaml(io.StringIO(u"""
            packages:
                - MKL 10.3-1
                - numpy 1.8.1-1; depends (MKL == 10.3-1)

            request:
                - operation: install
                  requirement: numpy ^= 1.8.1
                - operation: install
                  requirement: MKL == 10.3-1
        """))
        packages = tuple(p for r in scenario.remote_repositories for p in r)

        # When
        requirements = [job.requirement for job in scenario.request.jobs]
        result = requirements_are_complete(packages, requirements)

        # Then
        self.assertTrue(result.is_satisfiable)
        self.assertEqual(result.message, "")
示例#18
0
    def test_requirements_are_complete(self):
        # Given
        scenario = Scenario.from_yaml(
            io.StringIO(u"""
            packages:
                - MKL 10.3-1
                - numpy 1.8.1-1; depends (MKL == 10.3-1)

            request:
                - operation: install
                  requirement: numpy ^= 1.8.1
                - operation: install
                  requirement: MKL == 10.3-1
        """))
        packages = tuple(p for r in scenario.remote_repositories for p in r)

        # When
        requirements = [job.requirement for job in scenario.request.jobs]
        result = requirements_are_complete(packages, requirements)

        # Then
        self.assertTrue(result.is_satisfiable)
        self.assertEqual(result.message, "")
示例#19
0
def main(argv=None):
    argv = argv or sys.argv[1:]

    default_composer_root = os.path.expanduser(
        os.path.join("~/src/projects/composer-git")
    )

    p = argparse.ArgumentParser()
    p.add_argument("scenario", help="Path to the YAML scenario file.")
    p.add_argument("templates", help="PHP templates.", nargs="+")
    p.add_argument("--composer-root", help="Composer root.",
                   default=default_composer_root)

    ns = p.parse_args(argv)

    remote_definition = "remote.json"
    installed_definition = "installed.json"

    scenario = Scenario.from_yaml(ns.scenario)

    template_variables = scenario_to_php_template_variables(scenario,
                                                            remote_definition,
                                                            installed_definition)
    template_variables["composer_bootstrap"] = os.path.join(
        ns.composer_root, "src", "bootstrap.php"
    )

    for template in ns.templates:
        suffix = ".in"
        assert template.endswith(suffix), \
               "Templates should end w/ the {0!r} suffix".format(suffix)

        with open(template, "rt") as fpin:
            output = template[:-len(suffix)]
            with open(output, "wt") as fpout:
                data = jinja2.Template(fpin.read()).render(**template_variables)
                fpout.write(data)