Conversation
Signed-off-by: 5hojib <yesiamshojib@gmail.com>
Signed-off-by: 5hojib <yesiamshojib@gmail.com>
Signed-off-by: 5hojib <yesiamshojib@gmail.com>
Signed-off-by: 5hojib <yesiamshojib@gmail.com>
Updates the requirements on [sphinx](https://github.com/sphinx-doc/sphinx) to permit the latest version. - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/v8.1.3/CHANGES.rst) - [Commits](sphinx-doc/sphinx@v0.1.61611...v8.1.3) --- updated-dependencies: - dependency-name: sphinx dependency-version: 8.1.3 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: 5hojib <yesiamshojib@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit updates top-level dependency constraints in `pyproject.toml` to their latest compatible versions and regenerates all lock files (`uv.lock`, `requirements.lock`, and `requirements-dev.lock`). Key changes: - Updated `pysocks`, `aiosqlite`, `pymediainfo`, `pymongo`, `ElectroCrypto`, and `anyio` minimum versions in `pyproject.toml`. - Bumped `hatch` and `pytest` minimum versions in `dev` extra. - Updated `sphinx` constraint to `<10.0.0` and added minimum versions for other documentation and development tools. - Regenerated `uv.lock` with latest compatible versions. - Re-exported `requirements.lock` and `requirements-dev.lock` with hashes using `uv export`, ensuring consistency across dependency management tools. - Verified all tests pass in the updated environment. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- Updated `compiler/docs/compiler.py` to support categorized Enums. - Enhanced documentation visuals with modern fonts (Inter, JetBrains Mono) and theme features (instant navigation). - Refined `docs/source/_static/css/custom.css` for a modern minimalist UI with backdrop-filter blurs and improved typography. - Improved `docs/source/index.rst` layout for a better first impression. - Fixed typo in enum filename: renamed `listerner_types.py` to `listener_types.py`. - Regenerated all API and documentation files. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- Fixed duplicate and missing decorators in `docs/source/api/decorators.rst`. - Renamed `refund_star_payment` to `refund_stars_payment` and `RefundStarPayment` to `RefundStarsPayment` for consistency with Telegram's terminology, with backward compatibility aliases. - Fixed a cut-off docstring in `pyrogram/types/user_and_chats/chat.py`. - Exported `Str` and `Link` types in `pyrogram.types` to resolve Sphinx import failures. - Removed a trailing transition in `docs/source/support.rst` that caused a docutils warning. - Configured Sphinx to preserve default values and suppress lexing warnings for better documentation output. - Verified that documentation now builds with zero warnings. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Signed-off-by: 5hojib <yesiamshojib@gmail.com>
* perf: optimize TL object serialization with buffer passing This change transitions the serialization process from a recursive "return bytes" pattern to a "write to buffer" pattern. By passing a shared BytesIO buffer through nested write calls, we avoid many redundant memory allocations and byte-copying operations, which significantly improves performance for large and deeply nested TL objects. Key changes: - Added optional `b: BytesIO` parameter to `TLObject.write`. - Optimized Primitives (Int, Long, Bytes, String, Vector, Bool) to support writing directly to a buffer. - Updated the API compiler and templates to generate optimized serialization logic for thousands of raw API classes. - Updated manually implemented core objects (Message, GzipPacked, etc.). - Pre-calculated Boolean byte constants. Co-authored-by: 5hojib <107526130+5hojib@users.noreply.github.com> * perf: refine TL object serialization and fix review issues - Explicitly delegate String.write to Bytes.write. - Use Int.write for Vector constructor ID instead of hardcoded literal. - Ensure BytesIO is imported at runtime in all primitive files. - Add missing write methods to Bool and Double primitives. - Optimize Vector.write to use inner type's write method. - Regenerate raw API with refined templates. Co-authored-by: 5hojib <107526130+5hojib@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Signed-off-by: 5hojib <yesiamshojib@gmail.com>
Signed-off-by: 5hojib <yesiamshojib@gmail.com>
Reviewer's GuideRefactors MTProto API schema handling and error compiler paths, introduces an automated schema update workflow and dev tool, updates dependencies and documentation styling/structure, and renames the business stars refund API while keeping it backward compatible. Updated class diagram for business stars refund APIclassDiagram
class Client
class RefundStarsPayment {
+async refund_stars_payment(self, user_id, telegram_payment_charge_id) bool
+refund_star_payment(self, user_id, telegram_payment_charge_id) bool
}
class TelegramBusiness {
}
class raw_functions_payments_RefundStarsCharge {
}
Client <|.. RefundStarsPayment : used_as_self
TelegramBusiness <|-- RefundStarsPayment
RefundStarsPayment ..> raw_functions_payments_RefundStarsCharge : uses
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Summary of ChangesHello @5hojib, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request focuses on updating the project's core API definitions to align with the latest Telegram schema, enhancing the user documentation for a more modern and organized experience, and streamlining the development workflow through dependency management migration and automation. These changes collectively improve the project's maintainability, clarity, and adherence to current standards. Highlights
Changelog
Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Hey - I've found 3 issues, and left some high level feedback:
- In
compiler/errors/compiler.py, thefiles = [i.name for i in (ERRORS_HOME_PATH / "source").iterdir()]line will now include directories as well as files (unlike the previousis_file()filter), which can break the CSV reading loop; consider restoring ani.is_file()check there. - The new
dev_tools/check_api_schema_updates.pyusesrequests.getwithout a timeout, which can cause the CI job to hang if the upstream endpoint is slow or unresponsive; adding an explicit timeout would make the workflow more robust. - The
compiler/errors/compiler.pyscript no longer overridesHOME/DESTwhen run as__main__, so its behavior differs from the previous relative-path based execution; if you still rely on calling it from different working directories, you may want to document or reintroduce equivalent CLI/path handling.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `compiler/errors/compiler.py`, the `files = [i.name for i in (ERRORS_HOME_PATH / "source").iterdir()]` line will now include directories as well as files (unlike the previous `is_file()` filter), which can break the CSV reading loop; consider restoring an `i.is_file()` check there.
- The new `dev_tools/check_api_schema_updates.py` uses `requests.get` without a timeout, which can cause the CI job to hang if the upstream endpoint is slow or unresponsive; adding an explicit timeout would make the workflow more robust.
- The `compiler/errors/compiler.py` script no longer overrides `HOME`/`DEST` when run as `__main__`, so its behavior differs from the previous relative-path based execution; if you still rely on calling it from different working directories, you may want to document or reintroduce equivalent CLI/path handling.
## Individual Comments
### Comment 1
<location> `dev_tools/check_api_schema_updates.py:92` </location>
<code_context>
+ logger.info("Fetching latest API schema from Telegram repository")
+
+ try:
+ api_response = requests.get(API_SCHEMA_URL)
+ api_response.raise_for_status()
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Add a timeout to the schema download to avoid hanging the script (and the workflow).
Since `requests.get` has no timeout, a slow or stalled GitHub response can hang this script and block the CI job. Please pass an explicit timeout (e.g. `timeout=10`–`30`) so the job fails fast with a clear error instead of hanging indefinitely.
Suggested implementation:
```python
import requests
SCHEMA_REQUEST_TIMEOUT = 20 # seconds
```
```python
api_response = requests.get(API_SCHEMA_URL, timeout=SCHEMA_REQUEST_TIMEOUT)
```
If the surrounding code has specific error handling, you may also want to:
1. Add a dedicated `except requests.exceptions.Timeout` block to log a clearer message (e.g. "Timed out fetching latest API schema").
2. Ensure the script exits with a non-zero status code in the timeout case so CI fails appropriately.
</issue_to_address>
### Comment 2
<location> `docs/source/index.rst:39` </location>
<code_context>
-in the top left corner.
-
-Here below you can, instead, find a list of the most relevant pages for a quick access.
+Contents are organized into sections composed of self-contained topics which can be all accessed from the sidebar.
+Here below you can find a list of the most relevant pages for quick access.
</code_context>
<issue_to_address>
**suggestion (typo):** Consider reordering "can be all accessed" to the more natural "can all be accessed".
Also consider phrasing the full clause as: “which can all be accessed from the sidebar.”
```suggestion
Contents are organized into sections composed of self-contained topics which can all be accessed from the sidebar.
```
</issue_to_address>
### Comment 3
<location> `dev_tools/check_api_schema_updates.py:81` </location>
<code_context>
+ return hashlib.sha256(MAIN_API_PATH.read_bytes()).hexdigest()
+
+
+def get_latest_schema() -> SchemaData | None:
+ """
+ Fetch the latest API schema from Telegram's repository.
</code_context>
<issue_to_address>
**issue (complexity):** Consider refactoring `get_latest_schema` into small helper functions and simplifying the BASIC_TYPES filtering logic to make the flow clearer and easier to maintain.
You can keep all current behavior but reduce complexity by extracting a few small helpers and simplifying the BASIC_TYPES filtering.
### 1. Split `get_latest_schema` into focused helpers
Right now `get_latest_schema` is handling fetching, parsing, filtering, and assembling. Splitting this into small pure helpers makes each step easier to reason about and test.
For example:
```python
def fetch_raw_schema() -> str:
api_response = requests.get(API_SCHEMA_URL)
api_response.raise_for_status()
return api_response.text
def extract_layer(raw: str) -> str:
match = LAYER_RE.search(raw)
return match.group(1) if match else "Unknown"
def split_types_and_functions(raw: str) -> tuple[str, str]:
functions_idx = raw.find("---functions---")
if functions_idx != -1:
types_part = raw[:functions_idx].strip()
functions_part = raw[functions_idx:]
else:
types_part = raw
functions_part = ""
return types_part, functions_part
```
Then the main function becomes mostly orchestration, which is much simpler to read:
```python
def get_latest_schema() -> SchemaData | None:
logger.info("Fetching latest API schema from Telegram repository")
try:
api_content = fetch_raw_schema()
layer_version = extract_layer(api_content)
types_part, functions_part = split_types_and_functions(api_content)
processed_types_content = filter_basic_types(types_part)
schema_content = build_final_content(processed_types_content, functions_part)
schema_hash = hashlib.sha256(schema_content.encode()).hexdigest()
return {
"content": schema_content,
"hash": schema_hash,
"layer": layer_version,
}
except requests.RequestException as e:
logger.error("Error fetching schema: %s", e)
return None
except (ValueError, KeyError) as e:
logger.error("Error processing schema: %s", e)
return None
```
### 2. Simplify BASIC_TYPES filtering
You can precompute the prefixes once and move the intent into a named helper, making the logic clearer and cheaper per line:
```python
BASIC_TYPE_PREFIXES: set[str] = {
bt.split("=")[0].strip() for bt in BASIC_TYPES
}
def is_basic_type_line(line: str) -> bool:
stripped = line.strip()
return any(stripped.startswith(prefix) for prefix in BASIC_TYPE_PREFIXES)
```
Then the loop becomes shorter and self‑describing:
```python
def filter_basic_types(types_part: str) -> str:
processed_types: list[str] = []
for line in types_part.split("\n"):
line_stripped = line.strip()
if not line_stripped:
processed_types.append("")
continue
if not is_basic_type_line(line):
processed_types.append(line)
return "\n".join(processed_types).strip()
```
And the final content builder can be a small helper as well:
```python
def build_final_content(types: str, functions: str) -> str:
if functions:
return f"{SCHEMA_HEADER}\n{types}\n\n{functions}"
return f"{SCHEMA_HEADER}\n{types}"
```
These changes keep all behavior (including whitespace handling and header injection) but make the control flow and responsibilities much clearer with minimal code movement.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| logger.info("Fetching latest API schema from Telegram repository") | ||
|
|
||
| try: | ||
| api_response = requests.get(API_SCHEMA_URL) |
There was a problem hiding this comment.
suggestion (bug_risk): Add a timeout to the schema download to avoid hanging the script (and the workflow).
Since requests.get has no timeout, a slow or stalled GitHub response can hang this script and block the CI job. Please pass an explicit timeout (e.g. timeout=10–30) so the job fails fast with a clear error instead of hanging indefinitely.
Suggested implementation:
import requests
SCHEMA_REQUEST_TIMEOUT = 20 # seconds api_response = requests.get(API_SCHEMA_URL, timeout=SCHEMA_REQUEST_TIMEOUT)If the surrounding code has specific error handling, you may also want to:
- Add a dedicated
except requests.exceptions.Timeoutblock to log a clearer message (e.g. "Timed out fetching latest API schema"). - Ensure the script exits with a non-zero status code in the timeout case so CI fails appropriately.
| in the top left corner. | ||
|
|
||
| Here below you can, instead, find a list of the most relevant pages for a quick access. | ||
| Contents are organized into sections composed of self-contained topics which can be all accessed from the sidebar. |
There was a problem hiding this comment.
suggestion (typo): Consider reordering "can be all accessed" to the more natural "can all be accessed".
Also consider phrasing the full clause as: “which can all be accessed from the sidebar.”
| Contents are organized into sections composed of self-contained topics which can be all accessed from the sidebar. | |
| Contents are organized into sections composed of self-contained topics which can all be accessed from the sidebar. |
| return hashlib.sha256(MAIN_API_PATH.read_bytes()).hexdigest() | ||
|
|
||
|
|
||
| def get_latest_schema() -> SchemaData | None: |
There was a problem hiding this comment.
issue (complexity): Consider refactoring get_latest_schema into small helper functions and simplifying the BASIC_TYPES filtering logic to make the flow clearer and easier to maintain.
You can keep all current behavior but reduce complexity by extracting a few small helpers and simplifying the BASIC_TYPES filtering.
1. Split get_latest_schema into focused helpers
Right now get_latest_schema is handling fetching, parsing, filtering, and assembling. Splitting this into small pure helpers makes each step easier to reason about and test.
For example:
def fetch_raw_schema() -> str:
api_response = requests.get(API_SCHEMA_URL)
api_response.raise_for_status()
return api_response.text
def extract_layer(raw: str) -> str:
match = LAYER_RE.search(raw)
return match.group(1) if match else "Unknown"
def split_types_and_functions(raw: str) -> tuple[str, str]:
functions_idx = raw.find("---functions---")
if functions_idx != -1:
types_part = raw[:functions_idx].strip()
functions_part = raw[functions_idx:]
else:
types_part = raw
functions_part = ""
return types_part, functions_partThen the main function becomes mostly orchestration, which is much simpler to read:
def get_latest_schema() -> SchemaData | None:
logger.info("Fetching latest API schema from Telegram repository")
try:
api_content = fetch_raw_schema()
layer_version = extract_layer(api_content)
types_part, functions_part = split_types_and_functions(api_content)
processed_types_content = filter_basic_types(types_part)
schema_content = build_final_content(processed_types_content, functions_part)
schema_hash = hashlib.sha256(schema_content.encode()).hexdigest()
return {
"content": schema_content,
"hash": schema_hash,
"layer": layer_version,
}
except requests.RequestException as e:
logger.error("Error fetching schema: %s", e)
return None
except (ValueError, KeyError) as e:
logger.error("Error processing schema: %s", e)
return None2. Simplify BASIC_TYPES filtering
You can precompute the prefixes once and move the intent into a named helper, making the logic clearer and cheaper per line:
BASIC_TYPE_PREFIXES: set[str] = {
bt.split("=")[0].strip() for bt in BASIC_TYPES
}
def is_basic_type_line(line: str) -> bool:
stripped = line.strip()
return any(stripped.startswith(prefix) for prefix in BASIC_TYPE_PREFIXES)Then the loop becomes shorter and self‑describing:
def filter_basic_types(types_part: str) -> str:
processed_types: list[str] = []
for line in types_part.split("\n"):
line_stripped = line.strip()
if not line_stripped:
processed_types.append("")
continue
if not is_basic_type_line(line):
processed_types.append(line)
return "\n".join(processed_types).strip()And the final content builder can be a small helper as well:
def build_final_content(types: str, functions: str) -> str:
if functions:
return f"{SCHEMA_HEADER}\n{types}\n\n{functions}"
return f"{SCHEMA_HEADER}\n{types}"These changes keep all behavior (including whitespace handling and header injection) but make the control flow and responsibilities much clearer with minimal code movement.
There was a problem hiding this comment.
Code Review
This pull request introduces a wide range of improvements, including a major update to the MTProto schema, automated tooling for schema updates, significant documentation enhancements in styling, organization, and content, and dependency updates. The code quality is high, with good use of modern Python features and robust error handling in the new tooling. The renaming of APIs for consistency while maintaining backward compatibility is also well-handled. I have found one critical issue in the updated schema that needs to be addressed.
| keyboardButtonSimpleWebView#e15c4370 flags:# style:flags.10?KeyboardButtonStyle text:string url:string = KeyboardButton; | ||
| keyboardButtonRequestPeer#5b0f15f5 flags:# style:flags.10?KeyboardButtonStyle text:string button_id:int peer_type:RequestPeerType max_quantity:int = KeyboardButton; | ||
| inputKeyboardButtonRequestPeer#c9662d05 flags:# name_requested:flags.0?true username_requested:flags.1?true photo_requested:flags.2?true text:string button_id:int peer_type:RequestPeerType max_quantity:int = KeyboardButton; | ||
| inputKeyboardButtonRequestPeer#2b78156 flags:# name_requested:flags.0?true username_requested:flags.1?true photo_requested:flags.2?true style:flags.10?KeyboardButtonStyle text:string button_id:int peer_type:RequestPeerType max_quantity:int = KeyboardButton; |
There was a problem hiding this comment.
The constructor ID #2b78156 for inputKeyboardButtonRequestPeer is only 7 characters long. It should be an 8-character hexadecimal value. It seems to be missing a leading zero and should be #02b78156. This will likely cause parsing failures.
inputKeyboardButtonRequestPeer#02b78156 flags:# name_requested:flags.0?true username_requested:flags.1?true photo_requested:flags.2?true style:flags.10?KeyboardButtonStyle text:string button_id:int peer_type:RequestPeerType max_quantity:int = KeyboardButton;
Summary by Sourcery
Refresh documentation styling and MTProto schema integration, add automated schema update tooling, adjust business payment API naming, and tighten dependencies and CI branches.
New Features:
Bug Fixes:
Enhancements:
Build:
CI:
Deployment:
Documentation:
Chores: