Skip to content
Merged
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
65 changes: 65 additions & 0 deletions TECHNICAL_REPORTS/1568-quote-python-extras-zsh-20260901.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Technical Report: PR #1568 - Quote Python extras installs under zsh

**Date**: 2026-09-01
**Status**: Completed
**Languages**: Markdown
**Risk Level**: Low

## Executive Summary

PR #1568 fixes a copy-paste failure in the Python client documentation by quoting the `./python[dev]` extras argument everywhere it is shown to users. The change is small, but it removes a shell-specific onboarding break on macOS, where zsh treats unquoted brackets as a glob pattern.

## 1. Problem Statement

The repository documents Python development setup in two places: `python/README.md` and `docs/python-client.md`. Three commands showed `pip install ./python[dev]` or `pip install -e ./python[dev]` without quotes. In zsh, which is the default shell on macOS and therefore the common path for this project's Apple Silicon users, `[dev]` is parsed as a glob character class rather than as part of the package extras syntax.

That makes the documented command fail before `pip` even runs. The problem is not in the package metadata or the Python client implementation; it is purely in the prose examples users are expected to copy verbatim.

## 2. Technical Decisions

### 2.1 Fix the commands by quoting the extras argument, not by rewriting the examples

The change keeps the documented install shape exactly the same and adds only the shell quoting that the command already needs in zsh. This matches the repository's existing CI invocation, which already uses `pip install -e "python[dev]"`, and avoids introducing alternative forms or longer explanatory text for a one-token shell parsing issue.

### 2.2 Update every duplicated example in one PR

The same failure mode appeared in both the user-facing Python client guide and the package-local README, including the editable install form in the test section. Fixing all three lines together prevents one document from remaining stale and reintroducing the same onboarding confusion.

## 3. Change Summary

| Area | Change |
|---|---|
| `python/README.md` | Quotes the development install command in the install section and the editable development install command in the test section. |
| `docs/python-client.md` | Quotes the matching development install command in the Python client guide. |

### Statistics

| Item | Value |
|------|-------|
| Files changed | 2 |
| Lines added | +3 |
| Lines deleted | -3 |
| Tests added | 0 |

### Related Commits

| Hash | Type | Message |
|------|------|---------|
| `5fdc3eb` | docs | docs: quote Python extras installs |

## 4. Validation

Validation was intentionally narrow because this PR changes documentation only.

- `rg -n 'pip install (\./python\[dev\]|-e \./python\[dev\])' python/README.md docs/python-client.md` returns no matches, confirming the unquoted broken forms were removed.
- `rg -n 'pip install ("\./python\[dev\]"|-e "\./python\[dev\]")' python/README.md docs/python-client.md` finds all three intended commands, confirming the docs now present the quoted forms consistently.

## 5. Follow-up Actions

- [ ] When other docs add Python extras examples, keep the extras argument quoted so shell-specific regressions do not reappear.
- [ ] If the install guidance is consolidated later, prefer a single source that the package README and the main docs can share or mirror mechanically.

## 6. Related Work

- Issue #1222: documents the zsh globbing failure and points at the three affected lines.
- PR #1568: applies the fix and closes the issue.
65 changes: 65 additions & 0 deletions TECHNICAL_REPORTS/1568-quote-python-extras-zsh-20260901.ko.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# 기술 보고서: PR #1568 - zsh용 Python extras 설치 명령 인용부호 추가

**작성일**: 2026-09-01
**상태**: 완료
**언어**: Markdown
**위험도**: Low

## 요약

PR #1568은 Python client 문서에 나온 `./python[dev]` extras 인자를 모두 인용부호로 감싸서, 복사-붙여넣기한 명령이 zsh에서도 그대로 동작하게 만든다. 변경 자체는 작지만, macOS 기본 셸인 zsh에서 대괄호를 glob 패턴으로 해석해 온보딩이 바로 깨지던 문제를 없앤다.

## 1. 문제 정의

저장소는 Python 개발용 설치 방법을 `python/README.md`와 `docs/python-client.md` 두 곳에 적고 있다. 이 중 세 개의 명령이 `pip install ./python[dev]` 또는 `pip install -e ./python[dev]`처럼 인용부호 없이 적혀 있었다. zsh에서는 `[dev]`가 package extras 문법의 일부가 아니라 glob 문자 클래스처럼 먼저 해석된다.

그 결과 `pip`가 실행되기 전에 셸 단계에서 명령이 실패한다. 문제는 패키지 메타데이터나 Python client 구현이 아니라, 사용자가 그대로 복사할 것으로 기대되는 문서 예시에만 있다.

## 2. 기술적 선택과 그 이유

### 2.1 예시를 다른 형식으로 바꾸지 않고 extras 인자만 인용한다

문서의 설치 형태는 그대로 두고, zsh에서 꼭 필요한 셸 인용만 추가했다. 이 저장소의 CI가 이미 `pip install -e "python[dev]"` 형태를 쓰고 있으므로, 더 긴 설명이나 다른 명령 형식을 도입하지 않고도 문제를 가장 직접적으로 고칠 수 있다.

### 2.2 중복된 세 예시를 한 PR에서 함께 수정한다

같은 실패 형태가 사용자 문서와 패키지 로컬 README 양쪽에 있었고, 테스트 섹션의 editable install까지 포함되어 있었다. 세 줄을 한 번에 고쳐야 한 문서만 낡은 상태로 남아 같은 혼란을 다시 만들지 않는다.

## 3. 변경 요약

| 영역 | 변경 내용 |
|---|---|
| `python/README.md` | 설치 섹션의 development install 명령과 테스트 섹션의 editable development install 명령에 인용부호를 추가. |
| `docs/python-client.md` | Python client 가이드의 대응하는 development install 명령에 인용부호를 추가. |

### 통계

| 항목 | 값 |
|-----|---|
| 변경된 파일 수 | 2 |
| 추가된 라인 | +3 |
| 삭제된 라인 | -3 |
| 테스트 추가 | 0 |

### 관련 커밋

| Hash | Type | Message |
|------|------|---------|
| `5fdc3eb` | docs | docs: quote Python extras installs |

## 4. 검증

이 PR은 문서만 바꾸므로 검증도 의도적으로 좁게 유지했다.

- `rg -n 'pip install (\./python\[dev\]|-e \./python\[dev\])' python/README.md docs/python-client.md`가 일치 항목을 내지 않아, 깨진 비인용 형식이 모두 제거됐음을 확인했다.
- `rg -n 'pip install ("\./python\[dev\]"|-e "\./python\[dev\]")' python/README.md docs/python-client.md`가 의도한 세 명령을 모두 찾아, 문서가 인용된 형태를 일관되게 보여 줌을 확인했다.

## 5. 후속 조치

- [ ] 앞으로 다른 문서에 Python extras 예시를 추가할 때도 셸별 회귀를 막기 위해 extras 인자를 인용된 형태로 유지한다.
- [ ] 설치 가이드를 나중에 통합한다면, 패키지 README와 메인 문서가 기계적으로 공유하거나 동기화할 수 있는 단일 출처를 고려한다.

## 6. 관련 작업

- Issue #1222: zsh globbing 실패와 영향받는 세 줄을 정리한 이슈.
- PR #1568: 실제 수정 PR이며 이 이슈를 닫는다.
2 changes: 1 addition & 1 deletion docs/python-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This is Phase 1 of Python integration. It builds entirely on the existing HTTP s

```bash
pip install ./python # from a repo checkout
pip install ./python[dev] # adds pytest, ruff, mypy
pip install "./python[dev]" # adds pytest, ruff, mypy
```

Requires Python 3.9 or newer. Runtime dependencies are `openai>=1.40` and `httpx>=0.27`. Managed mode additionally needs the `mlxcel` binary; the client finds it via the `binary=` argument, the `MLXCEL_BIN` environment variable, or `mlxcel` on `PATH`, in that order. See [Installation](installation.md) for building the binary.
Expand Down
10 changes: 5 additions & 5 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This is Phase 1 of Python integration: it builds entirely on the existing HTTP s

```bash
pip install ./python # from a repo checkout
pip install ./python[dev] # with pytest, ruff, mypy for development
pip install "./python[dev]" # with pytest, ruff, mypy for development
```

Requires Python 3.9+. The client itself is pure Python (`openai>=1.40`, `httpx>=0.27`). Managed mode additionally needs the `mlxcel` binary on `PATH`, or pass `binary=` / set `MLXCEL_BIN`.
Expand All @@ -27,8 +27,8 @@ with mlxcel.LLM("mlx-community/Qwen3-4B-4bit") as llm:

print(llm.chat([{"role": "user", "content": "Hello"}], max_tokens=64))

print(llm.model) # resolved model id (auto-discovered)
print(llm.models()) # ["<id>"]
print(llm.model) # resolved model id (auto-discovered)
print(llm.models()) # ["<id>"]
ids = llm.tokenize("hello world")
print(llm.detokenize(ids))

Expand All @@ -38,7 +38,7 @@ with mlxcel.LLM("mlx-community/Qwen3-4B-4bit") as llm:

# Connect mode: talk to an already-running server.
llm = mlxcel.LLM(base_url="http://localhost:8080/v1") # TCP
llm = mlxcel.LLM(socket="/tmp/mlxcel.sock") # Unix socket
llm = mlxcel.LLM(socket="/tmp/mlxcel.sock") # Unix socket
```

Async usage mirrors the sync API via `mlxcel.AsyncLLM` (`await llm.generate(...)`, `async for delta in llm.stream(...)`).
Expand Down Expand Up @@ -66,7 +66,7 @@ HTTP and API errors surface as native `openai` SDK exceptions (for example `open
## Tests

```bash
pip install -e ./python[dev]
pip install -e "./python[dev]"
ruff check python
ruff format --check python
mypy python/src
Expand Down