Skip to content

Commit 4fbb014

Browse files
committed
Add tests, update readme
1 parent 42de2b4 commit 4fbb014

7 files changed

+92
-10
lines changed

README.md

+43-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@ Get it via pip:
3333
pip install python-jsx
3434
```
3535

36-
## Minimal example
36+
## Minimal example (using the `coding` directive)
37+
38+
> [!TIP]
39+
> There are more examples available in the [examples folder](examples).
40+
41+
There are two supported ways to seamlessly integrate JSX into your codebase.
42+
One is by registering a custom codec shown here and the other by using a custom import hook shown [below](#minimal-example-using-an-import-hook).
3743

3844
```python
3945
# hello.py
@@ -58,9 +64,6 @@ $ python main.py
5864
<h1>Hello, word!</h1>
5965
```
6066

61-
> [!TIP]
62-
> There are more examples available in the [examples folder](examples).
63-
6467
Each file containing JSX must contain two things:
6568

6669
- `# coding: jsx` directive - This tells Python to let our library parse the
@@ -72,6 +75,42 @@ To run a file containing JSX, the `jsx` codec must be registered first which can
7275
be done with `from pyjsx import auto_setup`. This must occur before importing
7376
any other file containing JSX.
7477

78+
## Minimal example (using an import hook)
79+
80+
> [!TIP]
81+
> There are more examples available in the [examples folder](examples).
82+
83+
```python
84+
# hello.px
85+
from pyjsx import jsx
86+
87+
def hello():
88+
print(<h1>Hello, world!</h1>)
89+
```
90+
91+
```python
92+
# main.py
93+
from pyjsx import auto_setup
94+
95+
from hello import hello
96+
97+
hello()
98+
```
99+
100+
```sh
101+
$ python main.py
102+
<h1>Hello, word!</h1>
103+
```
104+
105+
Each file containing JSX must contain two things:
106+
107+
- The file extension must be `.px`
108+
- `from pyjsx import jsx` import. PyJSX transpiles JSX into `jsx(...)` calls so
109+
it must be in scope.
110+
111+
To be able to import `.px`, the import hook must be registered first which can
112+
be done with `from pyjsx import auto_setup` (same as for the codec version). This must occur before importing any other file containing JSX.
113+
75114
## Supported grammar
76115

77116
The full [JSX grammar](https://facebook.github.io/jsx/) is supported.

pyjsx/import_hook.py

+6
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,10 @@ def _spec_from_path(self, fullname: str, path: str) -> ModuleSpec | None:
6161

6262

6363
def register_import_hook() -> None:
64+
"""Register import hook for .px files."""
6465
sys.meta_path.append(PyJSXFinder())
66+
67+
68+
def unregister_import_hook() -> None:
69+
"""Unregister import hook for .px files."""
70+
sys.meta_path = [finder for finder in sys.meta_path if not isinstance(finder, PyJSXFinder)]
File renamed without changes.

tests/test_examples.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,18 @@ def run_example(name: str):
1313

1414

1515
@pytest.mark.parametrize(
16-
"example",
16+
("example", "loader"),
1717
[
18-
"table",
19-
"props",
20-
"custom",
18+
("table", "codec"),
19+
("table", "import_hook"),
20+
("props", "codec"),
21+
("props", "import_hook"),
22+
("custom_components", "codec"),
23+
("custom_components", "import_hook"),
2124
],
2225
)
23-
def test_example(request, snapshot, example):
26+
def test_example(snapshot, example, loader):
2427
snapshot.snapshot_dir = Path(__file__).parent / "data"
2528
snapshot.assert_match(
26-
run_example(example), f"examples-{request.node.callspec.id}.txt"
29+
run_example(f"{example}_{loader}"), f"examples-{example}.txt"
2730
)

tests/test_import_hook.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from pathlib import Path
2+
3+
import pytest
4+
5+
from pyjsx.import_hook import PyJSXFinder, register_import_hook, unregister_import_hook
6+
7+
8+
@pytest.fixture
9+
def import_hook():
10+
register_import_hook()
11+
yield
12+
unregister_import_hook()
13+
14+
15+
def test_finder():
16+
finder = PyJSXFinder()
17+
path = str(Path(__file__).parent / "test_module")
18+
spec = finder.find_spec("main", [path])
19+
assert spec is not None
20+
assert spec.name == "main"
21+
22+
23+
@pytest.mark.usefixtures("import_hook")
24+
def test_import():
25+
from .test_module import main
26+
27+
assert str(main.hello()) == """\
28+
<h1>
29+
Hello, World!
30+
</h1>"""

tests/test_module/__init__.py

Whitespace-only changes.

tests/test_module/main.px

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from pyjsx import jsx
2+
3+
def hello():
4+
return <h1>Hello, World!</h1>

0 commit comments

Comments
 (0)