Skip to content

Commit 564e915

Browse files
Merge pull request #44 from HDE/master
Release v0.1.8
2 parents 4bd9927 + 7fe2d75 commit 564e915

File tree

7 files changed

+241
-137
lines changed

7 files changed

+241
-137
lines changed

README.md

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ $ pip install python-lambda-local
2121
This will install the package with name `python-lambda-local` in the virtualenv.
2222
Now you can use the command `python-lambda-local` to run your AWS Lambda function written in Python on your own machine.
2323

24-
## Usage
24+
## Usage as a shell command
2525

2626
Run `python-lambda-local -h` to see the help.
2727

2828
```
2929
usage: python-lambda-local [-h] [-l LIBRARY_PATH] [-f HANDLER_FUNCTION]
3030
[-t TIMEOUT] [-a ARN_STRING] [-v VERSION_NAME]
31-
[--version]
31+
[-e ENVIRONMENT_VARIABLES] [--version]
3232
FILE EVENT
3333
3434
Run AWS Lambda function written in Python on local machine.
@@ -118,16 +118,50 @@ python-lambda-local -l lib/ -f handler -t 5 test.py event.json
118118
The output will be like:
119119

120120
```
121-
[root - INFO - 2017-04-19 12:39:05,512] Event: {u'answer': 42}
122-
[root - INFO - 2017-04-19 12:39:05,512] START RequestId: b918f9ae-0ca1-44af-9937-dd5f9eeedcc1
121+
[root - INFO - 2018-11-20 17:10:53,352] Event: {'answer': 42}
122+
[root - INFO - 2018-11-20 17:10:53,352] START RequestId: 3c8e6db4-886a-43da-a1c7-5e6f715de531 Version:
123123
0
124124
49
125125
196
126126
441
127127
784
128128
1225
129-
[root - INFO - 2017-04-19 12:39:05,515] END RequestId: b918f9ae-0ca1-44af-9937-dd5f9eeedcc1
130-
[root - INFO - 2017-04-19 12:39:05,515] RESULT:
129+
[root - INFO - 2018-11-20 17:10:53,359] END RequestId: 3c8e6db4-886a-43da-a1c7-5e6f715de531
130+
[root - INFO - 2018-11-20 17:10:53,360] REPORT RequestId: 3c8e6db4-886a-43da-a1c7-5e6f715de531 Duration: 2.17 ms
131+
[root - INFO - 2018-11-20 17:10:53,360] RESULT:
131132
None
132-
[root - INFO - 2017-04-19 12:39:05,515] REPORT RequestId: b918f9ae-0ca1-44af-9937-dd5f9eeedcc1 Duration: 2.27 ms
133+
```
134+
135+
## Usage as a library
136+
137+
### API signature
138+
139+
``` python
140+
call(func, event, context, environment_variables={})
141+
```
142+
143+
Call a handler function `func` with given `event`, `context` and custom `environment_variables`.
144+
145+
### Sample
146+
147+
1. Make sure the 3rd party libraries used in the AWS Lambda function can be imported.
148+
149+
``` bash
150+
pip install rx
151+
```
152+
153+
2. To call the lambda function above with your python code:
154+
155+
``` python
156+
from lambda_local.main import call
157+
from lambda_local.context import Context
158+
159+
import test
160+
161+
event = {
162+
"answer": 42
163+
}
164+
context = Context(5)
165+
166+
call(test.handler, event, context)
133167
```

README.rst

Lines changed: 111 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,45 @@ Within virtualenv, run the following command.
1818

1919
.. code:: bash
2020
21-
$ pip install python-lambda-local
21+
$ pip install python-lambda-local
2222
2323
This will install the package with name ``python-lambda-local`` in the
2424
virtualenv. Now you can use the command ``python-lambda-local`` to run
2525
your AWS Lambda function written in Python on your own machine.
2626

27-
Usage
28-
-----
27+
Usage as a shell command
28+
------------------------
2929

3030
Run ``python-lambda-local -h`` to see the help.
3131

3232
::
3333

34-
usage: python-lambda-local [-h] [-l LIBRARY_PATH] [-f HANDLER_FUNCTION]
35-
[-t TIMEOUT] [-a ARN_STRING] [-v VERSION_NAME]
36-
[--version]
37-
FILE EVENT
38-
39-
Run AWS Lambda function written in Python on local machine.
40-
41-
positional arguments:
42-
FILE lambda function file name
43-
EVENT event data file name
44-
45-
optional arguments:
46-
-h, --help show this help message and exit
47-
-l LIBRARY_PATH, --library LIBRARY_PATH
48-
path of 3rd party libraries
49-
-f HANDLER_FUNCTION, --function HANDLER_FUNCTION
50-
lambda function handler name, default: "handler"
51-
-t TIMEOUT, --timeout TIMEOUT
52-
seconds until lambda function timeout, default: 3
53-
-a ARN_STRING, --arn-string ARN_STRING
54-
ARN string for lambda function
55-
-v VERSION_NAME, --version-name VERSION_NAME
56-
lambda function version name
57-
--version print the version of python-lambda-local and exit
34+
usage: python-lambda-local [-h] [-l LIBRARY_PATH] [-f HANDLER_FUNCTION]
35+
[-t TIMEOUT] [-a ARN_STRING] [-v VERSION_NAME]
36+
[-e ENVIRONMENT_VARIABLES] [--version]
37+
FILE EVENT
38+
39+
Run AWS Lambda function written in Python on local machine.
40+
41+
positional arguments:
42+
FILE lambda function file name
43+
EVENT event data file name
44+
45+
optional arguments:
46+
-h, --help show this help message and exit
47+
-l LIBRARY_PATH, --library LIBRARY_PATH
48+
path of 3rd party libraries
49+
-f HANDLER_FUNCTION, --function HANDLER_FUNCTION
50+
lambda function handler name, default: "handler"
51+
-t TIMEOUT, --timeout TIMEOUT
52+
seconds until lambda function timeout, default: 3
53+
-a ARN_STRING, --arn-string ARN_STRING
54+
ARN string for lambda function
55+
-v VERSION_NAME, --version-name VERSION_NAME
56+
lambda function version name
57+
-e ENVIRONMENT_VARIABLES, --environment-variables ENVIRONMENT_VARIABLES
58+
path to flat json file with environment variables
59+
--version print the version of python-lambda-local and exit
5860

5961
Prepare development directory
6062
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -66,25 +68,25 @@ Suppose your project directory is like this:
6668

6769
::
6870

69-
├── event.json
70-
├── lib
71-
│   ├── rx
72-
│   │   ├── abstractobserver.py
73-
│   │   ├── ... (package content of rx)
74-
...
75-
│   │   └── testscheduler.py
76-
│   └── Rx-1.2.3.dist-info
77-
│   ├── DESCRIPTION.rst
78-
│   ├── METADATA
79-
│   ├── metadata.json
80-
│   ├── pbr.json
81-
│   ├── RECORD
82-
│   ├── top_level.txt
83-
│   ├── WHEEL
84-
│   └── zip-safe
85-
└── test.py
86-
87-
The handler's code is in ``test.py`` and the function name of the
71+
├── event.json
72+
├── lib
73+
│   ├── rx
74+
│   │   ├── abstractobserver.py
75+
│   │   ├── ... (package content of rx)
76+
...
77+
│   │   └── testscheduler.py
78+
│   └── Rx-1.2.3.dist-info
79+
│   ├── DESCRIPTION.rst
80+
│   ├── METADATA
81+
│   ├── metadata.json
82+
│   ├── pbr.json
83+
│   ├── RECORD
84+
│   ├── top_level.txt
85+
│   ├── WHEEL
86+
│   └── zip-safe
87+
└── test.py
88+
89+
The handlers code is in ``test.py`` and the function name of the
8890
handler is ``handler``. The source depends on 3rd party library ``rx``
8991
and it is installed in the directory ``lib``. The test event in json
9092
format is in ``event.json`` file.
@@ -94,25 +96,25 @@ Content of ``test.py``:
9496

9597
.. code:: python
9698
97-
from __future__ import print_function
98-
from rx import Observable
99+
from __future__ import print_function
100+
from rx import Observable
99101
100102
101-
def handler(event, context):
102-
xs = Observable.from_(range(event['answer']))
103-
ys = xs.to_blocking()
104-
zs = (x*x for x in ys if x % 7 == 0)
105-
for x in zs:
106-
print(x)
103+
def handler(event, context):
104+
xs = Observable.from_(range(event['answer']))
105+
ys = xs.to_blocking()
106+
zs = (x*x for x in ys if x % 7 == 0)
107+
for x in zs:
108+
print(x)
107109
108110
Content of ``event.json``:
109111
^^^^^^^^^^^^^^^^^^^^^^^^^^
110112

111113
.. code:: json
112114
113-
{
114-
"answer": 42
115-
}
115+
{
116+
"answer": 42
117+
}
116118
117119
Run the lambda function
118120
^^^^^^^^^^^^^^^^^^^^^^^
@@ -122,24 +124,63 @@ the following command
122124

123125
::
124126

125-
python-lambda-local -l lib/ -f handler -t 5 test.py event.json
127+
python-lambda-local -l lib/ -f handler -t 5 test.py event.json
126128

127129
The output will be like:
128130

129131
::
130132

131-
[root - INFO - 2017-04-19 12:39:05,512] Event: {u'answer': 42}
132-
[root - INFO - 2017-04-19 12:39:05,512] START RequestId: b918f9ae-0ca1-44af-9937-dd5f9eeedcc1
133-
0
134-
49
135-
196
136-
441
137-
784
138-
1225
139-
[root - INFO - 2017-04-19 12:39:05,515] END RequestId: b918f9ae-0ca1-44af-9937-dd5f9eeedcc1
140-
[root - INFO - 2017-04-19 12:39:05,515] RESULT:
141-
None
142-
[root - INFO - 2017-04-19 12:39:05,515] REPORT RequestId: b918f9ae-0ca1-44af-9937-dd5f9eeedcc1 Duration: 2.27 ms
133+
[root - INFO - 2018-11-20 17:10:53,352] Event: {'answer': 42}
134+
[root - INFO - 2018-11-20 17:10:53,352] START RequestId: 3c8e6db4-886a-43da-a1c7-5e6f715de531 Version:
135+
0
136+
49
137+
196
138+
441
139+
784
140+
1225
141+
[root - INFO - 2018-11-20 17:10:53,359] END RequestId: 3c8e6db4-886a-43da-a1c7-5e6f715de531
142+
[root - INFO - 2018-11-20 17:10:53,360] REPORT RequestId: 3c8e6db4-886a-43da-a1c7-5e6f715de531 Duration: 2.17 ms
143+
[root - INFO - 2018-11-20 17:10:53,360] RESULT:
144+
None
145+
146+
Usage as a library
147+
------------------
148+
149+
API signature
150+
~~~~~~~~~~~~~
151+
152+
.. code:: python
153+
154+
call(func, event, context, environment_variables={})
155+
156+
Call a handler function ``func`` with given ``event``, ``context`` and
157+
custom ``environment_variables``.
158+
159+
Sample
160+
~~~~~~
161+
162+
1. Make sure the 3rd party libraries used in the AWS Lambda function can
163+
be imported.
164+
165+
.. code:: bash
166+
167+
pip install rx
168+
169+
2. To call the lambda function above with your python code:
170+
171+
.. code:: python
172+
173+
from lambda_local.main import call
174+
from lambda_local.context import Context
175+
176+
import test
177+
178+
event = {
179+
"answer": 42
180+
}
181+
context = Context(5)
182+
183+
call(test.handler, event, context)
143184
144185
.. |Join the chat at https://gitter.im/HDE/python-lambda-local| image:: https://badges.gitter.im/Join%20Chat.svg
145186
:target: https://gitter.im/HDE/python-lambda-local?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge

lambda_local/__init__.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,16 @@
77

88
from __future__ import print_function
99
import argparse
10-
import sys
11-
from multiprocessing import Process
1210
import pkg_resources
1311

1412
from .main import run
1513

16-
1714
__version__ = pkg_resources.require("python-lambda-local")[0].version
1815

1916

2017
def main():
2118
args = parse_args()
22-
23-
p = Process(target=run, args=(args,))
24-
p.start()
25-
p.join()
26-
27-
sys.exit(p.exitcode)
19+
run(args)
2820

2921

3022
def parse_args():

lambda_local/context.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,47 @@
22
Copyright 2015-2018 HDE, Inc.
33
Licensed under MIT.
44
'''
5+
from __future__ import print_function
56

67
from datetime import datetime
78
from datetime import timedelta
9+
import uuid
810

911

1012
class Context(object):
11-
def __init__(self, timeout, arn_string, version_name):
12-
self.function_name = "undefined"
13-
self.function_version = version_name
14-
self.invoked_function_arn = arn_string
15-
self.memory_limit_in_mb = 0
16-
self.aws_request_id = "undefined"
17-
self.log_group_name = "undefined"
18-
self.log_stream_name = "undefined"
19-
self.identity = None
20-
self.client_context = None
21-
self.timeout = timeout
22-
self.duration = timedelta(seconds=timeout)
13+
def __init__(self, timeout_in_seconds,
14+
aws_request_id=uuid.uuid4(),
15+
function_name="undefined",
16+
function_version="$LATEST",
17+
log_group_name="undefined",
18+
log_stream_name="undefined",
19+
invoked_function_arn="undefined",
20+
memory_limit_in_mb='0',
21+
client_context=None,
22+
identity=None):
23+
self.function_name = function_name
24+
self.function_version = function_version
25+
self.invoked_function_arn = invoked_function_arn
26+
self.memory_limit_in_mb = memory_limit_in_mb
27+
self.aws_request_id = aws_request_id
28+
self.log_group_name = log_group_name
29+
self.log_stream_name = log_stream_name
30+
self.identity = identity
31+
self.client_context = client_context
32+
33+
self._timeout_in_seconds = timeout_in_seconds
34+
self._duration = timedelta(seconds=timeout_in_seconds)
2335

2436
def get_remaining_time_in_millis(self):
25-
if self.timelimit is None:
37+
if self._timelimit is None:
2638
raise Exception("Context not activated.")
27-
return millis_interval(datetime.now(), self.timelimit)
39+
return millis_interval(datetime.now(), self._timelimit)
40+
41+
def log(self, msg):
42+
print(msg)
2843

29-
def activate(self):
30-
self.timelimit = datetime.now() + self.duration
44+
def _activate(self):
45+
self._timelimit = datetime.now() + self._duration
3146
return self
3247

3348

0 commit comments

Comments
 (0)