Skip to content

Commit 2ad8ba2

Browse files
authored
Add Python examples to most of the code blocks in bindings/index.mdx (#27077)
1 parent d8ac279 commit 2ad8ba2

1 file changed

Lines changed: 107 additions & 1 deletion

File tree

  • src/content/docs/workers/runtime-apis/bindings

src/content/docs/workers/runtime-apis/bindings/index.mdx

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ description: Worker Bindings that allow for interaction with other Cloudflare Re
88
next: false
99
---
1010

11-
import { DirectoryListing, WranglerConfig } from "~/components";
11+
import { DirectoryListing, TabItem, Tabs, WranglerConfig } from "~/components";
1212

1313
Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform. Bindings provide better performance and less restrictions when accessing resources from Workers than the [REST APIs](/api/) which are intended for non-Workers applications.
1414

@@ -36,16 +36,35 @@ When you declare a binding on your Worker, you grant it a specific capability, s
3636

3737
</WranglerConfig>
3838

39+
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
40+
3941
```js
4042
export default {
4143
async fetch(request, env) {
44+
const url = new URL(request.url);
4245
const key = url.pathname.slice(1);
4346
await env.MY_BUCKET.put(key, request.body);
4447
return new Response(`Put ${key} successfully!`);
4548
},
4649
};
4750
```
4851

52+
</TabItem> <TabItem label="Python" icon="seti:python">
53+
54+
```python
55+
from workers import WorkerEntrypoint, Response
56+
from urllib.parse import urlparse
57+
58+
class Default(WorkerEntrypoint):
59+
async def fetch(self, request):
60+
url = urlparse(request.url)
61+
key = url.path.slice(1)
62+
await self.env.MY_BUCKET.put(key, request.body)
63+
return Response(f"Put {key} successfully!")
64+
```
65+
66+
</TabItem></Tabs>
67+
4968
You can think of a binding as a permission and an API in one piece. With bindings, you never have to add secret keys or tokens to your Worker in order to access resources on your Cloudflare account — the permission is embedded within the API itself. The underlying secret is never exposed to your Worker's code, and therefore can't be accidentally leaked.
5069

5170
## Making changes to bindings
@@ -99,27 +118,47 @@ Bindings are located on the `env` object, which can be accessed in several ways:
99118
* It is as class property on [WorkerEntrypoint](/workers/runtime-apis/bindings/service-bindings/rpc/#bindings-env),
100119
[DurableObject](/durable-objects/), and [Workflow](/workflows/):
101120

121+
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
102122
```js
103123
export class MyDurableObject extends DurableObject {
104124
async sayHello() {
105125
return `Hi, ${this.env.NAME}!`;
106126
}
107127
}
108128
```
129+
</TabItem> <TabItem label="Python" icon="seti:python">
130+
```python
131+
from workers import WorkerEntrypoint, Response
132+
133+
class Default(WorkerEntrypoint):
134+
async def fetch(self, request):
135+
return Response(f"Hi {self.env.NAME}")
136+
```
137+
</TabItem></Tabs>
138+
109139

110140
* It can be imported from `cloudflare:workers`:
111141

142+
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
112143
```js
113144
import { env } from "cloudflare:workers";
114145
console.log(`Hi, ${env.Name}`);
115146
```
147+
</TabItem> <TabItem label="Python" icon="seti:python">
148+
```python
149+
from workers import import_from_javascript
150+
env = import_from_javascript("cloudflare:workers").env
151+
print(f"Hi, {env.NAME}")
152+
```
153+
</TabItem></Tabs>
116154

117155
### Importing `env` as a global
118156

119157
Importing `env` from `cloudflare:workers` is useful when you need to access a binding
120158
such as [secrets](/workers/configuration/secrets/) or [environment variables](/workers/configuration/environment-variables/)
121159
in top-level global scope. For example, to initialize an API client:
122160

161+
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
123162
```js
124163
import { env } from "cloudflare:workers";
125164
import ApiClient from "example-api-client";
@@ -134,6 +173,19 @@ export default {
134173
},
135174
};
136175
```
176+
</TabItem> <TabItem label="Python" icon="seti:python">
177+
```python
178+
from workers import WorkerEntrypoint, env
179+
from example_api_client import ApiClient
180+
181+
api_client = ApiClient(api_key=env.API_KEY)
182+
LOG_LEVEL = getattr(env, "LOG_LEVEL", "info")
183+
184+
class Default(WorkerEntrypoint):
185+
async def fetch(self, request):
186+
# ...
187+
```
188+
</TabItem></Tabs>
137189

138190
Workers do not allow I/O from outside a request context. This means that even
139191
though `env` is accessible from the top-level scope, you will not be able to access
@@ -144,6 +196,7 @@ call `env.NAMESPACE.get` to get a [Durable Object stub](/durable-objects/api/stu
144196
top-level context. However, calling methods on the Durable Object stub, making [calls to a KV store](/kv/api/),
145197
and [calling to other Workers](/workers/runtime-apis/bindings/service-bindings) will not work.
146198

199+
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
147200
```js
148201
import { env } from "cloudflare:workers";
149202

@@ -158,11 +211,26 @@ export default {
158211
},
159212
};
160213
```
214+
</TabItem> <TabItem label="Python" icon="seti:python">
215+
```python
216+
from workers import Response, WorkerEntrypoint, env
217+
218+
# This would fail!
219+
# env.KV.get('my-key')
220+
221+
class Default(WorkerEntrypoint):
222+
async def fetch(self, request):
223+
# This works
224+
mv_val = await env.KV.get("my-key")
225+
return Response(my_val)
226+
```
227+
</TabItem></Tabs>
161228

162229
Additionally, importing `env` from `cloudflare:workers` lets you avoid passing `env`
163230
as an argument through many function calls if you need to access a binding from a deeply-nested
164231
function. This can be helpful in a complex codebase.
165232

233+
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
166234
```js
167235
import { env } from "cloudflare:workers";
168236

@@ -183,6 +251,24 @@ function getName() {
183251
return env.MY_NAME;
184252
}
185253
```
254+
</TabItem> <TabItem label="Python" icon="seti:python">
255+
```python
256+
from workers import Response, WorkerEntrypoint, env
257+
258+
class Default(WorkerEntrypoint):
259+
def fetch(req):
260+
return Response(say_hello())
261+
262+
# env is not an argument to say_hello...
263+
def say_hello():
264+
my_name = get_name()
265+
return f"Hello, {myName}"
266+
267+
# ...nor is it an argument to getName
268+
def get_name():
269+
return env.MY_NAME
270+
```
271+
</TabItem></Tabs>
186272

187273
:::note
188274
While using `env` from `cloudflare:workers` may be simpler to write than passing it
@@ -199,6 +285,7 @@ Imagine a user has defined the [environment variable](/workers/configuration/env
199285
`env.NAME` would print "Alice". Using the `withEnv` function, you can override the value of
200286
"NAME".
201287

288+
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
202289
```js
203290
import { env, withEnv } from "cloudflare:workers";
204291

@@ -220,5 +307,24 @@ export default {
220307
},
221308
};
222309
```
310+
</TabItem> <TabItem label="Python" icon="seti:python">
311+
```python
312+
from workers import Response, WorkerEntrypoint, env, patch_env
313+
314+
def log_name():
315+
print(env.NAME)
316+
317+
class Default(WorkerEntrypoint):
318+
async def fetch(req):
319+
# this will log "Alice"
320+
log_name()
321+
322+
with patch_env(NAME="Bob"):
323+
# this will log "Bob"
324+
log_name()
325+
326+
# ...etc...
327+
```
328+
</TabItem></Tabs>
223329

224330
This can be useful when testing code that relies on an imported `env` object.

0 commit comments

Comments
 (0)