Features¶
Method naming¶
The generator interprets your URL path structure to produce natural method names. No annotations or configuration needed — names are derived automatically.
Collection endpoints¶
Paths ending with a resource name represent collections. GET requests use the list_ / List prefix:
| Method | Path | Python | Go |
|---|---|---|---|
| GET | /api/v1/charges |
list_charges() |
ListCharges() |
| POST | /api/v1/charges |
create_charge() |
CreateCharge() |
Detail endpoints¶
Paths ending with a path parameter represent a single resource. Names are singularized:
| Method | Path | Python | Go |
|---|---|---|---|
| GET | /api/v1/charges/{id} |
get_charge() |
GetCharge() |
| PUT | /api/v1/charges/{id} |
update_charge() |
UpdateCharge() |
| DELETE | /api/v1/charges/{id} |
delete_charge() |
DeleteCharge() |
Verb detection¶
Paths ending with an action word use that verb as the method prefix. The generator uses NLTK WordNet to detect verbs, so /charges/{id}/cancel becomes cancel_charge() / CancelCharge() instead of the naive create_charge_cancel():
| Method | Path | Python | Go |
|---|---|---|---|
| POST | /api/v1/charges/{id}/cancel |
cancel_charge() |
CancelCharge() |
| POST | /api/v1/charges/{id}/refund |
refund_charge() |
RefundCharge() |
| POST | /api/v1/orders/{id}/approve |
approve_order() |
ApproveOrder() |
Non-API paths¶
Routes without a clear resource structure (e.g., /, /health) fall back to the route name:
| Method | Path | Route name | Python | Go |
|---|---|---|---|---|
| GET | / |
home |
get_home() |
GetHome() |
| GET | /health |
health |
get_health() |
GetHealth() |
Language-specific conventions¶
- Python:
snake_casemethod names,PascalCaseclass names - Go:
PascalCaseexported method names,PascalCasestruct names,camelCaseunexported fields
Schema renaming¶
Server-side schemas are named by domain concept (e.g., ChargeSchema). In the generated client, schemas are renamed by their usage role so consumers can tell what they send from what they receive.
Role suffixes¶
| Role | Suffix | Used for |
|---|---|---|
| Request body | RequestSchema |
Serializing outgoing POST/PUT bodies |
| Response | ResponseSchema |
Deserializing incoming responses |
| Querystring | QuerySchema |
Serializing query parameters |
| Error response | ErrorSchema |
Error response bodies |
Renaming rules¶
- Schemas without a role suffix are renamed based on the endpoint path and usage:
ChargeSchemaonPOST /api/v1/charges(request) →ChargesRequestSchemaChargeSchemaonGET /api/v1/charges/{id}(response) →ChargeResponseSchema
- Schemas that already have a recognized suffix (
RequestSchema,ResponseSchema,QuerySchema,BodySchema,PathSchema,ErrorSchema) are left unchanged. - If the same schema would get conflicting names from different endpoints, the original name is preserved.
Python schemas¶
Renamed schemas become Marshmallow Schema subclasses in schemas.py:
class ChargesRequestSchema(Schema):
amount = fields.Integer(required=True)
currency = fields.String(required=True)
Go structs¶
The same renamed schemas become Go structs in types.go with JSON tags:
Go type mapping:
| Marshmallow field | Go type (required) | Go type (optional) |
|---|---|---|
fields.String |
string |
*string |
fields.Integer |
int |
*int |
fields.Float |
float64 |
*float64 |
fields.Boolean |
bool |
*bool |
fields.DateTime |
time.Time |
*time.Time |
fields.List |
[]interface{} |
[]interface{} |
fields.Dict |
map[string]interface{} |
map[string]interface{} |
API versioning¶
When your endpoints have version prefixes in their paths (e.g., /api/v1/..., /api/v2/...), the generator produces a versioned output structure.
How it works¶
- The generator detects
v<digits>segments in endpoint paths - Endpoints are grouped by version
- Each version gets its own subdirectory (Python) or sub-package (Go)
- A root client aggregates version sub-clients as properties (Python) or exported fields (Go)
Usage¶
Benefits¶
- Schema names can't conflict across versions (each version has its own
schemas.pyortypes.go) - You can evolve your API without breaking the existing generated client
- Auth configuration is shared — set it once on the root client
When no versioned endpoints are detected, the flat output structure is used instead.
Include / exclude filtering¶
Control which endpoints are generated using glob patterns:
# Only include v1 API routes
pclient-build dev.ini --name payments --output ./gen/ \
--include "/api/v1/*"
# Exclude internal and webhook endpoints
pclient-build dev.ini --name payments --output ./gen/ \
--exclude "/api/v1/internal/*" \
--exclude "/api/v1/webhooks/*"
# Combine both — include first, then exclude from the result
pclient-build dev.ini --name payments --output ./gen/ \
--include "/api/*" \
--exclude "*/internal/*"
Patterns are matched against the endpoint's URL path using Python's fnmatch style:
*matches any sequence of characters within a single path segment?matches any single character- Multiple
--includeand--excludeflags can be specified
When --include is used, only matching endpoints are kept. When --exclude is used, matching endpoints are removed. If both are specified, include is applied first, then exclude.
Filtering applies to all generated variants — the same set of endpoints is used for Python and Go output.
Cornice and pycornmarsh support¶
The generator works with both Cornice schema patterns:
Standard Cornice¶
Schemas declared via the schema kwarg on Cornice decorators:
@service.post(schema=ChargeSchema, validators=(colander_body_validator,))
def create_charge(request):
...
pycornmarsh¶
Explicit location-to-schema mapping via pcm_request and per-status-code response schemas via pcm_responses:
@service.post(
pcm_request=dict(body=ChargeBodySchema, querystring=ChargeQuerySchema),
pcm_responses={200: ChargeResponseSchema, 400: ChargeErrorSchema},
)
def create_charge(request):
...
When both patterns are present, pcm_request takes precedence for request schemas, and pcm_responses takes precedence for response schemas. This gives you more explicit control over the generated client's types.
Conditional file generation¶
The generated output adapts to your API:
schemas.py/types.gois only created when endpoints have Marshmallow schemas. Plain Pyramid routes without schema declarations still produce a working client — Python methods return rawresponse.json(), Go methods returnmap[string]interface{}.- Version subdirectories only appear when versioned paths are detected.
- Files that would be empty are skipped entirely (e.g., a version's
schemas.pywhen that version has no schemas).