- The document discusses customizing PyPy by creating a custom module that can be included and built within PyPy. It covers adding the module code, interface, tests, and integrating it into the PyPy command line.
- Key aspects include adding the module code in a pypy/module directory, exposing interfaces in __init__.py, writing both app and interp level Python code, and testing at both levels.
- The command line is customized by modifying app_main.py and targetpypystandalone.py to include and run the custom module's code.
4. Interface in __init__.py Exposes symbols to the "user" from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): interpleveldefs = {} appleveldefs = { 'commands' : 'app_commands.COMMANDS', 'find_commands' : 'app_commands.find_commands', 'CommandError' : 'app_commands.CommandError', }
5. App Level Python Start with #NOT RPYTHON Consider your imports carefully And then write python like you normally will
6. Testing - App Level Hacking a module is pain . Roundtrip to build executable is >30 mins TDD wins Write unit tests to cover as much as you can. Time to write pypy/module/test/test_one.py
7. Testing - App Level Python Beware of imports and test setup mocks from pypy.conftest import gettestobjspace class AppTestCall(object): def setup_class(cls): # import mymod, sys space = cls.space = gettestobjspace(usemodules=('mymod','sys',)) # sys.app_name = "pypy-c" space.setattr(space.sys, space.wrap("app_name"), space.wrap("pypy-c")) def test_mymod(): import mymod
8. Interface in __init__.py Exposes symbols to the "user" from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): interpleveldefs = { 'find_module': 'interp_imp.find_module',} appleveldefs = {}
9. Interp Level Python RPython for Speed You can implement the internals of a module in RPython which will be compiled to binary. It is your responsibility to handle wrapping and unwrapping def find_module(space, w_name, w_path=None): name = space.str_w(w_name) if space.is_w(w_path, space.w_None): w_path = None return space.newtuple([w_fileobj, w_filename, w_import_info])
10. Testing - Interp Level Python Beware of imports and test setup mocks from pypy.conftest import gettestobjspace class AppTestImpModule: def setup_class(cls): cls.w_imp = cls.space.getbuiltinmodule('imp') def test_find_module(self): import os file, pathname, description = self.imp .find_module('StringIO')
11. Customising the Command Line pypy/translator/goal/ targetpypystandalone.py # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') app = gateway.applevel(open(filename).read(), 'app_main.py', 'app_main') Keep changes to a minimum as you have to build a binary to test them!
12. Customising the Command Line pypy/translator/goal/ app_main.py def run_command_line(.. settings .., cmd=None, **ignored): mainmodule = type(sys)('__main__') import site if run_command: ... elif run_module: ... elif run_stdin: # piped or interactive shell ... else: import installation if not sys.argv[0].endswith(".py") and sys.argv[0].find("/") == -1: argv = sys.argv[:] argv.insert(0,"") installation.commands.execute(argv) success = True else: ...
13. Main Sequence (I¨m not too sure about this) nanos module app_main.py ... full os module ... run_command_line(..) site.py sitecustomize.py main module/script/interpreter loading
14. Command Line Parsers app_main.py: def parse_command_line(argv) optparse.OptionParser argsparse.ArgsParser
15. My Objective Objective Self updating Filesystem monitoring Network Peer Daemon/Service capable Configurable command line
16. Building PyPy Add to pypy/config/pypyoptions.py (or) Use --with- mymod cd pypy/translator/goal translate.py --with- mymod targetpypystandalone.py