コード例 #1
0
    def _check_python_file(self, fname: str) -> None:
        from efrotools import get_public_license, PYVER
        with open(fname, encoding='utf-8') as infile:
            contents = infile.read()
            lines = contents.splitlines()

        # Make sure all standalone scripts are pointing to the right
        # version of python (with a few exceptions where it needs to
        # differ)
        if contents.startswith('#!/'):
            copyrightline = 1
            if fname not in ['tools/vmshell']:
                if not contents.startswith(f'#!/usr/bin/env python{PYVER}'):
                    raise CleanError(f'Incorrect shebang (first line) for '
                                     f'{fname}.')
        else:
            copyrightline = 0

        # Special case: it there's spinoff autogenerate notice there,
        # look below it.
        if (lines[copyrightline] == ''
                and 'THIS FILE IS AUTOGENERATED' in lines[copyrightline + 1]):
            copyrightline += 2

        # In all cases, look for our one-line legal notice.
        # In the public case, look for the rest of our public license too.
        if self._license_line_checks:
            public_license = get_public_license('python')
            private_license = '# ' + get_legal_notice_private()
            lnum = copyrightline
            if len(lines) < lnum + 1:
                raise RuntimeError('Not enough lines in file:', fname)

            disable_note = ('NOTE: You can disable license line'
                            ' checks by adding "license_line_checks": false\n'
                            'to the root dict in config/localconfig.json.\n'
                            'see https://ballistica.net/wiki'
                            '/Knowledge-Nuggets#'
                            'hello-world-creating-a-new-game-type')

            if self._public:
                # Check for public license only.
                if lines[lnum] != public_license:
                    raise CleanError(f'License text not found'
                                     f" at '{fname}' line {lnum+1};"
                                     f' please correct.\n'
                                     f'Expected text is: {public_license}\n'
                                     f'{disable_note}')
            else:
                # Check for public or private license.
                if (lines[lnum] != public_license
                        and lines[lnum] != private_license):
                    raise CleanError(f'License text not found'
                                     f" at '{fname}' line {lnum+1};"
                                     f' please correct.\n'
                                     f'Expected text (for public files):'
                                     f' {public_license}\n'
                                     f'Expected text (for private files):'
                                     f' {private_license}\n'
                                     f'{disable_note}')
コード例 #2
0
    def _check_makefiles(self) -> None:
        from efrotools import get_public_license

        # Run a few sanity checks on whatever makefiles we come across.
        fnames = subprocess.run('find . -maxdepth 3 -name Makefile',
                                shell=True,
                                capture_output=True,
                                check=True).stdout.decode().split()
        fnames = [n for n in fnames if '/build/' not in n]

        for fname in fnames:
            with open(fname, encoding='utf-8') as infile:
                makefile = infile.read()
            if self._public:
                public_license = get_public_license('makefile')
                if public_license not in makefile:
                    raise CleanError(f'Pub license not found in {fname}.')
            else:
                if (get_legal_notice_private() not in makefile
                        and get_public_license('makefile') not in makefile):
                    raise CleanError(
                        f'Priv or pub legal not found in {fname}.')
コード例 #3
0
def generate(projroot: str, infilename: str, outfilename: str) -> None:
    """Main script entry point."""
    from batools.project import project_centric_path

    out = (get_public_license('python') +
           f'\n"""Enum vals generated by {__name__}; do not edit by hand."""'
           f'\n\nfrom enum import Enum\n')

    out += _gen_enums(infilename)

    path = project_centric_path(projroot=projroot, path=outfilename)
    print(f'Meta-building {Clr.BLD}{path}{Clr.RST}')
    os.makedirs(os.path.dirname(outfilename), exist_ok=True)
    with open(outfilename, 'w', encoding='utf-8') as outfile:
        outfile.write(out)
コード例 #4
0
    def _check_c_license(self, fname: str, lines: list[str]) -> None:
        from efrotools import get_public_license

        # Look for public license line (public or private repo)
        # or private license line (private repo only)
        line_private = '// ' + get_legal_notice_private()
        line_public = get_public_license('c++')
        lnum = 0

        if self._public:
            if lines[lnum] != line_public:
                # Allow auto-correcting from private to public line
                allow_auto = lines[lnum] == line_private
                self._add_line_correction(fname,
                                          line_number=lnum,
                                          expected=line_public,
                                          can_auto_update=allow_auto)
        else:
            if lines[lnum] not in [line_public, line_private]:
                self._add_line_correction(fname,
                                          line_number=lnum,
                                          expected=line_private,
                                          can_auto_update=False)
コード例 #5
0
def generate(sources_hash: str, outfilename: str) -> None:
    """Run the actual generation from within the game."""
    import _ba as module
    from efrotools import get_public_license, PYVER
    import types
    funcnames = []
    classnames = []
    for entry in (e for e in dir(module) if not e.startswith('__')):
        if isinstance(getattr(module, entry), types.BuiltinFunctionType):
            funcnames.append(entry)
        elif isinstance(getattr(module, entry), type):
            classnames.append(entry)
        elif entry == 'app':
            # Ignore _ba.app.
            continue
        else:
            raise Exception(
                f'found unknown obj {entry}, {getattr(module, entry)}')
    funcnames.sort()
    classnames.sort()
    out = (get_public_license('python')
           + '\n'
           '#\n'
           '"""A dummy stub module for the real _ba.\n'
           '\n'
           'The real _ba is a compiled extension module and only available\n'
           'in the live game. This dummy module allows Pylint/Mypy/etc. to\n'
           'function reasonably well outside of the game.\n'
           '\n'
           'Make sure this file is never included in an actual game distro!\n'
           '\n'
           'Ideally this should be a stub (.pyi) file, but we\'d need\n'
           'to make sure that it still works with all our tools\n'
           '(mypy, pylint, pycharm).\n'
           '\n'
           'NOTE: This file was autogenerated by ' + __name__ + '; '
           'do not edit by hand.\n'
           '"""\n'
           '\n'
           # '# (hash we can use to see if this file is out of date)\n'
           # '# SOURCES_HASH='+sources_hash+'\n'
           # '\n'
           '# I\'m sorry Pylint. I know this file saddens you. Be strong.\n'
           '# pylint: disable=useless-suppression\n'
           '# pylint: disable=unnecessary-pass\n'
           '# pylint: disable=use-dict-literal\n'
           '# pylint: disable=use-list-literal\n'
           '# pylint: disable=unused-argument\n'
           '# pylint: disable=missing-docstring\n'
           '# pylint: disable=too-many-locals\n'
           '# pylint: disable=redefined-builtin\n'
           '# pylint: disable=too-many-lines\n'
           '# pylint: disable=redefined-outer-name\n'
           '# pylint: disable=invalid-name\n'
           '# pylint: disable=no-value-for-parameter\n'
           '\n'
           'from __future__ import annotations\n'
           '\n'
           'from typing import TYPE_CHECKING, overload, Sequence, TypeVar\n'
           '\n'
           'from ba._generated.enums import TimeFormat, TimeType\n'
           '\n'
           'if TYPE_CHECKING:\n'
           '    from typing import Any, Callable, Optional, Union, Literal\n'
           '    from ba._app import App\n'
           '    import ba\n'
           '\n'
           '\n'
           "_T = TypeVar('_T')\n"
           '\n'
           'app: App\n'
           '\n'
           'def _uninferrable() -> Any:\n'
           '    """Get an "Any" in mypy and "uninferrable" in Pylint."""\n'
           '    # pylint: disable=undefined-variable\n'
           '    return _not_a_real_variable  # type: ignore'
           '\n'
           '\n'
           )  # yapf: disable

    out += _writeclasses(module, classnames)
    out += _writefuncs(module, funcnames, indent=0, spacing=2, as_method=False)

    outhashpath = os.path.join(os.path.dirname(outfilename),
                               '._ba_sources_hash')

    with open(outfilename, 'w', encoding='utf-8') as outfile:
        outfile.write(out)

    with open(outhashpath, 'w', encoding='utf-8') as outfile:
        outfile.write(sources_hash)

    # Lastly, format it.
    subprocess.run([f'python{PYVER}', '-m', 'yapf', '--in-place', outfilename],
                   check=True)
コード例 #6
0
    def _check_python_file(self, fname: str) -> None:
        # pylint: disable=too-many-branches
        from efrotools import get_public_license
        with open(fname) as infile:
            contents = infile.read()
            lines = contents.splitlines()

        # Make sure all standalone scripts are pointing to the right
        # version of python (with a few exceptions where it needs to
        # differ)
        if contents.startswith('#!/'):
            copyrightline = 1
            if fname not in [
                    'tools/devtool', 'tools/version_utils', 'tools/vmshell'
            ]:
                if not contents.startswith('#!/usr/bin/env python3.7'):
                    print(f'{Clr.RED}Incorrect shebang (first line) for '
                          f'{fname}.{Clr.RST}')
                    sys.exit(255)
        else:
            copyrightline = 0

        # Special case: it there's spinoff autogenerate notice there,
        # look below it.
        if (lines[copyrightline] == ''
                and 'THIS FILE IS AUTOGENERATED' in lines[copyrightline + 1]):
            copyrightline += 2

        # In all cases, look for our one-line legal notice.
        # In the public case, look for the rest of our public license too.
        if self._copyright_checks:
            public_license = get_public_license('python')
            line = '# ' + get_legal_notice_private()

            # (Sanity check: public license's first line should be
            # same as priv)
            if line != public_license.splitlines()[0]:
                raise RuntimeError(
                    'Public license first line should match priv.')

            lnum = copyrightline
            if len(lines) < lnum + 1:
                raise RuntimeError('Not enough lines in file:', fname)

            if lines[lnum] != line:
                # Allow auto-correcting if it looks close already
                # (don't want to blow away an unrelated line)
                allow_auto = 'Copyright' in lines[
                    lnum] and 'Eric Froemling' in lines[lnum]
                self._add_line_correction(fname,
                                          line_number=lnum,
                                          expected=line,
                                          can_auto_update=allow_auto)
                found_intact_private = False
            else:
                found_intact_private = True

            if self._public:
                # Check for the full license.
                # If we can't find the full license but we found
                # a private-license line, offer to replace it with the
                # full one. Otherwise just complain and die.

                # Try to be reasonably certain it's not in here...
                definitely_have_full = public_license in contents
                might_have_full = ('Permission is hereby granted' in contents
                                   or 'THE SOFTWARE IS PROVIDED' in contents)

                # Only muck with it if we're not sure we've got it.
                if not definitely_have_full:
                    if found_intact_private and not might_have_full:
                        self._add_line_correction(fname,
                                                  line_number=lnum,
                                                  expected=public_license,
                                                  can_auto_update=True)
                    else:
                        raise RuntimeError(
                            f'Found incorrect license text in {fname};'
                            f' please correct.')