Exemple #1
0
def test_serialiser_python(make_dist):
    make_dist()
    jdist = JohnnyDist("jdtest")
    assert jdist.serialise() == [{
        "name": "jdtest",
        "summary": "default text for metadata summary"
    }]
Exemple #2
0
def test_serialiser():
    dist = JohnnyDist('wheel')
    assert dist.serialise(format=None) == [{
        'name':
        'wheel',
        'summary':
        'A built-package format for Python.'
    }]
    assert dist.serialise(
        format='toml'
    ) == 'name = "wheel"\nsummary = "A built-package format for Python."\n'
    assert dist.serialise(
        format='yaml'
    ) == '- {name: wheel, summary: A built-package format for Python.}\n'
    with ShouldRaise(Exception('Unsupported format')):
        dist.serialise(format='bogus')
Exemple #3
0
def test_serialiser_toml(make_dist):
    make_dist()
    jdist = JohnnyDist("jdtest")
    assert jdist.serialise(format="toml") == dedent("""\
        name = "jdtest"
        summary = "default text for metadata summary"
        """)
Exemple #4
0
def main():
    default_fields = os.environ.get("JOHNNYDEP_FIELDS", "name,summary").split(",")
    parser = ArgumentParser()
    parser.add_argument("req", help="The project name or requirement specifier")
    parser.add_argument("--index-url", "-i")
    parser.add_argument(
        "--output-format",
        "-o",
        choices=["human", "json", "yaml", "python", "toml", "pinned"],
        default="human",
    )
    parser.add_argument(
        "--no-deps", help="Don't recurse the dependency tree", dest="recurse", action="store_false"
    )
    parser.add_argument(
        "--fields", "-f", nargs="*", default=default_fields, choices=list(FIELDS) + ["ALL"]
    )
    parser.add_argument("--for-python", "-p", dest="env", type=python_interpreter)
    parser.add_argument("--verbose", "-v", default=1, type=int, choices=range(3))
    args = parser.parse_args()
    if "ALL" in args.fields:
        args.fields = list(FIELDS)
    configure_logging(verbosity=args.verbose)
    dist = JohnnyDist(args.req, index_url=args.index_url, env=args.env)
    print(dist.serialise(fields=args.fields, format=args.output_format, recurse=args.recurse))
Exemple #5
0
def test_serialiser_json(make_dist):
    make_dist()
    jdist = JohnnyDist("jdtest")
    assert jdist.serialise(format="json") == dedent("""\
        [
          {
            "name": "jdtest",
            "summary": "default text for metadata summary"
          }
        ]""")
Exemple #6
0
def test_serialiser_with_deps():
    dist = JohnnyDist('fakedist[dev]')
    assert dist.serialise(fields=['name']) == [
        {
            'name': 'fakedist'
        },
        {
            'name': 'wheel'
        },
    ]
Exemple #7
0
def test_serialiser_custom_fields(make_dist):
    make_dist(version="0.1")
    make_dist(version="0.2")
    jdist = JohnnyDist("jdtest")
    expected = [{
        "versions_available": ["0.1", "0.2"],
        "version_latest": "0.2"
    }]
    assert jdist.serialise(fields=("versions_available",
                                   "version_latest")) == expected
Exemple #8
0
def test_non_json_metadata():
    # this dist uses old-skool metadata format (plaintext not json)
    dist = JohnnyDist('testpath==0.3.1')
    assert dist.serialise(fields=['name', 'summary', 'import_names']) == [{
        'name':
        'testpath',
        'summary':
        'Test utilities for code working with files and commands',
        'import_names': ['testpath'],
    }]
Exemple #9
0
def test_plaintext_whl_metadata(add_to_index):
    # this dist uses an old-skool metadata version 1.2
    sdist_fname = os.path.join(here, "testpath-0.3.1-py2.py3-none-any.whl")
    fragment = "#md5=12728181294cf6f815421081d620c494"
    add_to_index(name="testpath", path=sdist_fname, urlfragment=fragment)
    dist = JohnnyDist("testpath==0.3.1")
    assert dist.serialise(fields=["name", "summary", "import_names", "homepage"]) == [
        {
            "name": "testpath",
            "summary": "Test utilities for code working with files and commands",
            "import_names": ["testpath"],
            "homepage": "https://github.com/jupyter/testpath",
        }
    ]
Exemple #10
0
def test_resolve_unresolvable():
    dist = JohnnyDist('distX')
    data = dist.serialise(recurse=False,
                          fields=['project_name', 'summary', 'requires'])
    assert data == [{
        'project_name': 'distX',
        'summary': 'Dist with unresolvable dependencies',
        'requires':
        ['distC (<=0.1)',
         'distC (>0.2)'],  # this installation requirement can not be resolved
    }]
    gen = flatten_deps(dist)
    assert next(gen) is dist
    with ShouldRaise(
            DistributionNotFound(
                'No matching distribution found for distc<=0.1,>0.2')):
        next(gen)
Exemple #11
0
def test_resolve_unresolvable(make_dist):
    make_dist(name="dist1",
              description="unresolvable",
              install_requires=["dist2<=0.1", "dist2>0.2"])
    make_dist(name="dist2", version="0.1")
    make_dist(name="dist2", version="0.3")
    dist = JohnnyDist("dist1")
    data = dist.serialise(recurse=False,
                          fields=["project_name", "summary", "requires"])
    assert data == [{
        "project_name": "dist1",
        "summary": "unresolvable",
        "requires": ["dist2<=0.1", "dist2>0.2"],
    }]
    gen = flatten_deps(dist)
    assert next(gen) is dist
    with pytest.raises(CalledProcessError) as cm:
        next(gen)
    msg = "DistributionNotFound: No matching distribution found for dist2<=0.1,>0.2\n"
    assert cm.value.output.decode().endswith(msg)
Exemple #12
0
def main():
    default_fields = os.environ.get('JOHNNYDEP_FIELDS',
                                    'name,summary').split(',')
    parser = ArgumentParser()
    parser.add_argument('req',
                        help='The project name or requirement specifier')
    parser.add_argument('--verbose', '-v', default=0, action='count')
    parser.add_argument('--index-url', '-i', default=DEFAULT_INDEX)
    parser.add_argument(
        '--output-format',
        '-o',
        choices=['json', 'yaml', 'text', 'python', 'toml', 'pinned'],
        default='text')
    parser.add_argument('--no-deps',
                        help="Don't recurse the dependency tree",
                        dest='recurse',
                        action='store_false')
    parser.add_argument('--fields',
                        '-f',
                        nargs='*',
                        default=default_fields,
                        choices=list(FIELDS) + ['ALL'])
    args = parser.parse_args()
    if 'ALL' in args.fields:
        args.fields = list(FIELDS)
    configure_logging(verbosity=args.verbose)
    dist = JohnnyDist(args.req, index_url=args.index_url)
    if args.output_format == 'text':
        table = gen_table(dist, extra_cols=args.fields)
        tabulate.PRESERVE_WHITESPACE = True
        print(tabulate.tabulate(table, headers='keys'))
    else:
        print(
            dist.serialise(fields=args.fields,
                           format=args.output_format,
                           recurse=args.recurse))
Exemple #13
0
def test_diamond_dependency_tree():
    dist = JohnnyDist('distA')
    fields = [
        'name',
        'summary',
        'specifier',
        'requires',
        'required_by',
        'import_names',
        'homepage',
        'extras_available',
        'extras_requested',
        'project_name',
        'versions_available',
        'version_installed',
        'version_latest',
        'version_latest_in_spec',
        'download_link',
        'checksum',
    ]
    data = dist.serialise(fields=fields)
    data = [dict(x) for x in data]
    assert data == [
        {
            'checksum': 'md5=c422ba4693b32da3c0721d425aff4eed',
            'download_link':
            'https://pypi.python.org/simple/dista/distA-0.1-py2.py3-none-any.whl',
            'extras_available': [],
            'extras_requested': [],
            'homepage': None,
            'import_names': [],
            'name': 'dista',
            'project_name': 'distA',
            'required_by': [],
            'requires': ['distB1', 'distB2'],
            'specifier': '',
            'summary': 'Top of a diamond dependency tree',
            'version_installed': None,
            'version_latest': '0.1',
            'version_latest_in_spec': '0.1',
            'versions_available': ['0.1'],
        },
        {
            'checksum': 'md5=a96f048902789a3faf8e8e829a27a5ec',
            'download_link':
            'https://pypi.python.org/simple/distb1/distB1-0.1-py2.py3-none-any.whl',
            'extras_available': [],
            'extras_requested': [],
            'homepage': None,
            'import_names': [],
            'name': 'distb1',
            'project_name': 'distB1',
            'required_by': ['distA'],
            'requires': ['distC[x,z] (<0.3)'],
            'specifier': '',
            'summary': 'Left edge of a diamond dependency tree',
            'version_installed': None,
            'version_latest': '0.1',
            'version_latest_in_spec': '0.1',
            'versions_available': ['0.1'],
        },
        {
            'checksum': 'md5=bc5761d4232c8e4a95dc0125605f5f65',
            'download_link':
            'https://pypi.python.org/simple/distb2/distB2-0.1-py2.py3-none-any.whl',
            'extras_available': [],
            'extras_requested': [],
            'homepage': None,
            'import_names': [],
            'name': 'distb2',
            'project_name': 'distB2',
            'required_by': ['distA'],
            'requires': ['distC[y] (!=0.2)'],
            'specifier': '',
            'summary': 'Right edge of a diamond dependency tree',
            'version_installed': None,
            'version_latest': '0.1',
            'version_latest_in_spec': '0.1',
            'versions_available': ['0.1'],
        },
        {
            'checksum': 'md5=e3404449fa48c97b384b6b64c52f5ce2',
            'download_link':
            'https://pypi.python.org/simple/distc/distC-0.1-py2.py3-none-any.whl',
            'extras_available': ['X', 'Y', 'Z'],
            'extras_requested': ['x', 'y', 'z'],  # Note: extras got merged
            'homepage': None,
            'import_names': [],
            'name': 'distc',
            'project_name': 'distC',
            'required_by': ['distB1', 'distB2'],
            'requires': [],
            'specifier': '!=0.2,<0.3',  # Note: specifiers got merged
            'summary': 'Bottom of a diamond dependency tree',
            'version_installed': None,
            'version_latest': '0.3',
            'version_latest_in_spec':
            '0.1',  # Even though this was not "best" for either dep
            'versions_available': ['0.1', '0.2', '0.3'],
        },
    ]
Exemple #14
0
def test_serialiser_with_children_no_recurse(make_dist):
    make_dist(name="a", install_requires=["b"])
    make_dist(name="b", version="2.0")
    jdist = JohnnyDist("A")
    assert jdist.serialise(format="pinned", recurse=False) == "a==0.1.2"
Exemple #15
0
def test_serialiser_unsupported(make_dist):
    make_dist()
    jdist = JohnnyDist("jdtest")
    with pytest.raises(Exception) as cm:
        jdist.serialise(format="bogus")
    assert cm.value.args == ("Unsupported format", )
Exemple #16
0
def test_serialiser_pinned(make_dist):
    make_dist()
    jdist = JohnnyDist("jdtest[a]")
    assert jdist.serialise(format="pinned") == "jdtest[a]==0.1.2"
Exemple #17
0
def test_serialiser_yaml(make_dist):
    make_dist()
    jdist = JohnnyDist("jdtest")
    yaml_out = "- {name: jdtest, summary: default text for metadata summary}\n"
    assert jdist.serialise(format="yaml") == yaml_out
Exemple #18
0
def get_dependencies_of(package: str):
    jd = JohnnyDist(package)
    dep_raw = jd.serialise(fields=('name', ), format='json')
    dep = json.loads(dep_raw)
    return dep
Exemple #19
0
def test_get_caching(make_dist, mocker):
    # this test is trying to make sure that distribution "c", a node which appears
    # twice in the dependency tree, is only downloaded from the index once.
    # i.e. check that the ttl caching on the downloader is working correctly
    downloader = mocker.patch("johnnydep.lib.pipper.get")
    _, c, _ = make_dist(name="c", description="leaf node")
    _, b1, _ = make_dist(name="b1",
                         install_requires=["c"],
                         description="branch one")
    _, b2, _ = make_dist(name="b2",
                         install_requires=["c"],
                         description="branch two")
    _, a, _ = make_dist(name="a",
                        install_requires=["b1", "b2"],
                        description="root node")
    downloader.side_effect = [
        {
            "path": a
        },
        {
            "path": b1
        },
        {
            "path": b2
        },
        {
            "path": c
        },
    ]
    jdist = JohnnyDist("a")
    txt = jdist.serialise(format="human")
    assert txt == dedent("""\
        name       summary
        ---------  ----------
        a          root node
        ├── b1     branch one
        │   └── c  leaf node
        └── b2     branch two
            └── c  leaf node""")
    assert downloader.call_count == 4
    assert downloader.call_args_list == [
        mocker.call("a",
                    env=None,
                    extra_index_url=None,
                    index_url=None,
                    tmpdir="."),
        mocker.call("b1",
                    env=None,
                    extra_index_url=None,
                    index_url=None,
                    tmpdir="."),
        mocker.call("b2",
                    env=None,
                    extra_index_url=None,
                    index_url=None,
                    tmpdir="."),
        mocker.call("c",
                    env=None,
                    extra_index_url=None,
                    index_url=None,
                    tmpdir="."),
    ]