Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs+feat: improve contributing guide and add clean_examples utility #4520

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
fail_fast: true

repos:

- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.8.2
hooks:
Expand All @@ -11,26 +10,26 @@ repos:
args: ["--fix", "--exit-non-zero-on-fix"]
exclude: '^integration/benchmarks/'

# Run pyi check before pyright because pyright can fail if pyi files are wrong.
- repo: local
hooks:
- id: update-pyi-files
name: update-pyi-files
always_run: true
language: system
entry: poetry run python scripts/make_pyi.py
description: 'Update pyi files as needed'
entry: python3 scripts/make_pyi.py

- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.313
- repo: local
hooks:
- id: pyright
args: [reflex, tests]
name: pyright
entry: poetry run pyright
language: system
types: [python]
args: [reflex, tests]

- repo: https://github.com/terrencepreilly/darglint
rev: v1.8.1
hooks:
- id: darglint
exclude: '^reflex/reflex.py'

86 changes: 63 additions & 23 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,32 @@ cd reflex
poetry install
```

**4. Now create an examples folder so you can test the local Python build in this repository.**
**4. Create an examples directory within the repository:**

- We have the `examples` folder in the `.gitignore`, so your changes in `reflex/examples` won't be reflected in your commit.
The examples directory is used for testing your local changes. It's included in `.gitignore` so your test apps won't be committed.

``` bash
mkdir examples
cd examples
```

**5. Init and Run**
**5. Init and Run:**

Initialize a new Reflex app and run it in development mode:

``` bash
poetry run reflex init
poetry run reflex run
poetry run reflex init # Select option 0 for blank template
poetry run reflex run # Add --frontend-only for faster frontend-only development
```

All the changes you make to the repository will be reflected in your running app.
The development server will start and your app will be available at http://localhost:3000. The server will automatically reload when you make changes to your code.

**Note:** In development mode, the server may occasionally need to be restarted when making significant changes. You can use Ctrl+C to stop the server and run it again.

- We have the examples folder in the .gitignore, so your changes in reflex/examples won't be reflected in your commit.
To clean up your examples directory and start fresh, you can use the provided cleanup script:
```bash
poetry run python scripts/clean_examples.py
```

## 🧪 Testing and QA

Expand All @@ -63,47 +70,80 @@ Within the 'test' directory of Reflex you can add to a test file already there o

Once you solve a current issue or improvement to Reflex, you can make a PR, and we will review the changes.

Before submitting, a pull request, ensure the following steps are taken and test passing.

In your `reflex` directory run make sure all the unit tests are still passing using the following command.
This will fail if code coverage is below 70%.
Before submitting a pull request, ensure the following steps are taken and tests are passing:

1. Run unit tests and coverage checks:
``` bash
poetry run pytest tests/units --cov --no-cov-on-fail --cov-report=
poetry run pytest tests/units --cov --no-cov-on-fail --cov-report=
```
This will fail if code coverage is below 70%.

Next make sure all the following tests pass. This ensures that every new change has proper documentation and type checking.

2. Run code quality checks:
``` bash
poetry run ruff check .
poetry run pyright reflex tests
find reflex tests -name "*.py" -not -path reflex/reflex.py | xargs poetry run darglint
```

Finally, run `ruff` to format your code.

3. Format your code:
``` bash
poetry run ruff format .
```

4. Install and run pre-commit hooks:
Consider installing git pre-commit hooks so Ruff, Pyright, Darglint and `make_pyi` will run automatically before each commit.
Note that pre-commit will only be installed when you use a Python version >= 3.9.

``` bash
pre-commit install
```

That's it you can now submit your PR. Thanks for contributing to Reflex!
You can also run the pre-commit checks manually:
```bash
pre-commit run --all-files
```

## Type Stub Generation

## Editing Templates
When adding new components or modifying existing ones, you need to regenerate the type stub files (.pyi). This ensures proper type checking and IDE support.

To edit the templates in Reflex you can do so in two way.
To generate type stubs:
```bash
poetry run python scripts/make_pyi.py
```

Change to the basic `blank` template can be done in the `reflex/.templates/apps/blank` directory.
After running this command:
1. Check `git status` to see if any .pyi files were modified
2. If changes were made, include them in your commit
3. If no changes were made, your types are up to date

Others templates can be edited in their own repository. For example the `sidebar` template can be found in the [`reflex-sidebar`](https://github.com/reflex-dev/sidebar-template) repository.
## Editing Templates

To edit the templates in Reflex you can do so in two ways:

1. Change to the basic `blank` template can be done in the `reflex/.templates/apps/blank` directory.

2. Other templates can be edited in their own repository. For example the `sidebar` template can be found in the [`reflex-sidebar`](https://github.com/reflex-dev/sidebar-template) repository.


## Troubleshooting

Common issues and their solutions:

1. **Development Server Issues**
- If the development server becomes unresponsive, stop it with Ctrl+C and restart
- For frontend-only changes, use `--frontend-only` flag for faster development
- Clear the examples directory using `scripts/clean_examples.py` if you encounter unexplained issues

2. **Pre-commit Hook Failures**
- Run `pre-commit run --all-files` to identify specific issues
- Ensure you've formatted code with `ruff format .` before committing
- Check that type stubs are up to date with `make_pyi.py`

3. **Type Checking Errors**
- Verify your changes haven't broken type definitions
- Regenerate type stubs if you modified components
- Check the error messages from pyright for specific type issues

## Other Notes

Expand All @@ -112,5 +152,5 @@ For some pull requests when adding new components you will have to generate a py
(Please check in with the team before adding a new component to Reflex we are cautious about adding new components to Reflex's core.)

``` bash
poetry run python scripts/make_pyi.py
```
poetry run python scripts/make_pyi.py
```
25 changes: 25 additions & 0 deletions scripts/clean_examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
"""Script to clean up the examples directory.

This script helps developers maintain a clean development environment by removing
the examples directory and its contents. This is useful when switching between
different example apps or when wanting to start fresh.
"""

import shutil
from pathlib import Path


def clean_examples():
"""Remove the examples directory and its contents."""
examples_dir = Path(__file__).parent.parent / "examples"
if examples_dir.exists():
print(f"Removing examples directory at {examples_dir}")
shutil.rmtree(examples_dir)
print("Examples directory removed successfully.")
else:
print("No examples directory found.")


if __name__ == "__main__":
clean_examples()
Loading