Skip to content

Commit 6ebd161

Browse files
authored
Merge pull request #215 from david-lev/dev
Deprecate properties, improve error handling, and enhance documentation
2 parents 4e5789a + cfa46ac commit 6ebd161

49 files changed

Lines changed: 2133 additions & 1050 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ repos:
2222

2323

2424
- repo: https://github.com/astral-sh/ruff-pre-commit
25-
rev: v0.14.10
25+
rev: v0.15.20
2626
hooks:
2727
- id: ruff-check
2828
args: [ --fix ]

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,16 @@
33

44
> NOTE: pywa follows the [semver](https://semver.org/) versioning standard.
55
6-
#### 4.2.1 (2026-07-01) **Latest**
6+
#### 4.3.0 (2026-08-07) **Latest**
7+
8+
- [filters] make `Filter` class generic
9+
- [signups] adding support for creating listing and updating signups
10+
- [templates] add documentation and strict typing for `ContactInfoRequestButton`
11+
- [message] deprecate `sender` and `recipient` properties and update user identifier priority
12+
- [cli] move uvicorn import to runtime and improve error handling
13+
- [errors] add more error codes for throttling, sending, and migration, and fix template error code
14+
15+
#### 4.2.1 (2026-07-01)
716

817
- [others] fix parsing contact with field `request contact`
918
- [others] fix parsing contact without name

CONTRIBUTING.md

Lines changed: 141 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
🤝 **Contributing**
22
--------------------
33

4-
Thank you for considering contributing to pywa! We appreciate your time and effort in helping improve this project. This guide will walk you through the steps and standards to follow for contributing.
4+
Thank you for considering contributing to pywa! We appreciate your time and effort in helping improve this project. This
5+
guide will walk you through the steps and standards to follow for contributing.
56

67
## Prerequisites
8+
79
- [Python](https://www.python.org/downloads/) 3.10 or higher
810
- A [GitHub account](https://github.com)
911
- Familiarity with [git](https://git-scm.com/) for version control
@@ -15,7 +17,7 @@ Thank you for considering contributing to pywa! We appreciate your time and effo
1517
```bash
1618
git clone https://github.com/<your-username>/pywa.git
1719
cd pywa
18-
```
20+
```
1921

2022

2123
2. Set up a [virtual environment](https://docs.python.org/3/library/venv.html) and install the required dependencies:
@@ -44,8 +46,14 @@ Now you are ready to start contributing!
4446
## Code Standards
4547

4648
- Follow the [PEP 8](https://pep8.org/) style guide.
47-
- Use [Google Style Python Docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) for docstrings.
49+
- Use [Google Style Python Docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) for
50+
docstrings.
4851
- Include type annotations for all function parameters and return types.
52+
- The project uses [Ruff](https://astral.sh/ruff) for linting and code formatting. You can run checks manually:
53+
```bash
54+
ruff check .
55+
ruff format .
56+
```
4957

5058
## Making Changes
5159

@@ -54,6 +62,7 @@ Now you are ready to start contributing!
5462
```bash
5563
git checkout -b my-new-feature
5664
```
65+
5766
> Use descriptive names like `feature-add-listeners` or `bugfix-handler-issue.`
5867
5968
2. Test your changes:
@@ -64,15 +73,15 @@ Now you are ready to start contributing!
6473

6574
If you're making doc changes, you can build the docs locally:
6675

67-
```bash
68-
make -C docs html
69-
```
76+
```bash
77+
make -C docs html
78+
```
7079

7180
And run a local server to view the changes:
7281

73-
```bash
74-
python3 -m http.server 8000 -d docs/build/html
75-
```
82+
```bash
83+
python3 -m http.server 8000 -d docs/build/html
84+
```
7685

7786
Then launch your browser and navigate to `http://localhost:8000`.
7887

@@ -90,18 +99,63 @@ Now you are ready to start contributing!
9099

91100
## Communication
92101

93-
If you have questions, feel free to reach out via our issue tracker or other communication channels listed in the repository.
102+
If you have questions, need help, or want to discuss changes, feel free to reach out via:
94103

104+
- Our **Telegram Group**: [pywa Chat](https://t.me/pywachat)
105+
- GitHub [Issues](https://github.com/david-lev/pywa/issues) for bug reports and feature requests.
106+
- GitHub [Discussions](https://github.com/david-lev/pywa/discussions) for general questions, ideas, and showcase.
95107

96108
## License
97109

98-
By contributing to pywa, you agree that your contributions will be licensed under the MIT License. See the [LICENSE](https://github.com/david-lev/pywa/blob/master/LICENSE) file for details.
110+
By contributing to pywa, you agree that your contributions will be licensed under the MIT License. See
111+
the [LICENSE](https://github.com/david-lev/pywa/blob/master/LICENSE) file for details.
99112

100113
## Project Structure
101114

115+
This project provides both synchronous (`pywa`) and asynchronous (`pywa_async`) implementations. The asynchronous
116+
implementation structure mirrors the synchronous implementation structure.
117+
118+
### Synchronous Structure (`pywa`)
119+
102120
```bash
103121
pywa/
104122
├── __init__.py
123+
├── __main__.py
124+
├── _helpers.py
125+
├── api.py
126+
├── cli.py
127+
├── client.py
128+
├── errors.py
129+
├── filters.py
130+
├── handlers.py
131+
├── listeners.py
132+
├── server.py
133+
├── types/
134+
│ ├── __init__.py
135+
│ ├── base_update.py
136+
│ ├── account_update.py
137+
│ ├── callback.py
138+
│ ├── calls.py
139+
│ ├── chat.py
140+
│ ├── flows.py
141+
│ ├── groups.py
142+
│ ├── media.py
143+
│ ├── message.py
144+
│ ├── message_status.py
145+
│ ├── others.py
146+
│ ├── sent_update.py
147+
│ ├── system.py
148+
│ ├── templates.py
149+
│ ├── user.py
150+
│ └── user_preferences.py
151+
└── utils.py
152+
```
153+
154+
### Asynchronous Structure (`pywa_async`)
155+
156+
```bash
157+
pywa_async/
158+
├── __init__.py
105159
├── _helpers.py
106160
├── api.py
107161
├── client.py
@@ -110,59 +164,96 @@ pywa/
110164
├── handlers.py
111165
├── listeners.py
112166
├── server.py
113-
├── types
114-
│   ├── __init__.py
115-
│   ├── base_update.py
116-
│   ├── callback.py
117-
│   ├── chat_opened.py
118-
│   ├── flows.py
119-
│   ├── media.py
120-
│   ├── message.py
121-
│   ├── message_status.py
122-
│   ├── others.py
123-
│   ├── sent_message.py
124-
│   └── templates.py
167+
├── types/
168+
│ ├── __init__.py
169+
│ ├── base_update.py
170+
│ ├── account_update.py
171+
│ ├── callback.py
172+
│ ├── calls.py
173+
│ ├── chat.py
174+
│ ├── flows.py
175+
│ ├── groups.py
176+
│ ├── media.py
177+
│ ├── message.py
178+
│ ├── message_status.py
179+
│ ├── others.py
180+
│ ├── sent_update.py
181+
│ ├── system.py
182+
│ ├── templates.py
183+
│ ├── user.py
184+
│ └── user_preferences.py
125185
└── utils.py
126186
```
127187

128-
**Let me explain how the library is structured:**
188+
### Project Components
189+
190+
#### API
191+
192+
The `api.py` file contains all the api calls to the WhatsApp Cloud API. It is responsible for sending requests to the
193+
WhatsApp Cloud API and returning their raw responses.
194+
195+
#### Client
196+
197+
The `WhatsApp` class in the `client.py` file is a wrapper around the api calls. It is responsible for sending requests
198+
to the WhatsApp Cloud API and returning the parsed responses. It allows to send messages, upload media, manage profiles,
199+
flows, templates, and more.
200+
201+
#### Server
202+
203+
The `Server` class in the `server.py` file is responsible for handling, verifying and parsing the incoming updates from
204+
the webhook. It is also responsible for registering the webhook routes and the callback url.
129205

130-
### API
131-
The `api.py` file contains all the api calls to the WhatsApp Cloud API. It responsible for sending requests to the WhatsApp Cloud API and returning their raw responses.
206+
#### Handlers
132207

133-
### Client
134-
The `WhatsApp` class in the `client.py` file is a wrapper around the api calls. It responsible for sending requests to the WhatsApp Cloud API and returning the parsed responses.
135-
It allows to send messages, upload media, manage profiles, flows, templates, and more.
208+
The `handlers.py` file contains the handler decorators and their respective handler objects. The handlers are used to
209+
handle incoming updates from the webhook.
136210

137-
### Server
138-
The `Server` class in the `server.py` file is responsible for handling, verifying and parsing the incoming updates from the webhook.
139-
It also responsible for registering the webhook routes and the callback url.
211+
#### Listeners
140212

141-
### Handlers
142-
The `handlers.py` file contains the handler decorators and their respective handler objects. The handlers are used to handle incoming updates from the webhook.
213+
The `listeners.py` file contains the listener functions and the logic to wait and listen to specific updates.
143214

144-
### Listeners
145-
The `listeners.py` file contains the listener functions and the logic to wait and listen to specific user updates.
215+
#### Filters
146216

147-
### Filters
148217
The `filters.py` file contains the filters to use in the handlers to filter incoming updates.
149218

150-
### Types
151-
The `types` package contains the data classes representing the different types of updates and messages.
219+
#### Types
152220

153-
### Utils
154-
Contains utility functions used across the library and by the users (not like `_helpers.py` which is used internally).
221+
The `types` package contains the data classes representing the different types of updates, messages, templates, flows,
222+
business profiles, calling settings, etc.
223+
224+
#### Utils
225+
226+
Contains utility functions used across the library and by the users (unlike `_helpers.py` which is used internally).
227+
228+
#### Errors
155229

156-
### Errors
157230
Contains the custom exceptions used in the library.
158231

159-
### Async
160-
The async version of pywa preserves the same structure as the sync version.
161-
Most of the code in the async version is inherited from the sync version, while overriding every api-related method to be async.
162-
So when you make changes to the sync version, make sure to apply the same changes to the async version.
232+
#### CLI
233+
234+
The `cli.py` and `__main__.py` files implement the command line interface (run using the `pywa` command) to run the dev
235+
server, send messages etc.
236+
237+
#### Async
238+
239+
The async version of pywa (`pywa_async`) preserves the same structure as the sync version (`pywa`). Most of the code in
240+
the async version is inherited from the sync version, while overriding every api-related method to be async. So when you
241+
make changes to the sync version, make sure to apply the same changes to the async version.
242+
243+
#### Docs
244+
245+
The documentation is written in reStructuredText and is located in the `docs/source/content` directory. The
246+
documentation is built using Sphinx and hosted on ReadTheDocs.
247+
248+
#### Tests
163249

164-
### Docs
165-
The documentation is written in reStructuredText and is located in the `docs/source/content` directory. The documentation is built using Sphinx and hosted on ReadTheDocs.
250+
The tests are located in the `tests` directory and are written using `pytest`.
166251

167-
### Tests
168-
The tests are located in the `tests` directory. The tests are written using `pytest`.
252+
- Run all tests:
253+
```bash
254+
pytest
255+
```
256+
- When adding new features or fixing bugs, please write corresponding tests:
257+
- Add tests for client methods/options in `test_client.py` and `test_async.py`.
258+
- Add tests for new filters in `test_filters.py`.
259+
- Add tests for new types/updates in `test_types.py` or `test_updates.py`.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<a href="https://pywa.readthedocs.io"><img src="https://readthedocs.org/projects/pywa/badge/?version=latest&" alt="Docs"/></a>
2121
<a href="https://github.com/david-lev/pywa/blob/master/LICENSE"><img src="https://img.shields.io/github/license/david-lev/pywa?color=%2334D058" alt="License"/></a>
2222
<a href="https://www.codefactor.io/repository/github/david-lev/pywa/overview/master"><img src="https://www.codefactor.io/repository/github/david-lev/pywa/badge/master" alt="Code Quality"/></a>
23-
<a href="https://t.me/py_wa"><img src="https://badges.aleen42.com/src/telegram.svg" /></a></p>
23+
<a href="https://t.me/py_wa"><img src="https://badges.aleen42.com/src/telegram.svg" alt="Updates"/></a></p>
2424

2525
---
2626

docs/source/content/client/client_reference.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ Client Reference
8383
.. automethod:: WhatsApp.get_current_username
8484
.. automethod:: WhatsApp.get_reserved_usernames
8585
.. automethod:: WhatsApp.delete_username
86-
.. automethod:: WhatsApp.delete_qr_code
86+
.. automethod:: WhatsApp.create_signup
87+
.. automethod:: WhatsApp.get_signup
88+
.. automethod:: WhatsApp.get_signups
89+
.. automethod:: WhatsApp.update_signup
8790
.. automethod:: WhatsApp.get_call_permissions
8891
.. automethod:: WhatsApp.pre_accept_call
8992
.. automethod:: WhatsApp.accept_call

docs/source/content/client/overview.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,23 @@ QR Codes
365365
* - :meth:`~WhatsApp.delete_qr_code`
366366
- Delete a QR code
367367

368+
Signups
369+
--------
370+
.. list-table::
371+
:widths: 40 60
372+
:header-rows: 1
373+
374+
* - Method
375+
- Description
376+
* - :meth:`~WhatsApp.create_signup`
377+
- Create a signup
378+
* - :meth:`~WhatsApp.get_signup`
379+
- Get details of a signup
380+
* - :meth:`~WhatsApp.get_signups`
381+
- List all signups
382+
* - :meth:`~WhatsApp.update_signup`
383+
- Update a signup
384+
368385

369386
Commerce
370387
--------

docs/source/content/errors/overview.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ That’s why it’s **important to always register a handler** for failed messag
6161
@wa.on_message_status(filters.failed)
6262
def handle_failed_message(client: WhatsApp, status: types.MessageStatus):
6363
logging.error("Message failed to send to %s: %s",
64-
status.sender, status.error
64+
status.fron_user, status.error
6565
)
6666
6767
------------------------------

docs/source/content/errors/sending_messages_errors.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,5 @@ Sending Messages Errors
5555
:show-inheritance:
5656
.. autoclass:: MarketingTemplatesDisabledForCloudAPI()
5757
:show-inheritance:
58+
.. autoclass:: PhoneNumberDisplayNameNotApproved()
59+
:show-inheritance:

docs/source/content/examples/demo-bots.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ This is a simple bot that echoes back the user's message.
4747
@wa.on_message
4848
def echo(_: WhatsApp, msg: types.Message):
4949
try:
50-
msg.copy(to=msg.sender, reply_to_message_id=msg.message_id_to_reply)
50+
msg.copy(to=msg.from_user.bsuid, reply_to_message_id=msg.message_id_to_reply)
5151
except ValueError:
5252
msg.reply("I can't echo this message")
5353

0 commit comments

Comments
 (0)