Esempio n. 1
0
def test_hash_not_there():
    "Make sure an exception is thrown when a module is not hashed."
    try:
        Nimporter.get_hash(Path('tests/lib4/lib4.nim'))
        assert False, 'Exception should have been thrown.'
    except NimporterException:
        "Expected case"
Esempio n. 2
0
def test_hash():
    "Make sure when a module is modified it's hash is also."
    module = Path('tests/pkg1/mod2.nim')
    Nimporter.update_hash(module)
    original_hash = Nimporter.get_hash(module)
    original_text = module.read_text()
    module.write_text(original_text.replace('World', 'Pebaz'))
    assert Nimporter.hash_file(module) != original_hash
    module.write_text(original_text.replace('Pebaz', 'World'))
    assert Nimporter.hash_file(module) == original_hash
Esempio n. 3
0
def test_should_compile():
    "Make sure that modules should be (re)compiled or not."
    filename = Path('tests/pkg4/mod4.nim')

    assert not Nimporter.is_hashed(filename)
    assert Nimporter.hash_changed(filename)
    assert not Nimporter.is_built(filename)
    assert not Nimporter.is_cache(filename)
    assert not NimCompiler.pycache_dir(filename).exists()
    assert not Nimporter.IGNORE_CACHE
    assert Nimporter.should_compile(filename)
Esempio n. 4
0
def main(args=None):
    parser = argparse.ArgumentParser(description='Nimporter CLI')
    subs = parser.add_subparsers(dest='cmd', required=True)

    subs.add_parser('clean')
    build = subs.add_parser('build')
    build.add_argument('source',
                       type=pathlib.Path,
                       help='the Nim module/library to compile')
    build.add_argument('--dest',
                       type=pathlib.Path,
                       help='the folder to store the build artifact')

    args = parser.parse_args(args or sys.argv[1:])

    if args.cmd == 'clean':
        cwd = pathlib.Path()
        print('Cleaning Directory:', cwd.resolve())
        clean(cwd)

    elif args.cmd == 'build':
        args.source = args.source.absolute()

        if not args.dest:
            args.dest = NimCompiler.build_artifact(args.source).parent

        else:
            assert args.dest.is_dir(), (
                'Cannot specify output filename since extensions change per '
                'platform. Please specify an output directory such as ".".')

        args.dest.mkdir(exist_ok=True)

        module = args.source

        if args.source.is_dir():
            is_library = bool([*module.glob('*.nimble')])
            assert is_library, 'Library dir must contain <libname>.nimble file'

        elif args.source.is_file():
            is_library = bool([*module.parent.glob('*.nimble')])
            if is_library: module = module.parent

        temp_build_dir = pathlib.Path('build').absolute()
        temp_build_dir.mkdir(exist_ok=True)
        artifact = temp_build_dir / (args.source.stem + NimCompiler.EXT)

        try:
            NimCompiler.compile_nim_code(module, artifact, library=is_library)
            shutil.copy(artifact, args.dest)
            module_name = args.source.stem + '.nim'
            Nimporter.update_hash(args.dest.parent / module_name)
        finally:
            shutil.rmtree(temp_build_dir)
Esempio n. 5
0
def test_find_extensions():
    "Make sure that all Nim modules and libraries can be found."
    gold = {
        Path('tests/proj1/proj1/lib1'),
        Path('tests/proj1/proj1/performance.nim')
    }
    for ext in Nimporter._find_extensions(Path('tests/proj1')):
        assert ext in gold
Esempio n. 6
0
def test_build_extension_module():
    "Make sure A Nim module compiles to C and an Extension object is built."
    module = Path('tests/proj1/proj1/performance.nim')
    ext = Nimporter._build_nim_extension(module, Path('tests/proj1'))

    assert isinstance(ext, Extension)
    assert ext.name == 'proj1.performance'

    includes = set(Path(i) for i in ext.include_dirs)

    for source in ext.sources:
        src = Path(source).absolute()
        assert src.suffix == '.c'
Esempio n. 7
0
def test_build_extension_library():
    "Make sure a Nim library compiles to C and an Extension object is built."

    library = Path('tests/proj1/proj1/lib1')
    ext = Nimporter._build_nim_extension(library, Path('tests/proj1'))

    assert isinstance(ext, Extension)
    assert ext.name == 'proj1.lib1'

    includes = set(Path(i) for i in ext.include_dirs)

    for source in ext.sources:
        src = Path(source).absolute()
        assert src.suffix == '.c'
Esempio n. 8
0
def test_build_all_extensions():
    "Make sure all extensions within a project are compiled correctly."

    extension_names = {'proj2.lib1', 'proj2.performance'}
    extensions = Nimporter.build_nim_extensions(Path('tests/proj2'))
    assert len(extensions) == 2

    for ext in extensions:
        assert ext.name in extension_names
        assert isinstance(ext, Extension)

        includes = set(Path(i) for i in ext.include_dirs)

        for source in ext.sources:
            src = Path(source).absolute()
            assert src.suffix == '.c'
Esempio n. 9
0
def test_hash_coincides():
    "Make sure an imported Nim module's hash matches the actual source file."
    from pkg1 import mod1
    assert not Nimporter.hash_changed(Path('tests/pkg1/mod1.nim'))
Esempio n. 10
0
def test_hash_filename():
    "Make sure that the file used to store the hash is the correct path."
    module = Path('tests/pkg1/mod2.nim')
    proper_hash = Path('tests/pkg1/__pycache__/mod2.nim.hash').resolve()
    assert Nimporter.hash_filename(module) == proper_hash
Esempio n. 11
0
def main(cli_args=None):
    parser = argparse.ArgumentParser(description='Nimporter CLI')
    subs = parser.add_subparsers(dest='cmd', required=True)

    # Clean command
    subs.add_parser(
        'clean',
        help=(
            'Run in project root to recursively remove all Nimporter-specific '
            'build artifacts and hash files'))

    # Build command
    build = subs.add_parser(
        'build',
        help=(
            'Builds a Nim module/library into an importable Python extension'))
    build.add_argument('source',
                       type=pathlib.Path,
                       help='the Nim module/library to compile')
    build.add_argument('--dest',
                       type=pathlib.Path,
                       help='the folder to store the build artifact')

    # Bundle command
    bundle_parser = subs.add_parser(
        'bundle',
        help=(
            'Convenience command for running: python setup.py sdist/bdist_wheel'
        ))
    bundle = bundle_parser.add_subparsers(dest='exp', required=True)
    bin_ = bundle.add_parser('bin')
    src = bundle.add_parser('src')

    # Compile command
    compile_ = subs.add_parser(
        'compile',
        help=('Clean project and then recurse through and build all Nim '
              'modules/libraries'))

    args = parser.parse_args(cli_args or sys.argv[1:])

    if args.cmd == 'clean':
        cwd = pathlib.Path()
        print('Cleaning Directory:', cwd.resolve())
        clean(cwd)

    elif args.cmd == 'build':
        args.source = args.source.absolute()

        if not args.dest:
            args.dest = NimCompiler.build_artifact(args.source).parent

        else:
            assert args.dest.is_dir(), (
                'Cannot specify output filename since extensions change per '
                'platform. Please specify an output directory such as ".".')

        args.dest.mkdir(exist_ok=True)

        module = args.source

        if args.source.is_dir():
            is_library = bool([*module.glob('*.nimble')])
            assert is_library, 'Library dir must contain <libname>.nimble file'

        elif args.source.is_file():
            is_library = bool([*module.parent.glob('*.nimble')])
            if is_library: module = module.parent

        temp_build_dir = pathlib.Path('build').absolute()
        temp_build_dir.mkdir(exist_ok=True)
        artifact = temp_build_dir / (args.source.stem + NimCompiler.EXT)

        try:
            NimCompiler.compile_nim_code(module, artifact, library=is_library)
            shutil.copy(artifact, args.dest)
            module_name = args.source.stem + '.nim'
            Nimporter.update_hash(args.dest.parent / module_name)
        finally:
            shutil.rmtree(temp_build_dir)

    elif args.cmd == 'bundle':
        setup = pathlib.Path('setup.py')

        if not setup.exists():
            print('No setup.py found in dir, would you like to generate one?')

            answer = 'a'
            while answer not in 'YN':
                answer = input('  Y/N: ').upper() or 'a'

            if answer == 'Y':
                setup.write_text(SETUPPY_TEMPLATE)

                print('Generated reference setup.py')
                print('Modify setup.py to point to your modules/packages.')

                bundle_type = 'source' if args.exp == 'src' else 'binary'

                print(
                    f'Once you have finished, run `{" ".join(cli_args)}` again '
                    f'to create a {bundle_type} distribution package.')
        else:
            pyexe = 'python' if sys.platform == 'win32' else 'python3'

            if args.exp == 'bin':
                subprocess.Popen(
                    f'{pyexe} setup.py bdist_wheel'.split()).wait()

            elif args.exp == 'src':
                subprocess.Popen(f'{pyexe} setup.py sdist'.split()).wait()

    elif args.cmd == 'compile':
        clean()

        CTM = lambda: round(time.time() * 1000)
        start = CTM()
        extensions = Nimporter._find_extensions(pathlib.Path())

        for extension in extensions:
            is_lib = extension.is_dir()

            print(f'Building Extension {"Lib" if is_lib else "Mod"}: '
                  f'{extension.name}')

            NimCompiler.compile_nim_code(extension.absolute(),
                                         NimCompiler.build_artifact(
                                             extension.absolute()),
                                         library=is_lib)

            if is_lib:
                Nimporter.update_hash(extension / (extension.name + '.nim'))
            else:
                Nimporter.update_hash(extension)

        print('Done.')
        print(f'Built {len(extensions)} Extensions In '
              f'{(CTM() - start) / 1000.0} secs')

    return 0
Esempio n. 12
0
def main(cli_args=None):
    parser = argparse.ArgumentParser(description='Nimporter CLI')
    subs = parser.add_subparsers(dest='cmd', required=True)

    subs.add_parser('clean')
    build = subs.add_parser('build')
    build.add_argument(
        'source',
        type=pathlib.Path,
        help='the Nim module/library to compile'
    )
    build.add_argument(
        '--dest',
        type=pathlib.Path,
        help='the folder to store the build artifact'
    )

    bundle_parser = subs.add_parser('bundle')
    bundle = bundle_parser.add_subparsers(dest='exp', required=True)
    bin_ = bundle.add_parser('bin')
    src = bundle.add_parser('src')
    args = parser.parse_args(cli_args or sys.argv[1:])

    if args.cmd == 'clean':
        cwd = pathlib.Path()
        print('Cleaning Directory:', cwd.resolve())
        clean(cwd)

    elif args.cmd == 'build':
        args.source = args.source.absolute()

        if not args.dest:
            args.dest = NimCompiler.build_artifact(args.source).parent

        else:
            assert args.dest.is_dir(), (
                'Cannot specify output filename since extensions change per '
                'platform. Please specify an output directory such as ".".'
            )

        args.dest.mkdir(exist_ok=True)

        module = args.source

        if args.source.is_dir():
            is_library = bool([*module.glob('*.nimble')])
            assert is_library, 'Library dir must contain <libname>.nimble file'

        elif args.source.is_file():
            is_library = bool([*module.parent.glob('*.nimble')])
            if is_library: module = module.parent

        temp_build_dir = pathlib.Path('build').absolute()
        temp_build_dir.mkdir(exist_ok=True)
        artifact = temp_build_dir / (args.source.stem + NimCompiler.EXT)

        try:
            NimCompiler.compile_nim_code(
                module, artifact, library=is_library
            )
            shutil.copy(artifact, args.dest)
            module_name = args.source.stem + '.nim'
            Nimporter.update_hash(args.dest.parent / module_name)
        finally:
            shutil.rmtree(temp_build_dir)

    elif args.cmd == 'bundle':
        setup = pathlib.Path('setup.py')

        if not setup.exists():
            print('No setup.py found in dir, would you like to generate one?')

            answer = 'a'
            while answer not in 'YN':
                answer = input('  Y/N: ').upper() or 'a'

            if answer == 'Y':
                setup.write_text(
                    f'# Setup.py tutorial:\n'
                    f'# https://github.com/navdeep-G/setup.py\n'
                    f'# Edit `packages=` to fit your requirements\n'
                    f'import setuptools, nimporter\n\n'
                    f'setuptools.setup(\n'
                    f'    name="{pathlib.Path().absolute().name}",\n'
                    f'    packages=[..],  # Please read the above tutorial\n'
                    f'    ext_modules=nimporter.build_nim_extensions()\n'
                    f')\n'
                )

                print('Generated reference setup.py')
                print('Modify setup.py to point to your modules/packages.')

                bundle_type = 'source' if args.exp == 'src' else 'binary'

                print(
                    f'Once you have finished, run `{" ".join(cli_args)}` again '
                    f'to create a {bundle_type} distribution package.'
                )
        else:
            pyexe = 'python' if sys.platform == 'win32' else 'python3'

            if args.exp == 'bin':
                subprocess.Popen(f'{pyexe} setup.py bdist_wheel'.split()).wait()

            elif args.exp == 'src':
                subprocess.Popen(f'{pyexe} setup.py sdist'.split()).wait()

    return 0