@vercel/python 2.3.4-canary.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { BuildOptions, shouldServe } from '@vercel/build-utils';
2
2
  import { installRequirement, installRequirementsFile } from './install';
3
3
  export declare const version = 3;
4
- export declare function downloadFilesInWorkPath({ entrypoint, workPath, files, meta, }: BuildOptions): Promise<string>;
4
+ export declare function downloadFilesInWorkPath({ entrypoint, workPath, files, meta, }: Pick<BuildOptions, 'entrypoint' | 'workPath' | 'files' | 'meta'>): Promise<string>;
5
5
  export declare const build: ({ workPath, files: originalFiles, entrypoint, meta, config, }: BuildOptions) => Promise<{
6
6
  output: import("@vercel/build-utils").Lambda;
7
7
  }>;
package/dist/index.js CHANGED
@@ -3553,14 +3553,12 @@ async function downloadFilesInWorkPath({ entrypoint, workPath, files, meta = {},
3553
3553
  }
3554
3554
  exports.downloadFilesInWorkPath = downloadFilesInWorkPath;
3555
3555
  const build = async ({ workPath, files: originalFiles, entrypoint, meta = {}, config, }) => {
3556
- var _a, _b;
3557
3556
  let pythonVersion = version_1.getLatestPythonVersion(meta);
3558
3557
  workPath = await downloadFilesInWorkPath({
3559
3558
  workPath,
3560
3559
  files: originalFiles,
3561
3560
  entrypoint,
3562
3561
  meta,
3563
- config,
3564
3562
  });
3565
3563
  try {
3566
3564
  // See: https://stackoverflow.com/a/44728772/376773
@@ -3602,7 +3600,7 @@ const build = async ({ workPath, files: originalFiles, entrypoint, meta = {}, co
3602
3600
  const obj = JSON.parse(json);
3603
3601
  pythonVersion = version_1.getSupportedPythonVersion({
3604
3602
  isDev: meta.isDev,
3605
- pipLockPythonVersion: (_b = (_a = obj === null || obj === void 0 ? void 0 : obj._meta) === null || _a === void 0 ? void 0 : _a.requires) === null || _b === void 0 ? void 0 : _b.python_version,
3603
+ pipLockPythonVersion: obj?._meta?.requires?.python_version,
3606
3604
  });
3607
3605
  }
3608
3606
  catch (err) {
@@ -3655,8 +3653,8 @@ const build = async ({ workPath, files: originalFiles, entrypoint, meta = {}, co
3655
3653
  meta,
3656
3654
  });
3657
3655
  }
3658
- const originalPyPath = __webpack_require__.ab + "vc_init.py";
3659
- const originalHandlerPyContents = await readFile(__webpack_require__.ab + "vc_init.py", 'utf8');
3656
+ const originalPyPath = path_1.join(__dirname, '..', 'vc_init.py');
3657
+ const originalHandlerPyContents = await readFile(originalPyPath, 'utf8');
3660
3658
  build_utils_1.debug('Entrypoint is', entrypoint);
3661
3659
  const moduleName = entrypoint.replace(/\//g, '.').replace(/\.py$/, '');
3662
3660
  // Since `vercel dev` renames source files, we must reference the original
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/python",
3
- "version": "2.3.4-canary.1",
3
+ "version": "3.0.0",
4
4
  "main": "./dist/index.js",
5
5
  "license": "MIT",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -23,10 +23,10 @@
23
23
  "devDependencies": {
24
24
  "@types/execa": "^0.9.0",
25
25
  "@types/jest": "27.4.1",
26
- "@vercel/build-utils": "3.1.1-canary.1",
26
+ "@vercel/build-utils": "4.0.0",
27
27
  "@vercel/ncc": "0.24.0",
28
28
  "execa": "^1.0.0",
29
29
  "typescript": "4.3.4"
30
30
  },
31
- "gitHead": "08b04d0bda5e50b0dbce6f2595207e96271fc11e"
31
+ "gitHead": "de0d2fba0b32588726a2799015eaff4e6bb65ffb"
32
32
  }
package/dist/vc_init.py DELETED
@@ -1,299 +0,0 @@
1
- import sys
2
- import base64
3
- import json
4
- import inspect
5
- from importlib import util
6
- from http.server import BaseHTTPRequestHandler
7
-
8
- # Import relative path https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
9
- __vc_spec = util.spec_from_file_location("__VC_HANDLER_MODULE_NAME", "./__VC_HANDLER_ENTRYPOINT")
10
- __vc_module = util.module_from_spec(__vc_spec)
11
- sys.modules["__VC_HANDLER_MODULE_NAME"] = __vc_module
12
- __vc_spec.loader.exec_module(__vc_module)
13
- __vc_variables = dir(__vc_module)
14
-
15
-
16
- def format_headers(headers, decode=False):
17
- keyToList = {}
18
- for key, value in headers.items():
19
- if decode and 'decode' in dir(key) and 'decode' in dir(value):
20
- key = key.decode()
21
- value = value.decode()
22
- if key not in keyToList:
23
- keyToList[key] = []
24
- keyToList[key].append(value)
25
- return keyToList
26
-
27
-
28
- if 'handler' in __vc_variables or 'Handler' in __vc_variables:
29
- base = __vc_module.handler if ('handler' in __vc_variables) else __vc_module.Handler
30
- if not issubclass(base, BaseHTTPRequestHandler):
31
- print('Handler must inherit from BaseHTTPRequestHandler')
32
- print('See the docs https://vercel.com/docs/runtimes#advanced-usage/advanced-python-usage')
33
- exit(1)
34
-
35
- print('using HTTP Handler')
36
- from http.server import HTTPServer
37
- import http
38
- import _thread
39
-
40
- server = HTTPServer(('', 0), base)
41
- port = server.server_address[1]
42
-
43
- def vc_handler(event, context):
44
- _thread.start_new_thread(server.handle_request, ())
45
-
46
- payload = json.loads(event['body'])
47
- path = payload['path']
48
- headers = payload['headers']
49
- method = payload['method']
50
- encoding = payload.get('encoding')
51
- body = payload.get('body')
52
-
53
- if (
54
- (body is not None and len(body) > 0) and
55
- (encoding is not None and encoding == 'base64')
56
- ):
57
- body = base64.b64decode(body)
58
-
59
- request_body = body.encode('utf-8') if isinstance(body, str) else body
60
- conn = http.client.HTTPConnection('0.0.0.0', port)
61
- conn.request(method, path, headers=headers, body=request_body)
62
- res = conn.getresponse()
63
-
64
- return_dict = {
65
- 'statusCode': res.status,
66
- 'headers': format_headers(res.headers),
67
- }
68
-
69
- data = res.read()
70
-
71
- try:
72
- return_dict['body'] = data.decode('utf-8')
73
- except UnicodeDecodeError:
74
- return_dict['body'] = base64.b64encode(data).decode('utf-8')
75
- return_dict['encoding'] = 'base64'
76
-
77
- return return_dict
78
-
79
- elif 'app' in __vc_variables:
80
- if (
81
- not inspect.iscoroutinefunction(__vc_module.app) and
82
- not inspect.iscoroutinefunction(__vc_module.app.__call__)
83
- ):
84
- print('using Web Server Gateway Interface (WSGI)')
85
- from io import BytesIO
86
- from urllib.parse import urlparse
87
- from werkzeug.datastructures import Headers
88
- from werkzeug.wrappers import Response
89
-
90
- string_types = (str,)
91
-
92
- def to_bytes(x, charset=sys.getdefaultencoding(), errors="strict"):
93
- if x is None:
94
- return None
95
- if isinstance(x, (bytes, bytearray, memoryview)):
96
- return bytes(x)
97
- if isinstance(x, str):
98
- return x.encode(charset, errors)
99
- raise TypeError("Expected bytes")
100
-
101
- def wsgi_encoding_dance(s, charset="utf-8", errors="replace"):
102
- if isinstance(s, str):
103
- s = s.encode(charset)
104
- return s.decode("latin1", errors)
105
-
106
- def vc_handler(event, context):
107
- payload = json.loads(event['body'])
108
-
109
- headers = Headers(payload.get('headers', {}))
110
-
111
- body = payload.get('body', '')
112
- if body != '':
113
- if payload.get('encoding') == 'base64':
114
- body = base64.b64decode(body)
115
- if isinstance(body, string_types):
116
- body = to_bytes(body, charset='utf-8')
117
-
118
- url = urlparse(payload['path'])
119
- query = url.query
120
- path = url.path
121
-
122
- environ = {
123
- 'CONTENT_LENGTH': str(len(body)),
124
- 'CONTENT_TYPE': headers.get('content-type', ''),
125
- 'PATH_INFO': path,
126
- 'QUERY_STRING': query,
127
- 'REMOTE_ADDR': headers.get(
128
- 'x-forwarded-for', headers.get(
129
- 'x-real-ip', payload.get(
130
- 'true-client-ip', ''))),
131
- 'REQUEST_METHOD': payload['method'],
132
- 'SERVER_NAME': headers.get('host', 'lambda'),
133
- 'SERVER_PORT': headers.get('x-forwarded-port', '80'),
134
- 'SERVER_PROTOCOL': 'HTTP/1.1',
135
- 'event': event,
136
- 'context': context,
137
- 'wsgi.errors': sys.stderr,
138
- 'wsgi.input': BytesIO(body),
139
- 'wsgi.multiprocess': False,
140
- 'wsgi.multithread': False,
141
- 'wsgi.run_once': False,
142
- 'wsgi.url_scheme': headers.get('x-forwarded-proto', 'http'),
143
- 'wsgi.version': (1, 0),
144
- }
145
-
146
- for key, value in environ.items():
147
- if isinstance(value, string_types):
148
- environ[key] = wsgi_encoding_dance(value)
149
-
150
- for key, value in headers.items():
151
- key = 'HTTP_' + key.upper().replace('-', '_')
152
- if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
153
- environ[key] = value
154
-
155
- response = Response.from_app(__vc_module.app, environ)
156
-
157
- return_dict = {
158
- 'statusCode': response.status_code,
159
- 'headers': format_headers(response.headers)
160
- }
161
-
162
- if response.data:
163
- return_dict['body'] = base64.b64encode(response.data).decode('utf-8')
164
- return_dict['encoding'] = 'base64'
165
-
166
- return return_dict
167
- else:
168
- print('using Asynchronous Server Gateway Interface (ASGI)')
169
- # Originally authored by Jordan Eremieff and included under MIT license:
170
- # https://github.com/erm/mangum/blob/b4d21c8f5e304a3e17b88bc9fa345106acc50ad7/mangum/__init__.py
171
- # https://github.com/erm/mangum/blob/b4d21c8f5e304a3e17b88bc9fa345106acc50ad7/LICENSE
172
- import asyncio
173
- import enum
174
- from urllib.parse import urlparse
175
- from werkzeug.datastructures import Headers
176
-
177
-
178
- class ASGICycleState(enum.Enum):
179
- REQUEST = enum.auto()
180
- RESPONSE = enum.auto()
181
-
182
-
183
- class ASGICycle:
184
- def __init__(self, scope):
185
- self.scope = scope
186
- self.body = b''
187
- self.state = ASGICycleState.REQUEST
188
- self.app_queue = None
189
- self.response = {}
190
-
191
- def __call__(self, app, body):
192
- """
193
- Receives the application and any body included in the request, then builds the
194
- ASGI instance using the connection scope.
195
- Runs until the response is completely read from the application.
196
- """
197
- loop = asyncio.new_event_loop()
198
- self.app_queue = asyncio.Queue(loop=loop)
199
- self.put_message({'type': 'http.request', 'body': body, 'more_body': False})
200
-
201
- asgi_instance = app(self.scope, self.receive, self.send)
202
-
203
- asgi_task = loop.create_task(asgi_instance)
204
- loop.run_until_complete(asgi_task)
205
- return self.response
206
-
207
- def put_message(self, message):
208
- self.app_queue.put_nowait(message)
209
-
210
- async def receive(self):
211
- """
212
- Awaited by the application to receive messages in the queue.
213
- """
214
- message = await self.app_queue.get()
215
- return message
216
-
217
- async def send(self, message):
218
- """
219
- Awaited by the application to send messages to the current cycle instance.
220
- """
221
- message_type = message['type']
222
-
223
- if self.state is ASGICycleState.REQUEST:
224
- if message_type != 'http.response.start':
225
- raise RuntimeError(
226
- f"Expected 'http.response.start', received: {message_type}"
227
- )
228
-
229
- status_code = message['status']
230
- headers = Headers(message.get('headers', []))
231
-
232
- self.on_request(headers, status_code)
233
- self.state = ASGICycleState.RESPONSE
234
-
235
- elif self.state is ASGICycleState.RESPONSE:
236
- if message_type != 'http.response.body':
237
- raise RuntimeError(
238
- f"Expected 'http.response.body', received: {message_type}"
239
- )
240
-
241
- body = message.get('body', b'')
242
- more_body = message.get('more_body', False)
243
-
244
- # The body must be completely read before returning the response.
245
- self.body += body
246
-
247
- if not more_body:
248
- self.on_response()
249
- self.put_message({'type': 'http.disconnect'})
250
-
251
- def on_request(self, headers, status_code):
252
- self.response['statusCode'] = status_code
253
- self.response['headers'] = format_headers(headers, decode=True)
254
-
255
- def on_response(self):
256
- if self.body:
257
- self.response['body'] = base64.b64encode(self.body).decode('utf-8')
258
- self.response['encoding'] = 'base64'
259
-
260
- def vc_handler(event, context):
261
- payload = json.loads(event['body'])
262
-
263
- headers = payload.get('headers', {})
264
-
265
- body = payload.get('body', b'')
266
- if payload.get('encoding') == 'base64':
267
- body = base64.b64decode(body)
268
- elif not isinstance(body, bytes):
269
- body = body.encode()
270
-
271
- url = urlparse(payload['path'])
272
- query = url.query.encode()
273
- path = url.path
274
-
275
- scope = {
276
- 'server': (headers.get('host', 'lambda'), headers.get('x-forwarded-port', 80)),
277
- 'client': (headers.get(
278
- 'x-forwarded-for', headers.get(
279
- 'x-real-ip', payload.get(
280
- 'true-client-ip', ''))), 0),
281
- 'scheme': headers.get('x-forwarded-proto', 'http'),
282
- 'root_path': '',
283
- 'query_string': query,
284
- 'headers': [[k.lower().encode(), v.encode()] for k, v in headers.items()],
285
- 'type': 'http',
286
- 'http_version': '1.1',
287
- 'method': payload['method'],
288
- 'path': path,
289
- 'raw_path': path.encode(),
290
- }
291
-
292
- asgi_cycle = ASGICycle(scope)
293
- response = asgi_cycle(__vc_module.app, body)
294
- return response
295
-
296
- else:
297
- print('Missing variable `handler` or `app` in file "__VC_HANDLER_ENTRYPOINT".')
298
- print('See the docs https://vercel.com/docs/runtimes#advanced-usage/advanced-python-usage')
299
- exit(1)