Skip to main content

Add docstrings for everything

ID
933311f
date
2024-08-24 09:24:47+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
1ce232c
message
Add docstrings for everything
changed files
2 files, 126 additions, 4 deletions

Changed files

src/javascript/__init__.py (4687) → src/javascript/__init__.py (5019)

diff --git a/src/javascript/__init__.py b/src/javascript/__init__.py
index 2e64194..36ec47f 100644
--- a/src/javascript/__init__.py
+++ b/src/javascript/__init__.py
@@ -1,3 +1,16 @@
+"""
+This is a collection of Python functions for manipulating JavaScript
+"data files" -- that is, JavaScript files that define a single variable
+with a JSON value.
+
+This is an example of a JavaScript data file:
+
+    const shape = { "sides": 5, "colour": "red" };
+
+Think of this like the JSON module, but for JavaScript files.
+
+"""
+
 import json
 import pathlib
 import re

tests/test_javascript.py (7664) → tests/test_javascript.py (10705)

diff --git a/tests/test_javascript.py b/tests/test_javascript.py
index d33c509..afad739 100644
--- a/tests/test_javascript.py
+++ b/tests/test_javascript.py
@@ -1,3 +1,7 @@
+"""
+Tests for the ``javascript`` module.
+"""
+
 import pathlib
 import typing
 
@@ -8,10 +12,19 @@ from javascript import append_to_js_array, append_to_js_object, read_js, write_j
 
 @pytest.fixture
 def js_path(tmp_path: pathlib.Path) -> pathlib.Path:
+    """
+    Returns a path to a JavaScript file.
+
+    This only returns the path and does not create the file.
+    """
     return tmp_path / "data.js"
 
 
 class TestReadJs:
+    """
+    Tests for the ``read_js()`` function.
+    """
+
     @pytest.mark.parametrize(
         "text",
         [
@@ -23,21 +36,49 @@ class TestReadJs:
         ],
     )
     def test_can_read_file(self, js_path: pathlib.Path, text: str) -> None:
+        """
+        JavaScript "data values" can be read from files, with a certain
+        amount of allowance for:
+
+        *   whitespace
+        *   trailing semicolon or not
+        *   a var/const prefix
+
+        """
         js_path.write_text(text)
 
         assert read_js(js_path, varname="redPentagon") == {"sides": 5, "colour": "red"}
 
-    def test_non_existent_file_is_error(self) -> None:
+    def test_error_if_path_does_not_exist(self) -> None:
+        """
+        Reading a file which doesn't exist throws a FileNotFoundError.
+        """
         with pytest.raises(FileNotFoundError):
             read_js("doesnotexist.js", varname="shape")
 
+    def test_error_if_path_is_directory(self, tmp_path: pathlib.Path) -> None:
+        """
+        Reading a path which is a directory throws an IsADirectoryError.
+        """
+        assert tmp_path.is_dir()
+
+        with pytest.raises(IsADirectoryError):
+            read_js(tmp_path, varname="shape")
+
     def test_non_json_value_is_error(self, js_path: pathlib.Path) -> None:
+        """
+        Reading a file which doesn't contain a JavaScript "data value"
+        throws a ValueError.
+        """
         js_path.write_text("const sum = 1 + 1 + 1;")
 
         with pytest.raises(ValueError):
             read_js(js_path, varname="sum")
 
     def test_incorrect_varname_is_error(self, js_path: pathlib.Path) -> None:
+        """
+        Reading a file with the wrong variable name throws a ValueError.
+        """
         js_path.write_text(
             'const redPentagon = {\n  "sides": 5,\n  "colour": "red"\n};\n'
         )
@@ -49,7 +90,14 @@ class TestReadJs:
 
 
 class TestWriteJs:
+    """
+    Tests for the ``write_js()`` function.
+    """
+
     def test_can_write_file(self, js_path: pathlib.Path) -> None:
+        """
+        Writing to a file stores the correct JavaScript string.
+        """
         red_pentagon = {"sides": 5, "colour": "red"}
 
         write_js(js_path, value=red_pentagon, varname="redPentagon")
@@ -60,12 +108,18 @@ class TestWriteJs:
         )
 
     def test_fails_if_cannot_write_file(self) -> None:
+        """
+        Writing to the root folder throws an IsADirectoryError.
+        """
         red_pentagon = {"sides": 5, "colour": "red"}
 
         with pytest.raises(IsADirectoryError):
             write_js("/", value=red_pentagon, varname="redPentagon")
 
     def test_fails_if_target_is_folder(self, tmp_path: pathlib.Path) -> None:
+        """
+        Writing to a folder throws an IsADirectoryError.
+        """
         assert tmp_path.is_dir()
 
         red_pentagon = {"sides": 5, "colour": "red"}
@@ -74,6 +128,10 @@ class TestWriteJs:
             write_js(tmp_path, value=red_pentagon, varname="redPentagon")
 
     def test_creates_parent_directory(self, tmp_path: pathlib.Path) -> None:
+        """
+        If the parent directory of the output path doesn't exist, it is
+        created before the file is written.
+        """
         js_path = tmp_path / "1/2/3/shape.js"
         red_pentagon = {"sides": 5, "colour": "red"}
 
@@ -87,6 +145,10 @@ class TestWriteJs:
 
 
 class TestAppendToArray:
+    """
+    Tests for the ``append_to_js_array`` function.
+    """
+
     @pytest.mark.parametrize(
         "text",
         [
@@ -98,6 +160,13 @@ class TestAppendToArray:
         ],
     )
     def test_can_append_array_value(self, js_path: pathlib.Path, text: str) -> None:
+        """
+        After you append an item to an array, you can retrieve the
+        updated array.
+
+        This is true regardless of what the trailing whitespace in the
+        original file looks like.
+        """
         js_path.write_text(text)
 
         append_to_js_array(js_path, value="damson")
@@ -109,6 +178,9 @@ class TestAppendToArray:
         ]
 
     def test_can_mix_types(self, js_path: pathlib.Path) -> None:
+        """
+        Arrays can contain a mixture of different types.
+        """
         write_js(js_path, value=["apple", "banana", "coconut"], varname="fruit")
         append_to_js_array(js_path, value=["damson"])
         assert read_js(js_path, varname="fruit") == [
@@ -119,6 +191,10 @@ class TestAppendToArray:
         ]
 
     def test_error_if_file_doesnt_look_like_array(self, js_path: pathlib.Path) -> None:
+        """
+        Appending to a file which doesn't contain a JSON array throws
+        a ValueError.
+        """
         red_pentagon = {"sides": 5, "colour": "red"}
 
         write_js(js_path, value=red_pentagon, varname="redPentagon")
@@ -142,6 +218,10 @@ class TestAppendToArray:
 
 
 class TestAppendToObject:
+    """
+    Tests for the ``append_to_js_object`` function.
+    """
+
     @pytest.mark.parametrize(
         "text",
         [
@@ -152,17 +232,30 @@ class TestAppendToObject:
             'const redPentagon = {\n  "colour": "red",\n  "sides": 5\n}',
         ],
     )
-    def test_can_append_array_value(self, js_path: pathlib.Path, text: str) -> None:
+    def test_append_to_js_object(self, js_path: pathlib.Path, text: str) -> None:
+        """
+        After you add a key/value pair to an object, you can retrieve the
+        updated object.
+
+        This is true regardless of what the trailing whitespace in the
+        original file looks like.
+        """
         js_path.write_text(text)
 
-        append_to_js_object(js_path, key="sideLengths", value=[5, 5, 6, 6, 6])
+        assert read_js(js_path, varname="redPentagon") == {"colour": "red", "sides": 5}
+
+        append_to_js_object(js_path, key="sideLengths", value=[1, 2, 3, 4, 5])
         assert read_js(js_path, varname="redPentagon") == {
             "colour": "red",
             "sides": 5,
-            "sideLengths": [5, 5, 6, 6, 6],
+            "sideLengths": [1, 2, 3, 4, 5],
         }
 
     def test_error_if_file_doesnt_look_like_object(self, js_path: pathlib.Path) -> None:
+        """
+        Appending to a file which doesn't contain a JSON object throws
+        a ValueError.
+        """
         shapes = ["apple", "banana", "cherry"]
 
         write_js(js_path, value=shapes, varname="fruit")
@@ -186,6 +279,14 @@ class TestAppendToObject:
 
 
 class TestRoundTrip:
+    """
+    A "round trip" is a test that we can use one function to store a value,
+    and another function to retrieve it.
+
+    It checks that the functions are consistent with each other, and aren't
+    losing any information along the way.
+    """
+
     @pytest.mark.parametrize(
         "value",
         [
@@ -202,10 +303,18 @@ class TestRoundTrip:
     def test_can_read_and_write_value(
         self, js_path: pathlib.Path, value: typing.Any
     ) -> None:
+        """
+        After you write a value with ``write_js()``, you get the same value
+        back when you call ``read_js()``.
+        """
         write_js(js_path, value=value, varname="myTestVariable")
         assert read_js(js_path, varname="myTestVariable") == value
 
     def test_can_append_to_file(self, js_path: pathlib.Path) -> None:
+        """
+        After you append a value to an array, you can read the entire file
+        and get the updated array.
+        """
         write_js(js_path, value=["apple", "banana", "coconut"], varname="fruit")
         append_to_js_array(js_path, value="damson")
         assert read_js(js_path, varname="fruit") == [