forked from marcy-terui/lamvery
/
archive.py
155 lines (133 loc) · 4.96 KB
/
archive.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# -*- coding: utf-8 -*-
import os
import sys
import tempfile
import shutil
import re
import warnings
import lamvery.secret
import lamvery.config
from zipfile import PyZipFile, ZIP_DEFLATED
from lamvery.log import get_logger
warnings.simplefilter("ignore", UserWarning)
EXCLUDE_DIR = [
'.git',
'__pycache__'
]
PYFILE_PATTERN = re.compile('.+\.py.?$')
class Archive:
def __init__(
self,
filename,
function_filename=None,
single_file=False,
no_libs=False,
secret={},
exclude=[],
runtime=lamvery.config.RUNTIME_PY_27
):
self._filename = filename
self._function_filename = function_filename
self._tmpdir = tempfile.mkdtemp(suffix='lamvery')
self._zippath = os.path.join(self._tmpdir, self._filename)
self._secret = secret
self._single_file = single_file
self._no_libs = no_libs
self._exclude = exclude
self._runtime = runtime
def __del__(self):
shutil.rmtree(self._tmpdir)
def create_zipfile(self):
with PyZipFile(self._zippath, 'w', compression=ZIP_DEFLATED) as zipfile:
for p in self._get_paths():
if os.path.isdir(p):
self._archive_dir(zipfile, p)
else:
self._archive_file(zipfile, p)
if not self._single_file:
secret_path = os.path.join(self._tmpdir, lamvery.secret.SECRET_FILE_NAME)
lamvery.secret.generate(secret_path, self._secret)
self._archive_file(zipfile, secret_path)
if self._runtime == lamvery.config.RUNTIME_NODE_JS:
self._archive_dist(zipfile, 'lamvery.js')
return open(self._zippath, 'rb')
def _archive_dist(self, zipfile, dist):
self._archive_file(
zipfile, os.path.join(os.path.dirname(__file__), 'dists', dist))
def _archive_dir(self, zipfile, path):
dirname = os.path.basename(path)
if not self.is_exclude_dir(dirname):
zipfile.writepy(path)
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
f_path = os.path.join(dirpath, filename)
if self.is_source_file(filename) and not self.is_exclude_file(filename):
f_name = f_path.replace(os.path.dirname(path) + os.sep, '')
try:
zipfile.getinfo(f_name)
except KeyError:
zipfile.write(f_path, f_name)
def _archive_file(self, zipfile, path):
filename = os.path.basename(path)
if not self.is_exclude_file(filename):
if PYFILE_PATTERN.match(filename) is None:
try:
zipfile.getinfo(filename)
except KeyError:
zipfile.write(path, filename)
elif filename.endswith('.py'):
try:
zipfile.getinfo('{}c'.format(filename))
zipfile.getinfo('{}o'.format(filename))
except KeyError:
if self._single_file:
zipfile.write(path, filename)
else:
zipfile.writepy(path)
def is_exclude(self, name):
for ex in self._exclude:
if re.compile(ex).match(name) is not None:
return True
return False
def is_exclude_file(self, name):
if self.is_exclude(name):
return True
if name == self._filename:
return True
return False
def is_exclude_dir(self, name):
if self.is_exclude(name):
return True
for ex in EXCLUDE_DIR:
if name == ex:
return True
return False
def is_source_file(self, name):
return PYFILE_PATTERN.match(name) is not None
def _get_paths(self):
logger = get_logger(__name__)
try:
venv = os.environ['VIRTUAL_ENV']
except:
logger.warn(
'VIRTUAL_ENV environment variable can not be found. ' +
'Python libraries are not included in the archive.')
venv = None
paths = []
if not self._no_libs and venv is not None:
for p in sys.path:
if os.path.isdir(p) and os.path.exists(p):
if p.startswith(venv) and p.find('site-packages') != -1:
for f in os.listdir(p):
f_path = os.path.join(p, f)
paths.append(f_path)
for f in os.listdir(os.getcwd()):
f_path = os.path.join(os.getcwd(), f)
if not f_path == venv:
paths.append(f_path)
if self._single_file:
f = self._function_filename
paths = [os.path.join(os.getcwd(), f)]
return paths
def get_size(self):
return os.stat(self._zippath).st_size