From fa9452f54750b7c118b724c201394b4a0eed9db7 Mon Sep 17 00:00:00 2001 From: awildtechno Date: Tue, 11 Jun 2019 16:26:56 -0700 Subject: [PATCH 01/29] Updated the how-tos with a bunch of stuff. Split out tests to its own section. Added a tour of the code. Fixed a grammar error. --- docs/how-to/builtins.rst | 79 ++++++++++---------- docs/how-to/contribute-docs.rst | 2 +- docs/how-to/contribute-tests.rst | 118 ++++++++++++++++++++++++++++++ docs/how-to/index.rst | 2 + docs/how-to/tour.rst | 122 +++++++++++++++++++++++++++++++ 5 files changed, 284 insertions(+), 39 deletions(-) create mode 100644 docs/how-to/contribute-tests.rst create mode 100644 docs/how-to/tour.rst diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 1403a4e35..50eafffe8 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -22,7 +22,7 @@ directory in the Batavia code. Each built-in is placed inside its own file. throw new builtins.BataviaError.$pyclass("Batavia calling convention not used."); } - // We are now checking if a kwargs object is passed. If it isn't kwargs will be null. Like + // We are now checking if a kwargs object is passed. If it isn't, kwargs will be null. Like // obj.keys() in Python we can use Object.keys(obj) to get the keys of an object. If the // function doesn't need support any kwargs we throw an error. if (kwargs && Object.keys(kwargs).length > 0) { @@ -46,59 +46,62 @@ directory in the Batavia code. Each built-in is placed inside its own file. Javascript.Function.Stuff(); } - .__doc__ = 'docstring from Python 3.4 goes here, for documentation' + .__doc__ = 'docstring from Python 3.x goes here, for documentation' modules.export = +Building Blocks of Batavia +-------------------------- -Adding Tests ------------- +This section is a quick reference for things you'll see often in the codebase. -The tests corresponding to Batavia implementations of built-ins are available inside -``tests/builtins``. The Batavia test infrastructure includes a system to check the compatibility of -JavaScript implementation of Python with the reference CPython implementation. +builtins.js +*********** -It does this by running a test in the Python interpreter, and then running the same code using -Batavia in the Node.js JavaScript interpreter. It will compare the output in both cases to see if -they match. Furthermore the test suite will automatically test the builtin against values of all -data types to check if it gets the same response across both implementations. +This contains all of the native Python builtin functions, like ``str``, ``len``, and ``iter``. -In many cases these tests will not cover everything, so you can add your own. For an example look at -the ``test_bool.py`` file in ``tests/builtins``. You will see two classes with test cases, -``BoolTests`` and ``BuiltinBoolFunctionTests``. Both derive from ``TranspileTestCase`` which -handles running your code in both interpreters and comparing outputs. +When dealing with Python types, many of the native JavaScript operations have been overriden to +try to use these first. For instance, .toString() will often just call the object's __str__. -Let's look at some test code that checks if a the Batavia implementation of ``bool`` can handle a -bool-like class that implements ``__bool__``. +Note again that *args* and *kwargs* are required for most builtins, even if empty. -.. code-block:: Python +types.js +******** - def test_bool_like(self): - self.assertCodeExecution(""" - class BoolLike: - def __init__(self, val): - self.val = val +This contains all of the native Python types that have been implemented in Batavia. It also has some helper functions: - def __bool__(self): - return self.val == 1 - print(bool(BoolLike(0))) - print(bool(BoolLike(1))) - """) +* ``types.js2py`` Converts a native JavaScript type to a corresponding Batavia type. +* ``types.isinstance`` checks to see if the object is a Python instance of the corresponding type. +* ``types.isbataviainstance`` checks to see if the object is an instance of any Batavia type. +* ``types.type_name`` get the name of the type. -The ``assertCodeExecution`` method will run the code provided to it in both implementations. This -code needs to generate some output so that the output can be compared, hence the need to print the -values. +Where possible, use Python types from types.js instead of native JavaScript objects and types. +This allows us to avoid things like comparing ``Object.prototype.constructor``. Instead, use these helpers! +core/callables.js +***************** -Process ----------- +These methods ensure that all Python code is executed using the proper __call__ procedure, which could occasionally +have something special built in or be overriden or decorated by the programmer. -For a given function, run `functionname.__doc__` in the Python 3.4 repl +* ``callables.call_function`` Invokes a function using its __call__ method if possible. If not, just call it normally. +* ``callables.call_method`` Calls a class method using the call_function specification above. +* ``callables.iter_for_each`` Exhausts an iterable using the call_function specification above. -Copy the docstring into the doc +As a general rule, use the builtin where possible. If no builtin is available, use the appropriate version +of ``call_function`` instead of calling Python functions and methods directly. An example: -Run the function in Python 3.4 +.. code-block:: javascript + + // Avoid this + my_thing.__repr__() + + // Better + const callables = require('./core/callables.js') + callables.call_method(my_thing, '__repr__', [], {}) -Take a guess at the implementation structure based on the other functions. + // Best + const repr = require('./builtins.js').repr + repr(my_thing, [], {}) -Copy the style of the other implemented functions +Note the use of the Batavia calling convention in the two cases above! \ No newline at end of file diff --git a/docs/how-to/contribute-docs.rst b/docs/how-to/contribute-docs.rst index 3ef7f5d32..ff8bc02d1 100644 --- a/docs/how-to/contribute-docs.rst +++ b/docs/how-to/contribute-docs.rst @@ -28,6 +28,6 @@ Create the static files: :: $ make html -Check for any errors and,if possible, fix them. +Check for any errors and, if possible, fix them. The output of the file should be in the ``_build/html`` folder. Open the file you changed in the browser. diff --git a/docs/how-to/contribute-tests.rst b/docs/how-to/contribute-tests.rst new file mode 100644 index 000000000..e12013ef5 --- /dev/null +++ b/docs/how-to/contribute-tests.rst @@ -0,0 +1,118 @@ +Implementing Tests in Batavia +============================= + +Basic Test Structure +-------------------- + +Batavia's job is to run a browser-compatible Python compiler, which takes valid Python as input and runs it. +Therefore, tests should test that the output of the Batavia compiler matches the output of CPython:: + + print('Hello') # Code to test + Hello # CPython output + Hello # Batavia output + # Outputs match. Test passes! + +This test structure is simple and effective. It's used in almost every test we've written. + +Adding Tests +------------ + +In many cases, existing tests will not cover everything. Feel free to add your own! + +The tests corresponding to Batavia implementations of built-ins are available inside +``tests/builtins``. The Batavia test infrastructure includes a system to check the compatibility of +JavaScript implementation of Python with the reference CPython implementation. + +These all tests derive from ``TranspileTestCase``, which handles running your code in both interpreters +and comparing outputs. For an example look at the ``test_bool.py`` file in ``tests/builtins``. You +will see two classes with test cases, ``BoolTests`` and ``BuiltinBoolFunctionTests``. Both derive +from ``TranspileTestCase``. + +Let's look at some test code that checks if a the Batavia implementation of ``bool`` can handle a +bool-like class that implements ``__bool__``. + +.. code-block:: Python + + def test_bool_like(self): + self.assertCodeExecution(""" + class BoolLike: + def __init__(self, val): + self.val = val + + def __bool__(self): + return self.val == 1 + print(bool(BoolLike(0))) + print(bool(BoolLike(1))) + """) + +The ``assertCodeExecution`` method will run the code provided to it in both implementations. This +code needs to generate some output so that the output can be compared, hence the need to print the +values. **Code that is not being printed is not being tested.** + +Template +-------- + +.. code-block:: python + + def test__(self): + # Valid Python code to be tested. + code = """ + print('>>> print()') + print() + """ + self.assertCodeExecution(code) + +This code block provides a printout of the code being run as well as the output of the code, +which can be very useful for debugging in test cases where a decent amount of code is being run. + +Testing for Errors +------------------ + +Since we're compiling Python, we need to ensure that errors for all of the builtins are thrown correctly. +We also want to ensure that we're not accepting the wrong errors in our tests. Simply include a try/except +block in your test. + +.. code-block:: python + + def test_some_error(self): + code = """ + try: + code_that_raises_a_ValueError() + except ValueError as err: + print(err) + """ + self.assertCodeExecution(code) + +Remember to catch the specific error you want, and then print the error. **Code that is not being printed +is not being tested.** + +Output Cleaners +--------------- + +In some cases, the test output will vary. ``TranspileTestCase`` will automatically apply some common output +cleanup for you. Some cases will need more or less cleanup. If you run your Python code directly in the REPL, +and the output differs from the test case output, you may need to modify what cleanup steps are being run. + +As such, ``assertCodeExecution`` accepts optional ``js_cleaner`` and ``py_cleaner`` objects. These can be provided by +the ``@transform`` decorator, located in ``tests/utils/output_cleaners.py``. Here's an example: + +.. code-block:: python + + @transform(float_exp=False) + def test_some_floats(self, js_cleaner, py_cleaner): # + Cleaner objects as arguments + code = ... + self.assertCodeExecution(code, js_cleaner=js_cleaner, py_cleaner=py_cleaner) # + Cleaner objects again + +This code means that the output of floating-point numbers will not be normalized using a regex. Refer to other +test cases and the docstring for ``@transform`` for more examples. + +Node/Python Crashes +------------------- + +If the CPython or JavaScript code crashes outright, UnitTest struggles. For instance, +``confused END_FINALLY`` in the middle of your test output tends to mean that the JavaScript code threw an +uncaught exception, causing Node to stop. It's hard for UnitTest to pull the details out of this type of thing +since that error occurred in the virtual machine. + +These types of errors will often appear above the test case as a crash report instead of in the usual section for the +output of your test's print() statements. Look there for clues. \ No newline at end of file diff --git a/docs/how-to/index.rst b/docs/how-to/index.rst index 1453651ac..22bf5c270 100644 --- a/docs/how-to/index.rst +++ b/docs/how-to/index.rst @@ -10,7 +10,9 @@ How-to guides are recipes that take the user through steps in key subjects. They :maxdepth: 1 :glob: + Tour of the Code Contribute to Batavia's code Contribute to Batavia's documentation + Follow the Goat: Batavia's Test Suite Implementing Python Built-ins in JavaScript Adding a module and testing it diff --git a/docs/how-to/tour.rst b/docs/how-to/tour.rst new file mode 100644 index 000000000..1d14be4f0 --- /dev/null +++ b/docs/how-to/tour.rst @@ -0,0 +1,122 @@ +Tour of the Code +================ + +Before getting started, it's nice to know a bit about how the project is structured and where +to look for examples. This document aims to provide a brief tour of the +important features of the code. It's aimed at new contributors, but frequent flyers can +skip down to the bottom for a quick reference. + +General Structure +----------------- + +Core Code +********* + +Batavia implements the Python native types, builtins, and standard library partially in JavaScript. +This ensures quick execution and less compiling of the compiler. These are orgainzed into the +``builtins``, ``core``, ``modules``, ``stdlib``, and ``types`` files of the main ``/batavia`` directory, with +corresponding subdirectories. Alongside the virtual machine and test suite, this code makes +up the bulk of Batavia. New contributors should start with the ``types`` and ``builtins`` sections +for the best examples to review and copy from. These implementations are the foundation of Python as you know it and +should be immediately familiar to a Python developer. + +Support +******* +You'll also notice folders for tests, docs, and a few other bits and bobs, like ``testserver``, which is +a Django project that allows code execution. Contributions to the +tests and documentation are always welcome and are great ways to familiarize yourself with the +code and meet the other contributors. + +The Core Code +------------- + +A Word on Args & Kwargs +*********************** + +Batavia's implementations of various builtin functions +often **require** ``args`` and ``kwargs`` as input. Here's an example of calling +the repr of a ``my_thing`` object: ``builtins.repr(my_thing, [], {})`` + +The empty [] and {} arguments represent empty argument and keyword argument parameters. +This mimics how Python handles function arguments behind the scenes, and it's important! + +For instance, what happens when you pass a keyword argument into a list? You might say, +"list() doesn't take keyword arguments." In actuality, the list function does receive those +arguments, and the result is that it throws ``TypeError: '' is an invalid keyword +argument for this function`` + +Batavia needs those arguments explicitly specified in a standard format so that it can +check for that case and generate the correct error. The below code examples all use this calling +convention, and you'll be up to your knees in ``BataviaErrors`` if you're not aware of it. + +Building Blocks of Batavia +************************** + +This section is a quick reference for the most common code you'll see. + +builtins.js +^^^^^^^^^^^ + +.. code-block:: javascript + + var builtins = require('./builtins.js') + builtins.abs([-1], {}) // equivalent to abs(-1) + +This contains all of the native Python builtin functions, like ``str``, ``len``, and ``iter``. + +When dealing with Python types, many of the native JavaScript operations have been modified to +try to use builtins first. For instance, .toString() will often just call the object's __str__ if +possible. Still, the best practice is to use the builtins and types wherever possible. + +types.js +^^^^^^^^ + +.. code-block:: javascript + + var types = require('./types.js) + var my_dict = new types.dict([], {}) + +This contains all of the native Python types that have been implemented in Batavia. It also has some helper functions: + +* ``types.js2py`` Converts a native JavaScript type to a corresponding Batavia type. +* ``types.isinstance`` checks to see if the object is a Python instance of the corresponding type. +* ``types.isbataviainstance`` checks to see if the object is an instance of **any** Batavia type. +* ``types.Type.type_name`` get the name of the type. + +This allows us to avoid ugly things like comparing ``Object.prototype.constructor``. Instead, +use ``types.isinstance`` or ``types.isbataviainstance``. Secondly, it's important that the inputs to Python +types are Pythonized themselves where needed. You should not be making a list() of JavaScript arrays, for +instance. That doesn't make sense! (It may even pass some tests, which is dangerous.) + +core/callables.js +^^^^^^^^^^^^^^^^^ + +These methods ensure that all Python code is executed using the proper __call__ procedure, which could be +overriden or decorated by the programmer. + +* ``callables.call_function`` Invokes a function using its __call__ method if possible. If not, just call it normally. +* ``callables.call_method`` Calls a class method using the call_function specification above. +* ``callables.iter_for_each`` Exhausts an iterable using the call_function specification above. + +As a general rule, use the builtin where possible. If no builtin is available, use the appropriate version +of ``call_function`` instead of calling Python functions and methods directly. An example: + +.. code-block:: javascript + + // Avoid this + my_thing.__repr__() + + // Better + var callables = require('./core/callables.js') + callables.call_method(my_thing, '__repr__', [], {}) + + // Best + var repr = require('./builtins.js').repr + repr(my_thing, [], {}) + +Note the use of the Batavia calling convention in the two cases above! + +/core/version.js +^^^^^^^^^^^^^^^^ +Some helper functions for distinguishing the version of Python that's running. Outputs +vary from version to version, so it's nice to have this handy. \ No newline at end of file From 9705679951435ab15799081d1f652dfc26a7d597 Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 10:43:09 -0700 Subject: [PATCH 02/29] Updated builtins.rst to include a better breakdown and more information. --- docs/how-to/builtins.rst | 154 ++++++++++++++++++++++----------------- 1 file changed, 86 insertions(+), 68 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 50eafffe8..9b2e569dc 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -1,107 +1,125 @@ Implementing Python Built-ins in JavaScript =========================================== +Process +------- + +The first thing to do when adding anything to Batavia is to play around a bit with it in the Python REPL:: + + >> list() + [] + >> [] + [] + >> list(4) + Traceback (most recent call last): + File "", line 1, in + TypeError: 'int' object is not iterable + +Your goal is to find out how the function responds to various inputs and outputs. You may also +want to consult the offical documentation. Once you're a little familiar, you can add your +implementation to Batavia. + General Structure ------------------ +***************** JavaScript versions of Python built-in functions can be found inside the ``batavia/builtins`` -directory in the Batavia code. Each built-in is placed inside its own file. +directory in the Batavia code. Each built-in is placed inside its own file. These builtins are +designed to be used only inside Batavia, as such they need to ensure +they are being used in a compatible manner. + +Each builtin function will receive arguments and keyword arguments and needs to handle them, +even if the result is throwing an error. Args should be an array, and kwargs should be a +JavaScript object. The first thing to do is check that both were passed in. .. code-block:: javascript // Example: a function that accepts exactly one argument, and no keyword arguments - var = function(, ) { - // These builtins are designed to be used only inside Batavia, as such they need to ensure - // they are being used in a compatible manner. - - // Batavia will only ever pass two arguments, args and kwargs. If more or fewer arguments - // are passed, then Batavia is being used in an incompatible way. - // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments + var = function(args, kwargs) { + // Always add this code. if (arguments.length !== 2) { throw new builtins.BataviaError.$pyclass("Batavia calling convention not used."); } - // We are now checking if a kwargs object is passed. If it isn't, kwargs will be null. Like - // obj.keys() in Python we can use Object.keys(obj) to get the keys of an object. If the - // function doesn't need support any kwargs we throw an error. - if (kwargs && Object.keys(kwargs).length > 0) { - throw new builtins.TypeError.$pyclass("() doesn't accept keyword arguments."); - } +Next, we need to validate the arguments are correct. We can use JavaScript's ``Object.keys()`` to +get the keys of an object. If the function pass in the , we will check the Python REPL to see +what kind of error and throw it. - // Now we can check if the function has the supported number of arguments. In this case a - // single required argument. - if (!args || args.length !== 1) { - throw new builtins.TypeError.$pyclass("() expected exactly 1 argument (" + args.length + " given)"); - } +.. tabs:: - // If the function only works with a specific object type, add a test - var obj = args[0]; - if (!types.isinstance(obj, types.)) { - throw new builtins.TypeError.$pyclass( - "() expects a (" + type_name(obj) + " given)"); - } + .. group-tab:: Python REPL - // actual code goes here - Javascript.Function.Stuff(); - } + .. code-block:: - .__doc__ = 'docstring from Python 3.x goes here, for documentation' - - modules.export = + >> list(a=1) + TypeError: list() doesn't accept keyword arguments. + >> list(1, 2, 3) + TypeError: list() expected exactly 1 argument (3 given) -Building Blocks of Batavia --------------------------- + .. group-tab:: Batavia Code -This section is a quick reference for things you'll see often in the codebase. + .. code-block:: javascript -builtins.js -*********** + if (kwargs && Object.keys(kwargs).length > 0) { + throw new exceptions.TypeError.$pyclass("() doesn't accept keyword arguments."); + } -This contains all of the native Python builtin functions, like ``str``, ``len``, and ``iter``. + if (!args || args.length !== 1) { + throw new exceptions.TypeError.$pyclass("() expected exactly 1 argument (" + args.length + " given)"); + } -When dealing with Python types, many of the native JavaScript operations have been overriden to -try to use these first. For instance, .toString() will often just call the object's __str__. + // If the function only works with a specific object type, add a test + var obj = args[0]; + if (!types.isinstance(obj, types.)) { + throw new exceptions.TypeError.$pyclass( + "() expects a (" + type_name(obj) + " given)"); + } -Note again that *args* and *kwargs* are required for most builtins, even if empty. + Useful functions are ``types.isinstance``, which checks for a match against a Batavia type or list, + of Batavia types, ``types.isbataviainstance``, which checks for a match against any Batavia instance, + ``Object.keys(kwargs)`` for dealing with kwargs, and JavaScript's ``for in``, ``for of``, and + ``Array.forEach`` loops for iterating over the JavaScript arrays and objects. -types.js -******** + Note also the format for errors: ``throw new exceptions..$pyclass``. -This contains all of the native Python types that have been implemented in Batavia. It also has some helper functions: +Returning a value +***************** -* ``types.js2py`` Converts a native JavaScript type to a corresponding Batavia type. -* ``types.isinstance`` checks to see if the object is a Python instance of the corresponding type. -* ``types.isbataviainstance`` checks to see if the object is an instance of any Batavia type. -* ``types.type_name`` get the name of the type. +Builtins implement Python functions and should return a Python object. +Batavia implementations of all Python types are located in ``/batavia/types.js``. +JavaScript imports use the ``require`` keyword and can be imported inline or at +the top of the file. Inline imports can be preferable in some cases. -Where possible, use Python types from types.js instead of native JavaScript objects and types. -This allows us to avoid things like comparing ``Object.prototype.constructor``. Instead, use these helpers! +.. code-block:: javascript -core/callables.js -***************** + ... -These methods ensure that all Python code is executed using the proper __call__ procedure, which could occasionally -have something special built in or be overriden or decorated by the programmer. + Tuple = require('../types.js').Tuple + return new Tuple(my, results, here) + } -* ``callables.call_function`` Invokes a function using its __call__ method if possible. If not, just call it normally. -* ``callables.call_method`` Calls a class method using the call_function specification above. -* ``callables.iter_for_each`` Exhausts an iterable using the call_function specification above. +Documentation +************* -As a general rule, use the builtin where possible. If no builtin is available, use the appropriate version -of ``call_function`` instead of calling Python functions and methods directly. An example: +Finally, add the docstring to the function object. In JavaScript, like in Python, functions +are first-class objects and can have additional properties. .. code-block:: javascript - // Avoid this - my_thing.__repr__() + .__doc__ = 'docstring from Python 3.x goes here, for documentation' + + modules.export = - // Better - const callables = require('./core/callables.js') - callables.call_method(my_thing, '__repr__', [], {}) +Tests +***** - // Best - const repr = require('./builtins.js').repr - repr(my_thing, [], {}) +No implemenation for a project like this is complete without tests. Check out the other sections for +more details on test structure. Tests are located in ``/tests`` in a similar folder structure to the +core code, and most test files have already been created. Some things that should almost always be +tested: -Note the use of the Batavia calling convention in the two cases above! \ No newline at end of file +* Write a test or three to ensure your function returns the correct output with some normal inputs. +* Think of a few weird inputs that could throw off your code (or future code). Test them. +* If you are throwing an error (excluding ``BataviaError``) anywhere, write a test for that. +* If you accounted for an edge case (look for an ``if`` statement), +* Check out the official documentation (https://docs.python.org/3/) for more edge cases \ No newline at end of file From 1af71c9ae2a11cd6554d4a919c408a9275a33bb1 Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 10:55:56 -0700 Subject: [PATCH 03/29] Added introduction. Bit of cleanup as well. --- docs/how-to/builtins.rst | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 9b2e569dc..a92775651 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -1,22 +1,30 @@ Implementing Python Built-ins in JavaScript =========================================== +Pythons builtins are the absolute core of the language. If you're new to Python, read up on them here: https://docs.python.org/3/library/functions.html + +Most builtins have already been added to the project, but many do not follow the correct spec outlined below. +Some may not handle certain types of inputs correctly. In addition, new builtins may of course arrive with the +latest and greatest Python version. This guide should serve as your field manual for adding, updating, and +navigating our implementations. + Process ------- -The first thing to do when adding anything to Batavia is to play around a bit with it in the Python REPL:: +The first thing to do when adding anything to Batavia is to play around a bit with it in the Python REPL. +Here's an example using ``list()``:: >> list() [] - >> [] - [] + >> list((1, 2, 3, 4)) + [1, 2, 3, 4] >> list(4) Traceback (most recent call last): File "", line 1, in TypeError: 'int' object is not iterable Your goal is to find out how the function responds to various inputs and outputs. You may also -want to consult the offical documentation. Once you're a little familiar, you can add your +want to consult the offical documentation. Once you're a little familiar, you can start to add your implementation to Batavia. General Structure @@ -24,8 +32,8 @@ General Structure JavaScript versions of Python built-in functions can be found inside the ``batavia/builtins`` directory in the Batavia code. Each built-in is placed inside its own file. These builtins are -designed to be used only inside Batavia, as such they need to ensure -they are being used in a compatible manner. +designed to be used only inside Batavia, as such they need to ensure they are being used in +a compatible manner. Each builtin function will receive arguments and keyword arguments and needs to handle them, even if the result is throwing an error. Args should be an array, and kwargs should be a @@ -33,7 +41,7 @@ JavaScript object. The first thing to do is check that both were passed in. .. code-block:: javascript - // Example: a function that accepts exactly one argument, and no keyword arguments + // Example: accepts exactly one argument, and no keyword arguments var = function(args, kwargs) { // Always add this code. @@ -120,6 +128,6 @@ tested: * Write a test or three to ensure your function returns the correct output with some normal inputs. * Think of a few weird inputs that could throw off your code (or future code). Test them. -* If you are throwing an error (excluding ``BataviaError``) anywhere, write a test for that. -* If you accounted for an edge case (look for an ``if`` statement), -* Check out the official documentation (https://docs.python.org/3/) for more edge cases \ No newline at end of file +* If you are throwing an error (excluding ``BataviaError``) anywhere, write a test that tries to throw it. +* If you accounted for an edge case (look for an ``if`` statement), test it. +* Check out the official documentation (https://docs.python.org/3/) for more edge cases. \ No newline at end of file From dfa868b8d867ab0467aee9f2d361c04fc1771f62 Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 12:38:30 -0700 Subject: [PATCH 04/29] Added types.rst, a similar document to builtins.rst for working with Batavia types. --- docs/how-to/index.rst | 1 + docs/how-to/types.rst | 152 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 docs/how-to/types.rst diff --git a/docs/how-to/index.rst b/docs/how-to/index.rst index 22bf5c270..9ca93aa21 100644 --- a/docs/how-to/index.rst +++ b/docs/how-to/index.rst @@ -15,4 +15,5 @@ How-to guides are recipes that take the user through steps in key subjects. They Contribute to Batavia's documentation Follow the Goat: Batavia's Test Suite Implementing Python Built-ins in JavaScript + Implementing Python Types in JavaScript Adding a module and testing it diff --git a/docs/how-to/types.rst b/docs/how-to/types.rst new file mode 100644 index 000000000..5b1c82420 --- /dev/null +++ b/docs/how-to/types.rst @@ -0,0 +1,152 @@ +Implementing Python Types +=========================================== + +Python native types are the building blocks for all code. Python's popularity is, in large part, due to the +wonderful flexibility of its native types, like ``List`` and ``Dict``. This document will cover how to +update the existing Batavia implementations. + +Process +------- + +The first thing to do when adding anything to Batavia is to play around a bit with it in the Python REPL. +Here's an example using ``int``:: + + >>> int + + >>> int(1) + 1 + >>> dir(int) + ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes'] + +Your goal is to find out how the type responds to various inputs and outputs. You may also +want to consult the offical documentation. Once you're a little familiar, you can start to add your +implementation to Batavia. + +Anatomy of a Type +***************** + +Each Python type should be implemented as a JavaScript class. JavaScript handles classes similarly to Python, +but the syntax is very different. Each JavaScript class creates a constructor (similar to Python's ``__init__``), +which is any function that includes the ``this`` keyword, and a prototype, stored in ``.prototype``. +The prototype implements all of the methods for the class, including the constructor, and that's where we'll implement +the type's magic methods and other options. Let's take a look at ``List``. + +.. code-block:: javascript + + // Declare the list class. + function List() { + var builtins = require('../builtins') + + if (arguments.length === 0) { + this.push.apply(this) + } else if (arguments.length === 1) { + // Fast-path for native Array objects. + if (Array.isArray(arguments[0])) { + this.push.apply(this, arguments[0]) + } else { + var iterobj = builtins.iter([arguments[0]], null) + var self = this + callables.iter_for_each(iterobj, function(val) { + self.push(val) + }) + } + } else { + throw new exceptions.TypeError.$pyclass('list() takes at most 1 argument (' + arguments.length + ' given)') + } + } + + function Array_() {} + + Array_.prototype = [] + + List.prototype = Object.create(Array_.prototype) // Duplicates the prototype to avoid damaging the original + List.prototype.length = 0 + create_pyclass(List, 'list', true) // Register the class with Batavia + List.prototype.constructor = List + +This is the constructor, which is called by Batavia when someone invokes ``list()`` or ``[]``. We includes some code to inherit +JavaScript's native array prototype, which has much of the same functionality as List and has lots of quick functions. +You can use JavaScript natives in your implementation; this is a significant speed boost. + +Below that, you'll find all of the member methods added to the prototype. Note that each of these +should return a Python type from ``types.js``. + +.. code-block:: javascript + + List.prototype.__iter__ = function() { + return new ListIterator(this) + } + + List.prototype.__len__ = function() { + var types = require('../types') + return new types.Int(this.length) + } + +List also implements ``.toString()``, a JavaScript function that is sometimes called automatically when a string +conversion is needed. + +.. code-block:: javascript + + List.prototype.toString = function() { + return this.__str__() + } + +Note also the format for errors: ``throw new exceptions..$pyclass``. + +Making Changes +************** + +Make a Test +^^^^^^^^^^^ + +There is much work to be done in the types folder. When making changes, your goal is to match the output +of CPython and the output of the same call made in Batavia. Since we know the desired input and output, +we can use a test and then just fiddle. + +Head over to ``/tests`` and find the ``test_`` file. Many types have a robust test suite, but +do not assume that it is complete. +Follow the format there to add a test for your issue or modify an existing test. +Run it using the following command to check for errors. + +.. code-block:: bash + $ python setup.py -s tests.path.to.your.test.TestClass.test_function + +Note: ``@expectedFailure`` indicates a test that's not passing yet. Your issue may be tested in one of those cases already. + +Pass the Test +^^^^^^^^^^^^^ + +If the test code runs and fails, you've identified the bug and should have some helpful output comparisons. Head over to +the type you want and start making edits, running your test until it passes. Occasionally, your bug will take you into +other Batavia types and builtins. That's fine too! There are a million places for small omissions all over the codebase. +Just keep in mind that the further you go down the rabbit hole, the more likely you are to have missed something simple. + +Once the test passes, run all tests for the class and see what else broke. (There's always something):: + + $ python setup.py -s tests.path.to.your.test + +After that, it's a good idea to pull the upstream master and check for merge conflicts.:: + + $ git add . + $ git commit -m "" + $ git fetch upstream + $ git rebase origin/master + +If you made major changes, then it may be a good idea to run the full test suite before submitting your pull request.:: + + $ python setup.py -s tests + +(Check out the sidebar for better/faster ways to run the full suite.) Finally, push your code to your fork and submit +your pull request on GitHub to run the CI. Fix any issues and push again until CI passes. The Batavia team will get back +to you with any additional notes and edits. + +Tips +^^^^ + +Your goal is to mimic the CPython implementation as much as possible. If you do so, you'll often fix multiple issues at once. Here's some tips: + +* The original implementation is documented in detail at https://docs.python.org/3/ -- reading up there will definitely improve your understanding. +* If you're inherting your class from JavaScript, which is very common, you get JavaScript's internal methods for free. Oftentimes, they can be left as is or lightly wrapped. +* Make sure your test properly covers the issue. For instance, if a member function accepts any iterable, make a generic iterable instead of using a list or tuple. +* Make sure method implementations accept args and kwargs, and throw appropriate errors if the input doesn't match. +* Keep your Python REPL open to the side and test your assumptions with lots of inputs and outputs. From 38a2dcd27e7fba3d6ebd7c2a1c47a3d1bf02653a Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 12:42:20 -0700 Subject: [PATCH 05/29] Flavor edits. --- docs/how-to/builtins.rst | 4 ++-- docs/how-to/types.rst | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index a92775651..b259ec214 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -1,9 +1,9 @@ Implementing Python Built-ins in JavaScript =========================================== -Pythons builtins are the absolute core of the language. If you're new to Python, read up on them here: https://docs.python.org/3/library/functions.html +Pythons builtins give Python its trademark magical feel. If you're new to Python, read up on them here: https://docs.python.org/3/library/functions.html -Most builtins have already been added to the project, but many do not follow the correct spec outlined below. +Most builtins have already been added to the project, but many do not follow the spec outlined below. Some may not handle certain types of inputs correctly. In addition, new builtins may of course arrive with the latest and greatest Python version. This guide should serve as your field manual for adding, updating, and navigating our implementations. diff --git a/docs/how-to/types.rst b/docs/how-to/types.rst index 5b1c82420..b6252c154 100644 --- a/docs/how-to/types.rst +++ b/docs/how-to/types.rst @@ -1,9 +1,8 @@ Implementing Python Types =========================================== -Python native types are the building blocks for all code. Python's popularity is, in large part, due to the -wonderful flexibility of its native types, like ``List`` and ``Dict``. This document will cover how to -update the existing Batavia implementations. +Python's popularity is, in large part, due to the wonderful flexibility of its native types, like ``List`` and ``Dict``. In Batavia, Python native types are the building blocks for all of our other code. +This document will cover the structure of Batavia types and guide you on how to update the existing Batavia implementations. Process ------- From 2d11319128164accd0542b9a505c454f1f9a5429 Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 12:42:55 -0700 Subject: [PATCH 06/29] Flavor edits v2. --- docs/how-to/builtins.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index b259ec214..7e6da950a 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -4,7 +4,7 @@ Implementing Python Built-ins in JavaScript Pythons builtins give Python its trademark magical feel. If you're new to Python, read up on them here: https://docs.python.org/3/library/functions.html Most builtins have already been added to the project, but many do not follow the spec outlined below. -Some may not handle certain types of inputs correctly. In addition, new builtins may of course arrive with the +Some may not handle certain types of inputs correctly. In addition, new builtins may arrive with the latest and greatest Python version. This guide should serve as your field manual for adding, updating, and navigating our implementations. From 253094f2adf4f54e350dd53aa0806321998f727f Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 12:43:42 -0700 Subject: [PATCH 07/29] Grammar. --- docs/how-to/builtins.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 7e6da950a..c039032ab 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -1,7 +1,7 @@ Implementing Python Built-ins in JavaScript =========================================== -Pythons builtins give Python its trademark magical feel. If you're new to Python, read up on them here: https://docs.python.org/3/library/functions.html +Python's builtins give Python its trademark magical feel. If you're new to Python, read up on them here: https://docs.python.org/3/library/functions.html Most builtins have already been added to the project, but many do not follow the spec outlined below. Some may not handle certain types of inputs correctly. In addition, new builtins may arrive with the From f0ec5803806aa17548d82842e4256b12b7c92394 Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 12:46:10 -0700 Subject: [PATCH 08/29] Finish my sentence --- docs/how-to/builtins.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index c039032ab..3789e3dbe 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -50,7 +50,7 @@ JavaScript object. The first thing to do is check that both were passed in. } Next, we need to validate the arguments are correct. We can use JavaScript's ``Object.keys()`` to -get the keys of an object. If the function pass in the , we will check the Python REPL to see +get the keys of an object. If we can't accept certain args or kwargs, we will check the Python REPL to see what kind of error and throw it. .. tabs:: From 25ff0f2f14af55fa9e10b11360f66379e8fb91a4 Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 12:49:25 -0700 Subject: [PATCH 09/29] Explain a bit more. --- docs/how-to/tour.rst | 2 +- docs/how-to/types.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/how-to/tour.rst b/docs/how-to/tour.rst index 1d14be4f0..82421d65d 100644 --- a/docs/how-to/tour.rst +++ b/docs/how-to/tour.rst @@ -23,7 +23,7 @@ should be immediately familiar to a Python developer. Support ******* You'll also notice folders for tests, docs, and a few other bits and bobs, like ``testserver``, which is -a Django project that allows code execution. Contributions to the +a Django project that allows code execution from your browser. Contributions to the tests and documentation are always welcome and are great ways to familiarize yourself with the code and meet the other contributors. diff --git a/docs/how-to/types.rst b/docs/how-to/types.rst index b6252c154..689b79578 100644 --- a/docs/how-to/types.rst +++ b/docs/how-to/types.rst @@ -108,6 +108,7 @@ Follow the format there to add a test for your issue or modify an existing test. Run it using the following command to check for errors. .. code-block:: bash + $ python setup.py -s tests.path.to.your.test.TestClass.test_function Note: ``@expectedFailure`` indicates a test that's not passing yet. Your issue may be tested in one of those cases already. From f73628c8c6457988760c5b3a817dd78b37537477 Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 12:55:27 -0700 Subject: [PATCH 10/29] Added credit section. --- docs/how-to/builtins.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 3789e3dbe..35ed7ad0c 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -130,4 +130,9 @@ tested: * Think of a few weird inputs that could throw off your code (or future code). Test them. * If you are throwing an error (excluding ``BataviaError``) anywhere, write a test that tries to throw it. * If you accounted for an edge case (look for an ``if`` statement), test it. -* Check out the official documentation (https://docs.python.org/3/) for more edge cases. \ No newline at end of file +* Check out the official documentation (https://docs.python.org/3/) for more edge cases. + +Credit +^^^^^^ + +Thanks to Kshitij Sobti for the original document that this guide is based on. Most code examples are from his original. \ No newline at end of file From 708005eed9087217d241d14c0b8c74837262566e Mon Sep 17 00:00:00 2001 From: awildtechno Date: Thu, 13 Jun 2019 13:05:25 -0700 Subject: [PATCH 11/29] Cleanup for contribute-tests --- docs/how-to/contribute-tests.rst | 16 ++++++++-------- docs/how-to/index.rst | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/how-to/contribute-tests.rst b/docs/how-to/contribute-tests.rst index e12013ef5..4f9ea6094 100644 --- a/docs/how-to/contribute-tests.rst +++ b/docs/how-to/contribute-tests.rst @@ -23,8 +23,8 @@ The tests corresponding to Batavia implementations of built-ins are available in ``tests/builtins``. The Batavia test infrastructure includes a system to check the compatibility of JavaScript implementation of Python with the reference CPython implementation. -These all tests derive from ``TranspileTestCase``, which handles running your code in both interpreters -and comparing outputs. For an example look at the ``test_bool.py`` file in ``tests/builtins``. You +These tests all derive from ``TranspileTestCase``, which handles running your code in both interpreters +and comparing outputs. For an example, look at the ``test_bool.py`` file in ``tests/builtins``. You will see two classes with test cases, ``BoolTests`` and ``BuiltinBoolFunctionTests``. Both derive from ``TranspileTestCase``. @@ -68,18 +68,18 @@ which can be very useful for debugging in test cases where a decent amount of co Testing for Errors ------------------ -Since we're compiling Python, we need to ensure that errors for all of the builtins are thrown correctly. -We also want to ensure that we're not accepting the wrong errors in our tests. Simply include a try/except +Since we're testing the compiler, we need to ensure that errors for all of the builtins are thrown correctly. +We also want to ensure that we're not getting the wrong errors in our tests. Simply include a try/except block in your test. .. code-block:: python def test_some_error(self): code = """ - try: - code_that_raises_a_ValueError() - except ValueError as err: - print(err) + try: + code_that_raises_a_ValueError() + except ValueError as err: + print(err) """ self.assertCodeExecution(code) diff --git a/docs/how-to/index.rst b/docs/how-to/index.rst index 9ca93aa21..c9f6cb2ca 100644 --- a/docs/how-to/index.rst +++ b/docs/how-to/index.rst @@ -10,9 +10,9 @@ How-to guides are recipes that take the user through steps in key subjects. They :maxdepth: 1 :glob: - Tour of the Code Contribute to Batavia's code Contribute to Batavia's documentation + Tour of the Code Follow the Goat: Batavia's Test Suite Implementing Python Built-ins in JavaScript Implementing Python Types in JavaScript From 9a076c2c24ea9b605f56bbad9ad42778ae32284b Mon Sep 17 00:00:00 2001 From: awildtechno Date: Sun, 16 Jun 2019 09:06:38 -0700 Subject: [PATCH 12/29] Cleanup/suggested changes in builtins.rst. --- docs/how-to/builtins.rst | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 35ed7ad0c..2fc14c8e1 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -1,12 +1,13 @@ Implementing Python Built-ins in JavaScript =========================================== -Python's builtins give Python its trademark magical feel. If you're new to Python, read up on them here: https://docs.python.org/3/library/functions.html +Python's builtins give Python its trademark magical feel. If you're new to Python, read up on ``_ -Most builtins have already been added to the project, but many do not follow the spec outlined below. -Some may not handle certain types of inputs correctly. In addition, new builtins may arrive with the -latest and greatest Python version. This guide should serve as your field manual for adding, updating, and -navigating our implementations. +Most builtins have already been added to the project, but many are do not quite match the original +implementation exactly. Some may not handle certain types of inputs correctly. In addition, new builtins +may arrive with the latest and greatest Python version. This guide should serve as your field manual for +adding, updating, and navigating our implementations. Process ------- @@ -39,19 +40,21 @@ Each builtin function will receive arguments and keyword arguments and needs to even if the result is throwing an error. Args should be an array, and kwargs should be a JavaScript object. The first thing to do is check that both were passed in. +Let's take a look at an example using the ``list()`` builtin + .. code-block:: javascript - // Example: accepts exactly one argument, and no keyword arguments + // List accepts exactly one argument and no keyword arguments - var = function(args, kwargs) { + var list = function(args, kwargs) { // Always add this code. if (arguments.length !== 2) { throw new builtins.BataviaError.$pyclass("Batavia calling convention not used."); } -Next, we need to validate the arguments are correct. We can use JavaScript's ``Object.keys()`` to -get the keys of an object. If we can't accept certain args or kwargs, we will check the Python REPL to see -what kind of error and throw it. +This code ensures that the function can handle keyword arguments. Next, we need to validate the arguments are +correct. We can use JavaScript's ``Object.keys()`` to get the keys of an object. If we can't accept certain +args or kwargs, we will check the Python REPL to see what kind of error should be thrown and throw it. .. tabs:: @@ -130,9 +133,4 @@ tested: * Think of a few weird inputs that could throw off your code (or future code). Test them. * If you are throwing an error (excluding ``BataviaError``) anywhere, write a test that tries to throw it. * If you accounted for an edge case (look for an ``if`` statement), test it. -* Check out the official documentation (https://docs.python.org/3/) for more edge cases. - -Credit -^^^^^^ - -Thanks to Kshitij Sobti for the original document that this guide is based on. Most code examples are from his original. \ No newline at end of file +* Check out the `official documentation `_ for more edge cases. \ No newline at end of file From 8eaa1e8e9d37c4437baa8b7ce227157c15995bbd Mon Sep 17 00:00:00 2001 From: awildtechno Date: Sun, 16 Jun 2019 14:47:20 -0700 Subject: [PATCH 13/29] A bit more cleanup. --- docs/how-to/builtins.rst | 4 ++-- docs/how-to/contribute-tests.rst | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 2fc14c8e1..a517340c6 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -117,9 +117,9 @@ are first-class objects and can have additional properties. .. code-block:: javascript - .__doc__ = 'docstring from Python 3.x goes here, for documentation' + list.__doc__ = 'docstring from Python 3.x goes here, for documentation' - modules.export = + module.exports = list Tests ***** diff --git a/docs/how-to/contribute-tests.rst b/docs/how-to/contribute-tests.rst index 4f9ea6094..df0823bdb 100644 --- a/docs/how-to/contribute-tests.rst +++ b/docs/how-to/contribute-tests.rst @@ -80,11 +80,12 @@ block in your test. code_that_raises_a_ValueError() except ValueError as err: print(err) + print("Test complete!") """ self.assertCodeExecution(code) -Remember to catch the specific error you want, and then print the error. **Code that is not being printed -is not being tested.** +Remember to catch the specific error you want, and then print the error. Then, print a success message to +validate that your except block didn't crash as well. **Code that is not being printed is not being tested.** Output Cleaners --------------- From dc4d547a2416d4d064558a242a9adcbffe1aa9ce Mon Sep 17 00:00:00 2001 From: awildtechno Date: Sun, 16 Jun 2019 15:35:38 -0700 Subject: [PATCH 14/29] Implement suggested changes to tour of the code. --- docs/how-to/tour.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/how-to/tour.rst b/docs/how-to/tour.rst index 82421d65d..a1e455891 100644 --- a/docs/how-to/tour.rst +++ b/docs/how-to/tour.rst @@ -22,8 +22,8 @@ should be immediately familiar to a Python developer. Support ******* -You'll also notice folders for tests, docs, and a few other bits and bobs, like ``testserver``, which is -a Django project that allows code execution from your browser. Contributions to the +You'll also notice folders for tests, docs, and a few other sections, like ``testserver``, which is +a sample deployment via Django that allows code execution in your browser. Contributions to the tests and documentation are always welcome and are great ways to familiarize yourself with the code and meet the other contributors. @@ -65,7 +65,7 @@ builtins.js This contains all of the native Python builtin functions, like ``str``, ``len``, and ``iter``. When dealing with Python types, many of the native JavaScript operations have been modified to -try to use builtins first. For instance, .toString() will often just call the object's __str__ if +try to use builtins first. For instance, ``.toString()`` will often just call the object's ``__str__`` if possible. Still, the best practice is to use the builtins and types wherever possible. types.js @@ -91,10 +91,10 @@ instance. That doesn't make sense! (It may even pass some tests, which is danger core/callables.js ^^^^^^^^^^^^^^^^^ -These methods ensure that all Python code is executed using the proper __call__ procedure, which could be +These methods ensure that all Python code is executed using the proper ``__call__`` procedure, which could be overriden or decorated by the programmer. -* ``callables.call_function`` Invokes a function using its __call__ method if possible. If not, just call it normally. +* ``callables.call_function`` Invokes a function using its ``__call__`` method if possible. If not, just call it normally. * ``callables.call_method`` Calls a class method using the call_function specification above. * ``callables.iter_for_each`` Exhausts an iterable using the call_function specification above. @@ -104,15 +104,15 @@ of ``call_function`` instead of calling Python functions and methods directly. A .. code-block:: javascript // Avoid this - my_thing.__repr__() + my_thing.__len__() // Better var callables = require('./core/callables.js') - callables.call_method(my_thing, '__repr__', [], {}) + callables.call_method(my_thing, '__len__', [], {}) // Best - var repr = require('./builtins.js').repr - repr(my_thing, [], {}) + var len = require('./builtins.js').len + len(my_thing, [], {}) Note the use of the Batavia calling convention in the two cases above! From 1e8e57aae29ddde44ab7d4ee699249945e8f5faf Mon Sep 17 00:00:00 2001 From: awildtechno Date: Sun, 16 Jun 2019 15:45:50 -0700 Subject: [PATCH 15/29] Added a bit about edge cases. --- docs/how-to/contribute-tests.rst | 6 +++++- docs/how-to/index.rst | 2 +- docs/how-to/tour.rst | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/how-to/contribute-tests.rst b/docs/how-to/contribute-tests.rst index df0823bdb..c41c69c42 100644 --- a/docs/how-to/contribute-tests.rst +++ b/docs/how-to/contribute-tests.rst @@ -49,6 +49,10 @@ The ``assertCodeExecution`` method will run the code provided to it in both impl code needs to generate some output so that the output can be compared, hence the need to print the values. **Code that is not being printed is not being tested.** +Finally, ``print()`` is an imperfect creature for tests. Some things in Python aren't guaranteed to +print out in the same order or way, like sets dictionaries. Tests should be structured to compensate, +for instance by converting to a sorted list. See also the output cleaners section below. + Template -------- @@ -113,7 +117,7 @@ Node/Python Crashes If the CPython or JavaScript code crashes outright, UnitTest struggles. For instance, ``confused END_FINALLY`` in the middle of your test output tends to mean that the JavaScript code threw an uncaught exception, causing Node to stop. It's hard for UnitTest to pull the details out of this type of thing -since that error occurred in the virtual machine. +since that error occurred in Node, not Python. These types of errors will often appear above the test case as a crash report instead of in the usual section for the output of your test's print() statements. Look there for clues. \ No newline at end of file diff --git a/docs/how-to/index.rst b/docs/how-to/index.rst index c9f6cb2ca..86f80bd5f 100644 --- a/docs/how-to/index.rst +++ b/docs/how-to/index.rst @@ -13,7 +13,7 @@ How-to guides are recipes that take the user through steps in key subjects. They Contribute to Batavia's code Contribute to Batavia's documentation Tour of the Code - Follow the Goat: Batavia's Test Suite + Batavia's Test Suite Implementing Python Built-ins in JavaScript Implementing Python Types in JavaScript Adding a module and testing it diff --git a/docs/how-to/tour.rst b/docs/how-to/tour.rst index a1e455891..c7cceb39c 100644 --- a/docs/how-to/tour.rst +++ b/docs/how-to/tour.rst @@ -12,7 +12,8 @@ General Structure Core Code ********* -Batavia implements the Python native types, builtins, and standard library partially in JavaScript. +Batavia implements the core language (types, builtins and the core interpreter) are all javascript, as well those +portions of the standard library that depend on system services. This ensures quick execution and less compiling of the compiler. These are orgainzed into the ``builtins``, ``core``, ``modules``, ``stdlib``, and ``types`` files of the main ``/batavia`` directory, with corresponding subdirectories. Alongside the virtual machine and test suite, this code makes @@ -23,7 +24,7 @@ should be immediately familiar to a Python developer. Support ******* You'll also notice folders for tests, docs, and a few other sections, like ``testserver``, which is -a sample deployment via Django that allows code execution in your browser. Contributions to the +a sample deployment with Django that allows you to test code in the browser. Contributions to the tests and documentation are always welcome and are great ways to familiarize yourself with the code and meet the other contributors. From 3a348e461523554c4be46db73b1b6c4ab3ee9d0a Mon Sep 17 00:00:00 2001 From: awildtechno Date: Sun, 16 Jun 2019 15:45:53 -0700 Subject: [PATCH 16/29] Added a bit about edge cases. --- docs/how-to/contribute-tests.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to/contribute-tests.rst b/docs/how-to/contribute-tests.rst index c41c69c42..addb7c8ef 100644 --- a/docs/how-to/contribute-tests.rst +++ b/docs/how-to/contribute-tests.rst @@ -50,7 +50,7 @@ code needs to generate some output so that the output can be compared, hence the values. **Code that is not being printed is not being tested.** Finally, ``print()`` is an imperfect creature for tests. Some things in Python aren't guaranteed to -print out in the same order or way, like sets dictionaries. Tests should be structured to compensate, +print out in the same order every time, like sets dictionaries. Tests should be structured to compensate, for instance by converting to a sorted list. See also the output cleaners section below. Template From 53053fd8017afe5882748c39a9e94bfa40fce1e4 Mon Sep 17 00:00:00 2001 From: awildtechno Date: Sun, 16 Jun 2019 15:48:36 -0700 Subject: [PATCH 17/29] Indentation --- docs/how-to/contribute-tests.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/how-to/contribute-tests.rst b/docs/how-to/contribute-tests.rst index addb7c8ef..fc40ec302 100644 --- a/docs/how-to/contribute-tests.rst +++ b/docs/how-to/contribute-tests.rst @@ -67,7 +67,7 @@ Template self.assertCodeExecution(code) This code block provides a printout of the code being run as well as the output of the code, -which can be very useful for debugging in test cases where a decent amount of code is being run. +which can be very useful for debugging in test cases where more than a few lines of code are being run. Testing for Errors ------------------ @@ -84,7 +84,7 @@ block in your test. code_that_raises_a_ValueError() except ValueError as err: print(err) - print("Test complete!") + print("Test complete!") """ self.assertCodeExecution(code) From 5805e3435e2302ab1212b3b3ef7d59e310e717b3 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 11:25:24 +1000 Subject: [PATCH 18/29] Inline link text by moving the '<' https://github.com/beeware/batavia/pull/819#discussion_r293639408 --- docs/how-to/builtins.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index c45c5201a..ddffd2a98 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -1,8 +1,8 @@ Implementing Python Built-ins in JavaScript =========================================== -Python's builtins give Python its trademark magical feel. If you're new to Python, read up on ``_ +Python's builtins give Python its trademark magical feel. If you're new to Python, read up on `them here. +`_ Most builtins have already been added to the project, but many are do not quite match the original implementation exactly. Some may not handle certain types of inputs correctly. In addition, new builtins From 256eccd2b414be8d4e3960755dc1d14b53b51cf0 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 11:27:06 +1000 Subject: [PATCH 19/29] Typo "official" --- docs/how-to/builtins.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index ddffd2a98..b99981e87 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -25,7 +25,7 @@ Here's an example using ``list()``:: TypeError: 'int' object is not iterable Your goal is to find out how the function responds to various inputs and outputs. You may also -want to consult the offical documentation. Once you're a little familiar, you can start to add your +want to consult the official documentation. Once you're a little familiar, you can start to add your implementation to Batavia. General Structure From 79222152c369a7e3ec29c8c5c501a7a513b79e76 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 11:36:52 +1000 Subject: [PATCH 20/29] Make Python REPL link to https://www.python.org/shell/ I can see the pythonanywhere.com is at 3.7.0, though CPython is considered somewhat more authoritative. If repl.it (at 3.7.4) allows embedding in future, that may become a better candidate for python.org, though many people still prefer the lower latency of a local machine terminal shell-like experience which the shell version suggests (perhaps even encourages with the higher latency to wait for it to load). Anyway I'm sure someone else is aware of far more detail than I can see here. --- docs/how-to/builtins.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index b99981e87..d7a38b2eb 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -12,7 +12,8 @@ adding, updating, and navigating our implementations. Process ------- -The first thing to do when adding anything to Batavia is to play around a bit with it in the Python REPL. +The first thing to do when adding anything to Batavia is to play around a bit with it in a +`Python REPL `_. Here's an example using ``list()``:: >> list() From 541ee700db91a31f3f520cfb3b7dc699d5549e40 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 11:51:28 +1000 Subject: [PATCH 21/29] Add link to the official documentation --- docs/how-to/builtins.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index d7a38b2eb..99e22218d 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -26,8 +26,8 @@ Here's an example using ``list()``:: TypeError: 'int' object is not iterable Your goal is to find out how the function responds to various inputs and outputs. You may also -want to consult the official documentation. Once you're a little familiar, you can start to add your -implementation to Batavia. +want to consult the `official documentation `_. +Once you're a little familiar, you can start to add your implementation to Batavia. General Structure ***************** From b21043477a72a0a27b4757afdfd08e9248263c4e Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 11:59:46 +1000 Subject: [PATCH 22/29] Improve language and linking to the builtins They are the star on which this guide is constructed. --- docs/how-to/builtins.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 99e22218d..9d7317a2b 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -1,11 +1,11 @@ Implementing Python Built-ins in JavaScript =========================================== -Python's builtins give Python its trademark magical feel. If you're new to Python, read up on `them here. -`_ +Python's builtins give Python its trademark magical feel. If you're new to Python, +please read up on the builtins_. Most builtins have already been added to the project, but many are do not quite match the original -implementation exactly. Some may not handle certain types of inputs correctly. In addition, new builtins +implementation exactly. Some may not handle certain types of inputs correctly. In addition, new builtins_ may arrive with the latest and greatest Python version. This guide should serve as your field manual for adding, updating, and navigating our implementations. @@ -25,8 +25,8 @@ Here's an example using ``list()``:: File "", line 1, in TypeError: 'int' object is not iterable -Your goal is to find out how the function responds to various inputs and outputs. You may also -want to consult the `official documentation `_. +Your goal is to find out how the function responds to various inputs and outputs. +You may also want to consult the official documentation of the builtins_. Once you're a little familiar, you can start to add your implementation to Batavia. General Structure @@ -97,7 +97,7 @@ args or kwargs, we will check the Python REPL to see what kind of error should b Returning a value ***************** -Builtins implement Python functions and should return a Python object. +Builtins_ implement Python functions and should return a Python object. Batavia implementations of all Python types are located in ``/batavia/types.js``. JavaScript imports use the ``require`` keyword and can be imported inline or at the top of the file. Inline imports can be preferable in some cases. @@ -135,3 +135,5 @@ tested: * If you are throwing an error (excluding ``BataviaError``) anywhere, write a test that tries to throw it. * If you accounted for an edge case (look for an ``if`` statement), test it. * Check out the `official documentation `_ for more edge cases. + +.. _builtins: https://docs.python.org/3/library/functions.html From f2f82ecc3cc9aac603c17ec2b0424f64201f7b12 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 12:13:10 +1000 Subject: [PATCH 23/29] Add links to ECMA-262 spec and MDN From general experience, a lot of developers and engineers I've worked with acknowledge the ECMA specifications, though actually consult the MDN resource when they just want a quick overview of something as it's often simply easier than explaining the long history of the language, which is the goal here - get someone started off, without too much detail. --- docs/how-to/builtins.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 9d7317a2b..b6667c659 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -32,14 +32,16 @@ Once you're a little familiar, you can start to add your implementation to Batav General Structure ***************** -JavaScript versions of Python built-in functions can be found inside the ``batavia/builtins`` +`JavaScript `_ +versions of Python built-in functions can be found inside the ``batavia/builtins`` directory in the Batavia code. Each built-in is placed inside its own file. These builtins are designed to be used only inside Batavia, as such they need to ensure they are being used in a compatible manner. Each builtin function will receive arguments and keyword arguments and needs to handle them, even if the result is throwing an error. Args should be an array, and kwargs should be a -JavaScript object. The first thing to do is check that both were passed in. +JavaScript `object `_. +The first thing to do is check that both were passed in. Let's take a look at an example using the ``list()`` builtin @@ -53,8 +55,10 @@ Let's take a look at an example using the ``list()`` builtin throw new builtins.BataviaError.$pyclass("Batavia calling convention not used."); } -This code ensures that the function can handle keyword arguments. Next, we need to validate the arguments are -correct. We can use JavaScript's ``Object.keys()`` to get the keys of an object. If we can't accept certain +This code ensures that the function can handle keyword arguments. +Next, we need to validate the arguments are correct. We can use JavaScript's +`Object.keys() `_ +to get the keys of an object. If we can't accept certain args or kwargs, we will check the Python REPL to see what kind of error should be thrown and throw it. .. tabs:: From c5966d365d153adea210ebd9e6199c0568907e11 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 12:18:13 +1000 Subject: [PATCH 24/29] Typo "implementation" --- docs/how-to/builtins.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index b6667c659..0a85e636e 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -129,7 +129,7 @@ are first-class objects and can have additional properties. Tests ***** -No implemenation for a project like this is complete without tests. Check out the other sections for +No implementation for a project like this is complete without tests. Check out the other sections for more details on test structure. Tests are located in ``/tests`` in a similar folder structure to the core code, and most test files have already been created. Some things that should almost always be tested: From a4dd1e7e569d4056c1b45fe5bc175ad4cf92d36e Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 12:21:22 +1000 Subject: [PATCH 25/29] Update Github to GitHub Please forgive my occasional OCD. --- docs/background/community.rst | 2 +- docs/how-to/contribute-code.rst | 2 +- docs/how-to/development-env.rst | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/background/community.rst b/docs/background/community.rst index 5ed985502..c28eac2ac 100644 --- a/docs/background/community.rst +++ b/docs/background/community.rst @@ -36,7 +36,7 @@ want to contribute code, please `fork the code`_ and `submit a pull request`_. .. _announcement: https://groups.google.com/forum/#!topic/beeware-users/iUm-EDgypTg .. _BeeWare Users: https://groups.google.com/forum/#!forum/beeware-users .. _BeeWare Developers: https://groups.google.com/forum/#!forum/beeware-developers -.. _log them on Github: https://github.com/beeware/batavia/issues +.. _log them on GitHub: https://github.com/beeware/batavia/issues .. _fork the code: https://github.com/beeware/batavia .. _submit a pull request: https://github.com/beeware/batavia/pulls diff --git a/docs/how-to/contribute-code.rst b/docs/how-to/contribute-code.rst index 8fb9c6153..9442b2768 100644 --- a/docs/how-to/contribute-code.rst +++ b/docs/how-to/contribute-code.rst @@ -2,7 +2,7 @@ Contributing to Batavia's code ============================== In the following instructions, we're going to assume you’re familiar with -Github and making pull requests. We're also going to assume some entry level +GitHub and making pull requests. We're also going to assume some entry level Python and JavaScript; if anything we describe here doesn’t make sense, don’t worry - we're more than happy to fill in the gaps. At this point, we don’t know what you don’t know! diff --git a/docs/how-to/development-env.rst b/docs/how-to/development-env.rst index c3dd959f8..5475ba722 100644 --- a/docs/how-to/development-env.rst +++ b/docs/how-to/development-env.rst @@ -4,7 +4,7 @@ Setting up your development environment The process of setting up a development environment is very similar to the :doc:`/tutorial/tutorial-0` process. The biggest difference is that instead of using the official BeeWare repository, you'll be using your own -Github fork. +GitHub fork. As with the getting started guide, these instructions will assume that you have Python 3 (currently supported versions are 3.5, 3.6, and 3.7). @@ -12,7 +12,7 @@ have Python 3 (currently supported versions are 3.5, 3.6, and 3.7). Batavia codebase ---------------- -Start by forking Batavia into your own Github repository; then +Start by forking Batavia into your own GitHub repository; then check out your fork to your own computer into a development directory: .. code-block:: bash From 549ffed95a2a5300776f32be0a4d09eba5f83b33 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 12:49:18 +1000 Subject: [PATCH 26/29] Add link to wiki for Python docstrings --- docs/how-to/builtins.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 0a85e636e..3144a78ec 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -117,7 +117,8 @@ the top of the file. Inline imports can be preferable in some cases. Documentation ************* -Finally, add the docstring to the function object. In JavaScript, like in Python, functions +Finally, add the `docstring `_ +to the function object. In JavaScript, like in Python, functions are first-class objects and can have additional properties. .. code-block:: javascript From 05ace7aee1bf45562d41e91d99514bd0f65d3ff0 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 14:16:43 +1000 Subject: [PATCH 27/29] Migrate the builtins example from list() to max() I think list() as a collection type in types/List.js (and a 700+ line implementation) would be better in an advanced guide. --- docs/how-to/builtins.rst | 55 ++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/docs/how-to/builtins.rst b/docs/how-to/builtins.rst index 3144a78ec..98d37df9d 100644 --- a/docs/how-to/builtins.rst +++ b/docs/how-to/builtins.rst @@ -14,13 +14,13 @@ Process The first thing to do when adding anything to Batavia is to play around a bit with it in a `Python REPL `_. -Here's an example using ``list()``:: +Here's an example using ``max()``:: - >> list() - [] - >> list((1, 2, 3, 4)) - [1, 2, 3, 4] - >> list(4) + >> max([1]) + 1 + >> max((1, 2, 3, 4)) + 4 + >> max(4) Traceback (most recent call last): File "", line 1, in TypeError: 'int' object is not iterable @@ -43,13 +43,17 @@ even if the result is throwing an error. Args should be an array, and kwargs sho JavaScript `object `_. The first thing to do is check that both were passed in. -Let's take a look at an example using the ``list()`` builtin +Let's take a look at an example using the ``max()`` builtin. + +Note: ``max()`` already exists in ``batavia/builtins/max.js``, though +if you can make any improvements or find any bugs to fix, they are welcome. .. code-block:: javascript - // List accepts exactly one argument and no keyword arguments + // Max returns the largest item in an iterable or + // the largest of two or more arguments. - var list = function(args, kwargs) { + function max(args, kwargs) { // Always add this code. if (arguments.length !== 2) { throw new builtins.BataviaError.$pyclass("Batavia calling convention not used."); @@ -67,28 +71,35 @@ args or kwargs, we will check the Python REPL to see what kind of error should b .. code-block:: - >> list(a=1) - TypeError: list() doesn't accept keyword arguments. - >> list(1, 2, 3) - TypeError: list() expected exactly 1 argument (3 given) + >> max(a=1) + TypeError: max expected 1 arguments, got 0 + >> max(True) + TypeError: 'bool' object is not iterable + >> max([]) + ValueError: max() arg is an empty sequence .. group-tab:: Batavia Code .. code-block:: javascript - if (kwargs && Object.keys(kwargs).length > 0) { - throw new exceptions.TypeError.$pyclass("() doesn't accept keyword arguments."); + if (!args || args.length === 0) { + throw new exceptions.TypeError.$pyclass('max expected 1 arguments, got ' + args.length) } - if (!args || args.length !== 1) { - throw new exceptions.TypeError.$pyclass("() expected exactly 1 argument (" + args.length + " given)"); + if (args.length > 1) { + ... + } else { + if (!args[0].__iter__) { + throw new exceptions.TypeError.$pyclass("'" + type_name(args[0]) + "' object is not iterable") + } } - // If the function only works with a specific object type, add a test - var obj = args[0]; - if (!types.isinstance(obj, types.)) { - throw new exceptions.TypeError.$pyclass( - "() expects a (" + type_name(obj) + " given)"); + try { + ... + } catch (err) { + if (err instanceof exceptions.StopIteration.$pyclass) { + throw new exceptions.ValueError.$pyclass('max() arg is an empty sequence') + } } Useful functions are ``types.isinstance``, which checks for a match against a Batavia type or list, From b32891ce13d239f9751183da22ab00c960282540 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 14:26:51 +1000 Subject: [PATCH 28/29] Resolve more typos --- docs/how-to/modules-and-tests.rst | 3 ++- docs/how-to/tour.rst | 4 ++-- docs/how-to/types.rst | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/how-to/modules-and-tests.rst b/docs/how-to/modules-and-tests.rst index ddc5b955e..a8f4f1d2b 100644 --- a/docs/how-to/modules-and-tests.rst +++ b/docs/how-to/modules-and-tests.rst @@ -18,7 +18,8 @@ To create a test If the module doesn't exist yet, it must be created as a ``test_NAME-OF-THE-MODULE.py`` file. -If a test for the module already exists and you want to add functionalities to it, you must create a new function on the file. +If a test for the module already exists and you want to add functionality to it, +you must create a new function on the file. To run the tests diff --git a/docs/how-to/tour.rst b/docs/how-to/tour.rst index ca22fe49e..48b1c1e79 100644 --- a/docs/how-to/tour.rst +++ b/docs/how-to/tour.rst @@ -12,9 +12,9 @@ General Structure Core Code ********* -Batavia implements the core language (types, builtins and the core interpreter) are all javascript, as well those +Batavia implements the core language (types, builtins and the core interpreter) are all JavaScript, as well those portions of the standard library that depend on system services. -This ensures quick execution and less compiling of the compiler. These are orgainzed into the +This ensures quick execution and less compiling of the compiler. These are organized into the ``builtins``, ``core``, ``modules``, ``stdlib``, and ``types`` files of the main ``/batavia`` directory, with corresponding subdirectories. Alongside the virtual machine and test suite, this code makes up the bulk of Batavia. New contributors should start with the ``types`` and ``builtins`` sections diff --git a/docs/how-to/types.rst b/docs/how-to/types.rst index 81612137e..94de035f1 100644 --- a/docs/how-to/types.rst +++ b/docs/how-to/types.rst @@ -146,7 +146,7 @@ Tips Your goal is to mimic the CPython implementation as much as possible. If you do so, you'll often fix multiple issues at once. Here's some tips: * The original implementation is documented in detail at https://docs.python.org/3/ -- reading up there will definitely improve your understanding. -* If you're inherting your class from JavaScript, which is very common, you get JavaScript's internal methods for free. Oftentimes, they can be left as is or lightly wrapped. +* If you're inheriting your class from JavaScript, which is very common, you get JavaScript's internal methods for free. Oftentimes, they can be left as is or lightly wrapped. * Make sure your test properly covers the issue. For instance, if a member function accepts any iterable, make a generic iterable instead of using a list or tuple. * Make sure method implementations accept args and kwargs, and throw appropriate errors if the input doesn't match. * Keep your Python REPL open to the side and test your assumptions with lots of inputs and outputs. From 32b05d636d29231159bc59697c2dc99cf6289ec8 Mon Sep 17 00:00:00 2001 From: Peter Schmidt Date: Tue, 6 Aug 2019 14:47:02 +1000 Subject: [PATCH 29/29] Add missing single quote Resolves an error in "make html": /Users/pzrq/Projects/beeware/batavia/docs/how-to/tour.rst:75:Could not lex literal_block as "javascript". Highlighting skipped. --- docs/how-to/tour.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to/tour.rst b/docs/how-to/tour.rst index 48b1c1e79..ddec8ac0d 100644 --- a/docs/how-to/tour.rst +++ b/docs/how-to/tour.rst @@ -74,7 +74,7 @@ types.js .. code-block:: javascript - var types = require('./types.js) + var types = require('./types.js') var my_dict = new types.dict([], {}) This contains all of the native Python types that have been implemented in Batavia. It also has some helper functions: