# كتابة سلاسل التوثيق

يتم توليد مرجع واجهة برمجة التطبيقات الخاصة بـ LeRobot مباشرةً من سلاسل التوثيق (docstrings) الموجودة في `src/lerobot/`. سلسلة التوثيق ليست تعليقًا — بل هي التوثيق المنشور لذلك الكائن، والصيغة أدناه هي ما يحلله المُصيِّر (renderer) وفحوصات CI.

هذه الصفحة هي العقد. إذا كنت تضيف أو تعدّل أي شيء عام في `src/lerobot/`، فالتزم بها.

> [!IMPORTANT]
> **الطريقة العامة غير الموثقة هي طريقة غير مرئية.** يتجاهل `[[autodoc]]` بصمت الأعضاء التي لا تحتوي على نص توثيق — دون تحذير أو خطأ، فهي ببساطة لا تظهر على الصفحة المُصيَّرة. التغطية واكتمال مرجع الواجهة البرمجية هما المشكلة ذاتها.

## التنسيق في مثال واحد

عناوين الأقسام الخاصة بـ Google، وتنسيق أنواع Hugging Face. كلاهما معاً، وليس أحدهما دون الآخر.

````python
def send_action(self, action: RobotAction, rate_hz: float = 30.0) -> RobotAction:
    """Command the robot to move to a target joint configuration.

    Values are clipped by the configured maximum relative target before reaching the motors, so the
    returned action may differ from the requested one.

    Args:
        action (`dict[str, float]`):
            Target values keyed by motor name, e.g. `{"shoulder_pan.pos": 0.0}`. Keys must match the
            robot's action features.
        rate_hz (`float`, *optional*, defaults to `30.0`):
            Control loop frequency.

    Returns:
        `dict[str, float]`: The action actually written to the motors after safety clipping.

    Raises:
        DeviceNotConnectedError: If the robot has not been connected.

    Example:
        ```python
        >>> from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
        >>> robot = SO101Follower(SO101FollowerConfig(port="/dev/ttyACM0"))  # doctest: +SKIP
        >>> robot.connect()  # doctest: +SKIP
        >>> robot.send_action({"shoulder_pan.pos": 0.0})  # doctest: +SKIP
        ```
    """
````

تم استبعاد المراجع المتقاطعة من الأمثلة في هذه الصفحة — راجع [المراجع المتقاطعة](#cross-references) لمعرفة صياغتها ولماذا لا يمكن عرضها داخل كتلة الشيفرة.

## القواعد

### الأقسام

`Args:` · `Returns:` · `Raises:` · `Yields:` · `Example:` · `Note:`

بذلك الترتيب. لا تُستخدم عناوين أقسام أخرى. يأتي ملخص من سطر واحد أولاً، ثم وصف حر اختياري، ثم الأقسام.

### سطر `Args:` يُحلَّل آليًا

```
name (`type`, *optional*, defaults to `X`):
    Description, indented on its own line.
```

The `*optional*, defaults to` clause is **checked against the real signature default** by `make check-docstrings`. It is not decorative — if you write a default that has drifted from the code, CI fails. Omit the clause entirely for required parameters:

```python
    Args:
        port (`str`):
            Serial port the arm is connected to, e.g. `/dev/ttyACM0`.
        max_relative_target (`float | dict[str, float]`, *optional*):
            Caps the magnitude of the relative positional target vector. `None` disables clipping.
        use_degrees (`bool`, *optional*, defaults to `True`):
            Keep `True` for backward compatibility with existing policies and datasets.
```

Types go in backticks. Use `*optional*` with no `defaults to` when the default is `None` or is otherwise not worth restating.

### `Returns:` هو النوع أولاً

سطر واحد مُسقط، اكتب النوع أولاً، ثم النقطتين، ثم الوصف:

```python
    Returns:
        `dict[str, float]`: The action actually written to the motors after safety clipping.
```

`Yields:` يأخذ نفس الشكل.

### `**Attributes**:`، وليس `Attributes:`

يقوم doc-builder بتحليل `Attributes:` العاري على أنه **مرادف لـ `Parameters:`**، لذا يتم عرض خصائصك كحجج لمُنشئ الكائن. هذا الأمر صامت وخاطئ. عندما تختلف الخصائص عن معاملات المُنشئ، استخدم الصيغة العريضة مع فاصل `--`:

```python
class Robot(abc.ABC):
    """The base abstract class for all LeRobot-compatible robots.

    **Attributes**:
        - **config_class** (`type[RobotConfig]`) -- The expected configuration class for this robot.
        - **name** (`str`) -- The unique robot name used to identify this robot type.
    """
```

ملاحظة `--`، وليس `:`.

### مرجعيات متقاطعة

استخدم صيغة الأقواس الخاصة بـ doc-builder: مسار محاط بعلامتي تنصيص خلفيتين داخل قوسين مربعين. **أدوار Sphinx (`:pymeth:`، `:pyattr:`) غير مدعومة** وتظهر كنص حرفي في الصفحة.

| تريد                         | اكتب                               |
| ---------------------------- | ----------------------------------- |
| فئة في الحزمة الرئيسية    | &#91;`Robot`&#93;                   |
| الطريقة، اعرض المسار الكامل   | &#91;`Robot.connect`&#93;           |
| طريقة، اعرض الاسم المجرد   | &#91;`~Robot.connect`&#93;          |
| المسار المتداخل                  | &#91;`~robots.Robot.connect`&#93;   |
| كائن في مكتبة HF أخرى | &#91;`~accelerate.Accelerator`&#93; |

يقوم `~` بإزالة المسار من **نص الرابط فقط**؛ لا يزال الرابط يُحل إلى المسار الكامل.

> [!NOTE]
> يحل doc-builder هذه الصياغة في كل مكان داخل الصفحة — بما في ذلك داخل كتل الأكواد المحاطة. ولهذا السبب تستخدم أمثلة توثيق الدوال في هذه الصفحة نصاً عادياً بدلاً من المراجع المتقاطعة: فكتلة الأكواد التي تحتوي على مرجع متقاطع ستعرض الرابط المُحل بدلاً من الصياغة التي تحتاج إلى كتابتها. في توثيق الدوال الخاص بك، استخدم المراجع المتقاطعة بحرية؛ فقيود هذا الأمر تؤثر فقط على التوثيق _حول_ الصياغة.

### تنبيهات

استخدم اقتباسات كتل بأسلوب GitHub:

```markdown
> [!TIP]
> Call this once at startup — it takes about two seconds.

> [!WARNING]
> Torque is disabled on disconnect. The arm will drop if it is holding a load.
```

مكوّن `<Tip>` قديم وفقاً لـ doc-builder؛ لا تضيف مكوّنات جديدة.

### يجب أن تكون الأمثلة محاطة

An example lives inside a fenced `  DOCBUILDER_CODE_7 `python Example:
        ```python
        >>> from lerobot.robots.so_follower import SO101FollowerConfig
        >>> cfg = SO101FollowerConfig(port="/dev/ttyACM0")
        >>> cfg.use_degrees
        True
        ```
````

> [!WARNING]
> An unfenced `>>>` is still collected — doctest finds prompts anywhere in a docstring. What you lose is the
> rendering, so it shows up as a wall of prose on the page. Every example needs the fence.

Every example either executes in CI or carries `# doctest: +SKIP`. Anything that touches hardware, a GPU, or
downloads from the Hub gets `+SKIP`:

````python
    Example:
        ```python
        >>> robot.connect()  # doctest: +SKIP
        >>> policy = ACTPolicy.from_pretrained("lerobot/act_aloha_sim_transfer_cube_human")  # doctest: +SKIP
        ```
````

أضِف ملفات تحتوي على أمثلة قابلة للتنفيذ إلى `utils/documentation_tests.txt`.

ضع أمثلة على ثلاث إلى خمس نقاط دخول حقيقية للوحدة. الأمثلة على الوصولات البسيطة ضجيج.

## ثلاثة أنماط ستواجهها باستمرار

### فئات بيانات الإعداد

تُوثَّق حقول الإعداد تاريخياً بتعليقات `#` فوق كل حقل. **لا يمكن لـ doc-builder رؤية التعليقات المضمنة** — فتُعرض هذه الفئة مع كل الحقول المذكورة دون أي وصف. انقلها إلى كتلة `Args:` في سلسلة توثيق الفئة:

```python
@dataclass
class SOFollowerConfig:
    """Configuration for SO-family follower arms.

    Args:
        port (`str`):
            Serial port the arm is connected to, e.g. `/dev/ttyACM0`.
        max_relative_target (`float | dict[str, float]`, *optional*):
            Caps the magnitude of the relative positional target vector. A scalar applies to all motors;
            a dict maps motor name to a per-motor cap. `None` disables clipping.
        use_degrees (`bool`, *optional*, defaults to `True`):
            Keep `True` for backward compatibility with existing policies and datasets.
    """

    port: str
    max_relative_target: float | dict[str, float] | None = None
    use_degrees: bool = True
```

> [!IMPORTANT]
> **أداة doc-builder لا ترث توثيق الدوال (docstrings) من الفئات الأساسية.** فئات الإعداد المسجلة في LeRobot غالبًا ما تكون واجهات رقيقة تعتمد على الوراثة المتعددة:
>
> ```python
> @RobotConfig.register_subclass("so101_follower")
> @dataclass
> class SOFollowerRobotConfig(RobotConfig, SOFollowerConfig):
>     pass
> ```
>
> ترسم تلك الفئة **كل** الحقول — بما في ذلك الحقول الموروثة — دون أي أوصاف على الإطلاق، بغض النظر عن جودة توثيق الفئات الأساسية. يجب أن يكون كتلة `Args:` موجودة في الفئة الملموسة التي يسميها `[[autodoc]]`، ويجب أن تغطي الحقول الموروثة أيضاً.

### الفئة الأساسية، ثم الفئة الفرعية الملموسة

تحمل الفئة الأساسية المجردة العقد القياسي. توثّق الفئات الفرعية فقط ما ينحرف عن ذلك — دلالات المنفذ، خصوصيات المعايرة، تخطيط المحركات، مفاتيح الميزات المدعومة. لا تنسخ العقد الأساسي إلى كل فئة فرعية.

يتبع كل من `Robot` و`Teleoperator` و`Camera` و`MotorsBusBase` و`ProcessorStep` و`PreTrainedPolicy` هذا الشكل.

### مستويات التخصيص على مستوى الوحدة

تعدّ بعض الأسماء العامة مستعارة (aliases) وليست فئات منفصلة:

```python
SO100FollowerConfig = SOFollowerRobotConfig
SO101FollowerConfig = SOFollowerRobotConfig
```

يحلّ `[[autodoc]]` الاسم المستعار ويعرض اسم الفئة **القياسي**، لذا فإن عنوان `## SO101FollowerConfig` سيظهر `class lerobot.robots.so_follower.SOFollowerRobotConfig` في المتن. وثّق الفئة القياسية مرة واحدة، وأشر إلى الأسماء المستعارة في نص الصفحة بدلاً من منح كل اسم مستعار كتلة autodoc خاصة به.

## ما لا يجب توثيقه

- **أعضاء خاصة.** أي شيء يبدأ بـ `_` لا يُعد جزءًا من واجهة البرمجة العامة.
- **The type annotation restated as prose.** `port (`str`): A string.` adds nothing. Say what it is for.
- **كود مُضمَّن من المصدر الأصلي.** `src/lerobot/policies/molmoact2/molmoact2_hf_model/` مُضمَّن من `transformers` ويحمل بالفعل توثيقات بأسلوب المصدر الأصلي. اتركه كما هو — إعادة تنسيقه ستُحدث تعارضات فقط عند المزامنة التالية. وهو مستثنى من مرجع الواجهة البرمجية ومن فحوصات التوثيقات.

## كيف يتم فرض ذلك

| تحقق                     | ما يلتقطه                                                                                            |
| ------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `make check-docstrings`   | إدخال `Args:` لا يتطابق مع التوقيع؛ قيمة افتراضية موثقة انحرفت عن القيمة الفعلية |
| `make doctest`            | أمثلة لم تعد تعمل                                                                                |
| `make check-doctest-list` | عناصر قديمة أو غير مرتبة في `utils/documentation_tests.txt`                                               |
| `ruff` (قواعد `D`)        | انتهاكات نمط اتفاقية Google                                                                         |
| `interrogate`             | انخفاض تغطية توثيق الدوال عن الحد الأدنى الحالي                                                     |
| doc-builder               | مسار `[[autodoc]]` يشير إلى شيء غير موجود — هذا يُسبب فشل بناء التوثيق              |

شغّلها معًا قبل فتح طلب دمج:

```bash
make check-docstrings && make doctest && pre-commit run --all-files
```

ثم اعرض الصفحة وانظر إليها فعليًا:

```bash
doc-builder build lerobot docs/source/ --build_dir /tmp/doc-build
```

## قائمة التحقق

- [ ] كل عضو عام قمت بتعديله يحتوي على سلسلة توثيق.
- [ ] Every `Args:` entry matches the signature, including the `*optional*, defaults to` clause.
- [ ] `Returns:` يبدأ بالنوع في سطر واحد مُسقط.
- [ ] لا تُستخدم `Attributes:` عارية — استخدم `**Attributes**:` مع فواصل `--`.
- [ ] لا توجد أدوار Sphinx — تستخدم المراجع المتبادلة &#91;`~module.Class.method`&#93;.
- [ ] الأمثلة داخل كتلة ` ```python ` محاطة بعلامات، وتُنفَّذ إما في CI أو تحمل `# doctest: +SKIP`.
- [ ] حقول فئة البيانات Config موجودة في كتلة `Args:` داخل الفئة الملموسة، وليس في تعليقات `#`.
- [ ] تم فحص الصفحة المُصيَّرة بالعين المجردة.

