pydan 1.7__tar.gz
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.
- usr/local/lib/python3.8/dist-packages/pydan/__init__.py +0 -0
- usr/local/lib/python3.8/dist-packages/pydan/__pycache__/__init__.cpython-38.pyc +0 -0
- usr/local/lib/python3.8/dist-packages/pydan/__pycache__/jdata.cpython-38.pyc +0 -0
- usr/local/lib/python3.8/dist-packages/pydan/__pycache__/run.cpython-38.pyc +0 -0
- usr/local/lib/python3.8/dist-packages/pydan/__pycache__/script.cpython-38.pyc +0 -0
- usr/local/lib/python3.8/dist-packages/pydan/__pycache__/utils.cpython-38.pyc +0 -0
- usr/local/lib/python3.8/dist-packages/pydan/jdata.py +471 -0
- usr/local/lib/python3.8/dist-packages/pydan/run.py +22 -0
- usr/local/lib/python3.8/dist-packages/pydan/script.py +50 -0
- usr/local/lib/python3.8/dist-packages/pydan/utils.py +21 -0
- usr/local/lib/python3.8/dist-packages/pydan-1.7.egg-info/PKG-INFO +13 -0
- usr/local/lib/python3.8/dist-packages/pydan-1.7.egg-info/SOURCES.txt +12 -0
- usr/local/lib/python3.8/dist-packages/pydan-1.7.egg-info/dependency_links.txt +1 -0
- usr/local/lib/python3.8/dist-packages/pydan-1.7.egg-info/requires.txt +6 -0
- usr/local/lib/python3.8/dist-packages/pydan-1.7.egg-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Data Helpers
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
import collections
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import io
|
|
10
|
+
import binascii
|
|
11
|
+
import random
|
|
12
|
+
from datetime import datetime,timezone
|
|
13
|
+
import base64
|
|
14
|
+
import platform # platform.node() -> hostname
|
|
15
|
+
# for yaml
|
|
16
|
+
#from ruamel.yaml.comments import CommentedMap
|
|
17
|
+
import ruamel.yaml
|
|
18
|
+
# for json
|
|
19
|
+
import json
|
|
20
|
+
# for xml
|
|
21
|
+
import dicttoxml
|
|
22
|
+
# self tools
|
|
23
|
+
from pydan import run
|
|
24
|
+
|
|
25
|
+
# repair LANG=C -> utf8
|
|
26
|
+
if(sys.getfilesystemencoding()=="ascii" and sys.getdefaultencoding()=="utf-8"):
|
|
27
|
+
sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8', buffering=1)
|
|
28
|
+
|
|
29
|
+
c={
|
|
30
|
+
"none":"\033[0m",
|
|
31
|
+
"header":"\033[38;5;166m", # orange
|
|
32
|
+
"group":"\033[1;34m", # light blue
|
|
33
|
+
"item":"\033[0;36m", # cian
|
|
34
|
+
"null":"\033[1;30m", # gray
|
|
35
|
+
"date":"\033[38;5;105m", # xviolet
|
|
36
|
+
"str":"\033[0;32m", # green
|
|
37
|
+
"int":"\033[1;32m", # light green
|
|
38
|
+
"float":"\033[38;5;112m", # xolive
|
|
39
|
+
"bool":"\033[1;36m", # white
|
|
40
|
+
"unk":"\033[0;31m", # red
|
|
41
|
+
"varint":"\033[1;35m", # magentab
|
|
42
|
+
"varenv":"\033[0;35m", # magenta
|
|
43
|
+
"varcmd":"\033[1;31m", # red
|
|
44
|
+
"err":"\033[1;31m", # light red
|
|
45
|
+
"important":"\033[1;33m", # light red
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#{{{ colprint: Imprime un dict por pantalla con colores según el tipo de datos
|
|
49
|
+
def colprint(d,header=None,key=None,indent="",crop=True):
|
|
50
|
+
indentchars=" "
|
|
51
|
+
if(header): print(c["header"]+header+c["none"]);indent=indent+indentchars
|
|
52
|
+
|
|
53
|
+
# Si es diccionario iteramos
|
|
54
|
+
if(type(d)==dict or type(d)==collections.OrderedDict): # or type(d)==CommentedMap):
|
|
55
|
+
#if(type(d)==dict or type(d)==collections.OrderedDict or type(d)==CommentedMap):
|
|
56
|
+
#if hasattr(d,'__iter__') and type(d)!=str:
|
|
57
|
+
if(key!=None): print(indent+c["group"]+key+":"+c["none"]); indent+=indentchars
|
|
58
|
+
if(len(d)==0): print(indent+c["null"]+"empty"+c["none"])
|
|
59
|
+
else:
|
|
60
|
+
for k in d: colprint(d[k], key=k, indent=indent)
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
# Si es lista listamos con [indice]
|
|
64
|
+
#if(type(d)==list):
|
|
65
|
+
# i=0
|
|
66
|
+
# print(indent+c["group"]+key+":"+c["none"])
|
|
67
|
+
# indent=indent+indentchars
|
|
68
|
+
# # Lista de strings
|
|
69
|
+
# #if type(key[0])==str:
|
|
70
|
+
# # for k in d:
|
|
71
|
+
# # print(indent+c["item"]+"["+str(i)+"]: "+c["none"], end='')
|
|
72
|
+
|
|
73
|
+
# #for k in d:
|
|
74
|
+
# # #print(indent+c["group"]+key+"["+str(i)+"]:"+c["none"])
|
|
75
|
+
# # #colprint(k, indent=indent+indentchars)
|
|
76
|
+
# # #print(indent+c["item"]+"["+str(i)+"]: "+c["none"], end='')
|
|
77
|
+
# # colprint(k, indent=indent+c["item"]+"["+str(i)+"]: ")
|
|
78
|
+
# # i=i+1
|
|
79
|
+
# # #print(k);
|
|
80
|
+
#
|
|
81
|
+
# for k in d:
|
|
82
|
+
# #print(indent+c["group"]+key+"["+str(i)+"]:"+c["none"])
|
|
83
|
+
# print(indent+c["group"]+"["+str(i)+"]:"+c["none"])
|
|
84
|
+
# colprint(k, indent=indent+indentchars)
|
|
85
|
+
# # #print(indent+c["item"]+"["+str(i)+"]: "+c["none"], end='')
|
|
86
|
+
# #colprint(k, indent=indent+c["item"]+"["+str(i)+"]: ")
|
|
87
|
+
# i=i+1
|
|
88
|
+
# #print(k);
|
|
89
|
+
# return
|
|
90
|
+
|
|
91
|
+
if type(d)==list or type(d)==tuple:
|
|
92
|
+
# Vacia
|
|
93
|
+
if len(d)==0:
|
|
94
|
+
if(key!=None):
|
|
95
|
+
print(indent+c["group"]+key+"[]: "+c["null"]+"empty"+c["none"]);
|
|
96
|
+
else:
|
|
97
|
+
print(indent+c["null"]+"empty"+c["none"])
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
# Lista de strings o ints
|
|
101
|
+
if type(d[0])==str or type(d[0])==int:
|
|
102
|
+
i=0
|
|
103
|
+
if key!=None:
|
|
104
|
+
print(indent+c["group"]+key+":"+c["none"])
|
|
105
|
+
for k in d:
|
|
106
|
+
colprint(str(k), key="["+str(i)+"]", indent=indent+indentchars)
|
|
107
|
+
i+=1
|
|
108
|
+
else:
|
|
109
|
+
for k in d:
|
|
110
|
+
colprint(str(k), key="["+str(i)+"]", indent=indent)
|
|
111
|
+
i+=1
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
#for k in d:
|
|
115
|
+
# #print(indent+c["group"]+key+"["+str(i)+"]:"+c["none"])
|
|
116
|
+
# #colprint(k, indent=indent+indentchars)
|
|
117
|
+
# #print(indent+c["item"]+"["+str(i)+"]: "+c["none"], end='')
|
|
118
|
+
# colprint(k, indent=indent+c["item"]+"["+str(i)+"]: ")
|
|
119
|
+
# i=i+1
|
|
120
|
+
# #print(k);
|
|
121
|
+
|
|
122
|
+
# Lista de objetos
|
|
123
|
+
if(type(d[0])==dict or type(d[0])==collections.OrderedDict):
|
|
124
|
+
i=0
|
|
125
|
+
for k in d:
|
|
126
|
+
print(indent+c["group"]+key+"["+str(i)+"]:"+c["none"])
|
|
127
|
+
colprint(k, indent=indent+indentchars)
|
|
128
|
+
i=i+1
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
print(c["err"]+"¿list of "+type(d[0]).__name__+"?"+c["none"])
|
|
132
|
+
return
|
|
133
|
+
#print("unknown "+type(d).__name__)
|
|
134
|
+
#return
|
|
135
|
+
|
|
136
|
+
# Mostramos key
|
|
137
|
+
if(key!=None): print(indent+c["item"]+key+": ", end='')
|
|
138
|
+
else: print(indent, end='')
|
|
139
|
+
|
|
140
|
+
# Mostramos valor
|
|
141
|
+
t=type(d)
|
|
142
|
+
if(t==str):
|
|
143
|
+
p=re.compile("\$([a-zA-Z0-9_]*)\$")
|
|
144
|
+
vars=set(p.findall(d))
|
|
145
|
+
for k in vars: d=re.sub("\$"+k+"\$", c["varenv"]+"$"+k+"$"+c["str"], d)
|
|
146
|
+
p=re.compile("\%([a-zA-Z0-9_]*)\%")
|
|
147
|
+
vars=set(p.findall(d))
|
|
148
|
+
for k in vars: d=re.sub("\%"+k+"\%", c["varint"]+"%"+k+"%"+c["str"], d)
|
|
149
|
+
p=re.compile("\(\(([^)]*)\)\)")
|
|
150
|
+
vars=set(p.findall(d))
|
|
151
|
+
for k in vars: d=re.sub("\(\(.*\)\)", c["varcmd"]+"(("+k+"))"+c["str"], d)
|
|
152
|
+
if crop and len(d)>4000:
|
|
153
|
+
print(c["important"]+"###DATA-"+str(len(d))+"###"+c["none"])
|
|
154
|
+
else:
|
|
155
|
+
print(c["str"]+d+c["none"])
|
|
156
|
+
elif(t==datetime):
|
|
157
|
+
dtstr=re.sub("\+00:00", "Z", d.isoformat())
|
|
158
|
+
#dtstr=d.__str__()
|
|
159
|
+
print(c["date"]+dtstr+c["none"])
|
|
160
|
+
elif(t==int):
|
|
161
|
+
print(c["int"]+str(d)+c["none"])
|
|
162
|
+
elif(t==float):
|
|
163
|
+
print(c["float"]+str(d)+c["none"])
|
|
164
|
+
elif(t==bool):
|
|
165
|
+
print(c["bool"]+str(d)+c["none"])
|
|
166
|
+
# elif(t==list):
|
|
167
|
+
# print
|
|
168
|
+
# for i in d:
|
|
169
|
+
# colprint(i,header="x",indent=indent)
|
|
170
|
+
# #print(indent+indentchars+c["str"]+i)
|
|
171
|
+
# #print(d)
|
|
172
|
+
elif(t==type(None)):
|
|
173
|
+
print(c["null"]+"null"+c["none"])
|
|
174
|
+
else:
|
|
175
|
+
print(c["err"]+"¿"+str(t.__name__)+"?"+c["none"])
|
|
176
|
+
#}}}
|
|
177
|
+
|
|
178
|
+
# Por cada item en d reemplaza $var$ por el valor de la variable en la lista varlist
|
|
179
|
+
#{{{ replacevars
|
|
180
|
+
def replacevars(d, varlist, unknownempty=False, emptyremove=False, unknownnull=False, emptynull=False):
|
|
181
|
+
#o=collections.OrderedDict()
|
|
182
|
+
o={}
|
|
183
|
+
for k in d:
|
|
184
|
+
if(type(d[k])==dict or type(d[k])==collections.OrderedDict):
|
|
185
|
+
d[k]=replacevars(d[k], varlist, unknownempty=unknownempty, emptyremove=emptyremove, unknownnull=unknownnull, emptynull=emptynull)
|
|
186
|
+
o[k]=d[k]
|
|
187
|
+
continue
|
|
188
|
+
else:
|
|
189
|
+
if(type(d[k])==str):
|
|
190
|
+
#if(d[k][0]=='$'):
|
|
191
|
+
# var=d[k][1:-1]
|
|
192
|
+
# v=varlist.get(var)
|
|
193
|
+
# if(v): o[k]=v
|
|
194
|
+
#else:
|
|
195
|
+
# o[k]=d[k]
|
|
196
|
+
|
|
197
|
+
# Buscamos variables en varlist
|
|
198
|
+
p=re.compile("\$([a-zA-Z0-9_]*)\$")
|
|
199
|
+
vars=set(p.findall(d[k]))
|
|
200
|
+
# No hay variables
|
|
201
|
+
if(vars==None):
|
|
202
|
+
o[k]=d[k]
|
|
203
|
+
continue
|
|
204
|
+
# Hay variables
|
|
205
|
+
for sk in vars:
|
|
206
|
+
val=varlist.get(sk)
|
|
207
|
+
if(val==None):
|
|
208
|
+
if(unknownempty): val=""
|
|
209
|
+
else:
|
|
210
|
+
if(unknownnull):
|
|
211
|
+
if emptynull: val="$null$"
|
|
212
|
+
else: val="null"
|
|
213
|
+
else:
|
|
214
|
+
continue
|
|
215
|
+
d[k]=re.sub("\$"+sk+"\$", str(val), d[k])
|
|
216
|
+
|
|
217
|
+
if(d[k]=="$null$" and emptynull): continue
|
|
218
|
+
if(d[k]=="" and emptyremove): continue
|
|
219
|
+
o[k]=d[k]
|
|
220
|
+
else:
|
|
221
|
+
o[k]=d[k]
|
|
222
|
+
return o
|
|
223
|
+
#}}}
|
|
224
|
+
|
|
225
|
+
# Por cada item en d reemplaza $e$var$ por variable de entorno
|
|
226
|
+
#{{{ replaceenv
|
|
227
|
+
def replaceenv(d, unknownempty=False, emptyremove=None):
|
|
228
|
+
o=collections.OrderedDict()
|
|
229
|
+
for k in d:
|
|
230
|
+
if(type(d[k])==dict or type(d[k])==collections.OrderedDict):
|
|
231
|
+
d[k]=replaceenv(d[k], unknownempty=unknownempty, emptyremove=emptyremove)
|
|
232
|
+
o[k]=d[k]
|
|
233
|
+
continue
|
|
234
|
+
else:
|
|
235
|
+
if(type(d[k])==str):
|
|
236
|
+
p=re.compile("\$e$([a-zA-Z0-9_]*)\$")
|
|
237
|
+
vars=set(p.findall(d[k]))
|
|
238
|
+
# No hay variables
|
|
239
|
+
if(vars==None):
|
|
240
|
+
o[k]=d[k]
|
|
241
|
+
continue
|
|
242
|
+
# Hay variables
|
|
243
|
+
for sk in vars:
|
|
244
|
+
if (sk=="HOSTNAME"): val=platform.node()
|
|
245
|
+
else: val=os.environ.get(sk)
|
|
246
|
+
if(val==None):
|
|
247
|
+
if(unknownempty): val=""
|
|
248
|
+
else: continue
|
|
249
|
+
d[k]=re.sub("\$e\$"+sk+"\$", val, d[k])
|
|
250
|
+
|
|
251
|
+
if(d[k]=="" and emptyremove): continue
|
|
252
|
+
o[k]=d[k]
|
|
253
|
+
else:
|
|
254
|
+
o[k]=d[k]
|
|
255
|
+
return o
|
|
256
|
+
#}}}
|
|
257
|
+
|
|
258
|
+
# Por cada item en d reemplaza ((cmd)) por la ejecución de cmd
|
|
259
|
+
# Por cada item en d reemplaza $b$file$ por el fichero en b64
|
|
260
|
+
# Por cada item en d reemplaza $t$file$ por el contenido del fichero
|
|
261
|
+
#{{{ runvars
|
|
262
|
+
def runvars(d, unknownempty=False, emptyremove=None):
|
|
263
|
+
o=collections.OrderedDict()
|
|
264
|
+
for k in d:
|
|
265
|
+
if(type(d[k])==dict or type(d[k])==collections.OrderedDict):
|
|
266
|
+
d[k]=runvars(d[k], unknownempty=unknownempty, emptyremove=emptyremove)
|
|
267
|
+
o[k]=d[k]
|
|
268
|
+
continue
|
|
269
|
+
else:
|
|
270
|
+
if(type(d[k])==str):
|
|
271
|
+
modified=False
|
|
272
|
+
|
|
273
|
+
# Comando a ejecutar
|
|
274
|
+
r_buscacmd=re.compile("\(\((.*)\)\)")
|
|
275
|
+
vars=set(r_buscacmd.findall(d[k]))
|
|
276
|
+
# No hay variables
|
|
277
|
+
if(vars==None):
|
|
278
|
+
o[k]=d[k]
|
|
279
|
+
# continue
|
|
280
|
+
else:
|
|
281
|
+
modified=True
|
|
282
|
+
# Hay variables
|
|
283
|
+
for sk in vars:
|
|
284
|
+
# b|fichero -> base64 fichero
|
|
285
|
+
#sk=re.sub(r"^t\|(.*)$", r"cat '\g<1>'", sk)
|
|
286
|
+
sk=re.sub(r"^b\|(.*)$", r"cat '\g<1>'|base64 -w0", sk)
|
|
287
|
+
pars=["bash","-c",sk]
|
|
288
|
+
ex=run.cmd(pars)
|
|
289
|
+
#if ex.retcode==0:
|
|
290
|
+
val=ex.out
|
|
291
|
+
if(val==None):
|
|
292
|
+
if(unknownempty): val=""
|
|
293
|
+
else: continue
|
|
294
|
+
#d[k]=re.sub("\(\("+sk+"\)\)", val, d[k])
|
|
295
|
+
d[k]=re.sub("\(\(.*\)\)", val, d[k])
|
|
296
|
+
|
|
297
|
+
# Fichero base64
|
|
298
|
+
r_buscacmd=re.compile(r"$b$(.*)$")
|
|
299
|
+
vars=set(r_buscacmd.findall(d[k]))
|
|
300
|
+
# No hay variables
|
|
301
|
+
if(vars==None):
|
|
302
|
+
o[k]=d[k]
|
|
303
|
+
else:
|
|
304
|
+
modified=True
|
|
305
|
+
# Hay variables
|
|
306
|
+
for sk in vars:
|
|
307
|
+
f=open(sk, "rb")
|
|
308
|
+
fdata=base64.b64encode(f.read()).decode()
|
|
309
|
+
d[k]=re.sub(r"$b$.*$", fdata, d[k])
|
|
310
|
+
|
|
311
|
+
# Fichero directo
|
|
312
|
+
r_buscacmd=re.compile(r"$t$(.*)$")
|
|
313
|
+
vars=set(r_buscacmd.findall(d[k]))
|
|
314
|
+
# No hay variables
|
|
315
|
+
if(vars==None):
|
|
316
|
+
o[k]=d[k]
|
|
317
|
+
else:
|
|
318
|
+
modified=True
|
|
319
|
+
# Hay variables
|
|
320
|
+
for sk in vars:
|
|
321
|
+
f=open(sk, "r")
|
|
322
|
+
fdata=f.read()
|
|
323
|
+
d[k]=re.sub(r"$t$.*$", fdata, d[k])
|
|
324
|
+
|
|
325
|
+
if modified and d[k]=="" and emptyremove: continue
|
|
326
|
+
o[k]=d[k]
|
|
327
|
+
else:
|
|
328
|
+
o[k]=d[k]
|
|
329
|
+
return o
|
|
330
|
+
#}}}
|
|
331
|
+
|
|
332
|
+
# Values of dict contained in another dict
|
|
333
|
+
def contained(d1, d2):
|
|
334
|
+
for k in d1:
|
|
335
|
+
if d2.get(k)==None: return False
|
|
336
|
+
if(type(d1[k])==dict or type(d1[k])==collections.OrderedDict):
|
|
337
|
+
if not contained(d1[k], d2[k]): return False
|
|
338
|
+
else:
|
|
339
|
+
if d1[k]!=d2[k]: return False
|
|
340
|
+
return True
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
#{{{ xml tools
|
|
344
|
+
|
|
345
|
+
# XML -> dict
|
|
346
|
+
def fromxml(xmldata):
|
|
347
|
+
return xmltodict.parse("<xml>"+xmldata+"</xml>", disable_entities=True)[xml]
|
|
348
|
+
|
|
349
|
+
#}}}
|
|
350
|
+
|
|
351
|
+
#{{{ json tools
|
|
352
|
+
def fromjson(jsondata):
|
|
353
|
+
return json.loads(jsondata,object_pairs_hook=json_parser_hook)
|
|
354
|
+
|
|
355
|
+
def readjson(jsonfile):
|
|
356
|
+
f=open(jsonfile,"rt")
|
|
357
|
+
json=f.read()
|
|
358
|
+
data=fromjson(json)
|
|
359
|
+
return data
|
|
360
|
+
|
|
361
|
+
def tojson(data,indent=None):
|
|
362
|
+
return json.dumps(data,separators=(',',':'),default=json_serializer_hook,indent=indent)
|
|
363
|
+
|
|
364
|
+
def writejson(data,filename,tabs=0,spaces=0):
|
|
365
|
+
f=open(filename, "w")
|
|
366
|
+
indent=None
|
|
367
|
+
if spaces!=0:
|
|
368
|
+
indent=spaces
|
|
369
|
+
if (tabs==1):
|
|
370
|
+
indent='\t'
|
|
371
|
+
jsondata=tojson(data,indent=indent)
|
|
372
|
+
f.write(jsondata)
|
|
373
|
+
f.write("\n")
|
|
374
|
+
f.close()
|
|
375
|
+
|
|
376
|
+
# json -> dict
|
|
377
|
+
def json_parser_hook(js):
|
|
378
|
+
#out=collections.OrderedDict(js)
|
|
379
|
+
out=dict(js)
|
|
380
|
+
for (key, value) in out.items():
|
|
381
|
+
# Hora con timezone sin milisegundos
|
|
382
|
+
try:
|
|
383
|
+
dt=re.sub("Z$", "UTC",value)
|
|
384
|
+
dt=datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S%Z")
|
|
385
|
+
#dt=dt.replace(tzinfo=datetime.timezone(datetime.timedelta(0)))
|
|
386
|
+
dt=dt.replace(tzinfo=timezone.utc)
|
|
387
|
+
out[key]=dt
|
|
388
|
+
continue
|
|
389
|
+
except: pass
|
|
390
|
+
# Hora con timezone con milisegundos
|
|
391
|
+
try:
|
|
392
|
+
dt=re.sub("Z$", "UTC",value)
|
|
393
|
+
dt=datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S.%f%Z")
|
|
394
|
+
dt=dt.replace(tzinfo=timezone.utc)
|
|
395
|
+
out[key]=dt
|
|
396
|
+
continue
|
|
397
|
+
except: pass
|
|
398
|
+
# Hora sin timezone sin milisegundos
|
|
399
|
+
try:
|
|
400
|
+
out[key]=datetime.strptime(value, "%Y-%m-%dT%H:%M:%S")
|
|
401
|
+
continue
|
|
402
|
+
except: pass
|
|
403
|
+
# Hora sin timezone con milisegundos
|
|
404
|
+
try:
|
|
405
|
+
out[key]=datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")
|
|
406
|
+
continue
|
|
407
|
+
except: pass
|
|
408
|
+
return out
|
|
409
|
+
|
|
410
|
+
# dict -> json
|
|
411
|
+
def json_serializer_hook(o):
|
|
412
|
+
if isinstance(o, datetime):
|
|
413
|
+
return re.sub("\+00:00", "Z", o.isoformat())
|
|
414
|
+
|
|
415
|
+
#}}}
|
|
416
|
+
|
|
417
|
+
#{{{ yaml tools
|
|
418
|
+
def fromyaml(yamldata):
|
|
419
|
+
yaml=yamldata.replace("\t", " ")
|
|
420
|
+
data=ruamel.yaml.load(yaml, Loader=ruamel.yaml.Loader)
|
|
421
|
+
return data
|
|
422
|
+
|
|
423
|
+
def readrawyaml(filename):
|
|
424
|
+
# Cargar fichero yaml en dict
|
|
425
|
+
import collections
|
|
426
|
+
ruamel.yaml.representer.RoundTripRepresenter.add_representer(
|
|
427
|
+
collections.OrderedDict, ruamel.yaml.representer.RoundTripRepresenter.represent_ordereddict)
|
|
428
|
+
f=open(filename,"rt")
|
|
429
|
+
yamldata=f.read()
|
|
430
|
+
data=fromyaml(yamldata)
|
|
431
|
+
return data
|
|
432
|
+
|
|
433
|
+
def readyaml(filename):
|
|
434
|
+
data=readrawyaml(filename)
|
|
435
|
+
if data.get("yaml-include"):
|
|
436
|
+
for f in data["yaml-include"]:
|
|
437
|
+
if os.path.isfile(f):
|
|
438
|
+
subdata=readyaml(f)
|
|
439
|
+
data.update(subdata)
|
|
440
|
+
else:
|
|
441
|
+
path=os.path.dirname(filename)
|
|
442
|
+
f=path+os.path.sep+f
|
|
443
|
+
if os.path.isfile(f):
|
|
444
|
+
subdata=read(f)
|
|
445
|
+
data.update(subdata)
|
|
446
|
+
#data["include"]=None
|
|
447
|
+
data.pop("yaml-include")
|
|
448
|
+
return data
|
|
449
|
+
|
|
450
|
+
def yamlupdate(filename,var,val,node=None):
|
|
451
|
+
yaml=ruamel.yaml.YAML()
|
|
452
|
+
yaml.width=4096
|
|
453
|
+
f=open(filename,"r")
|
|
454
|
+
data=yaml.load(f.read())
|
|
455
|
+
f.close()
|
|
456
|
+
datamod=data
|
|
457
|
+
if node:
|
|
458
|
+
for n in node:
|
|
459
|
+
datamod=datamod.get(n)
|
|
460
|
+
datamod[var]=val
|
|
461
|
+
f=open(filename, "w")
|
|
462
|
+
yaml.dump(data, f)
|
|
463
|
+
f.close()
|
|
464
|
+
|
|
465
|
+
def writeyaml(data,filename):
|
|
466
|
+
yaml=ruamel.yaml.YAML()
|
|
467
|
+
f=open(filename, "w")
|
|
468
|
+
yaml.dump(data, f)
|
|
469
|
+
f.close()
|
|
470
|
+
|
|
471
|
+
#}}}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
import types
|
|
5
|
+
import sys
|
|
6
|
+
import os
|
|
7
|
+
import time
|
|
8
|
+
|
|
9
|
+
def cmd(cmd):
|
|
10
|
+
ret=types.SimpleNamespace()
|
|
11
|
+
|
|
12
|
+
if sys.platform.startswith('win'):
|
|
13
|
+
cmdproc=subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE,creationflags=0x00000200)
|
|
14
|
+
else:
|
|
15
|
+
cmdproc=subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE,preexec_fn=os.setpgrp)
|
|
16
|
+
t1=time.time()
|
|
17
|
+
binout,binerr=cmdproc.communicate()
|
|
18
|
+
t2=time.time()
|
|
19
|
+
ret.time=t2-t1
|
|
20
|
+
ret.out=binout.decode().rstrip()+binerr.decode().rstrip()
|
|
21
|
+
ret.retcode=cmdproc.returncode
|
|
22
|
+
return ret
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
# Directorio del script principal
|
|
7
|
+
#scriptdir=sys.path[0]
|
|
8
|
+
|
|
9
|
+
# Cambiamos al directorio del script principal
|
|
10
|
+
#os.chdir(scriptdir)
|
|
11
|
+
|
|
12
|
+
# Utilizamos scriptdir/lib como path para los import
|
|
13
|
+
#sys.path.insert(1,scriptdir+'/lib')
|
|
14
|
+
|
|
15
|
+
# Cambiamos el nombre del proceso al del script
|
|
16
|
+
import setproctitle
|
|
17
|
+
setproctitle.setproctitle(os.path.basename(sys.argv[0]))
|
|
18
|
+
|
|
19
|
+
# Excepciones coloreadas
|
|
20
|
+
import colored_traceback.always
|
|
21
|
+
|
|
22
|
+
# Exportamos scriptdir al script principal
|
|
23
|
+
#import __main__
|
|
24
|
+
#__main__.scriptdir=scriptdir
|
|
25
|
+
|
|
26
|
+
def parsecmdline():
|
|
27
|
+
cmdline={}
|
|
28
|
+
cmdline["params"]=[]
|
|
29
|
+
cmdline["options"]={}
|
|
30
|
+
i=0
|
|
31
|
+
while i < len(sys.argv)-1:
|
|
32
|
+
i+=1
|
|
33
|
+
s=sys.argv[i]
|
|
34
|
+
if '=' in s:
|
|
35
|
+
keyval=s.split("=")
|
|
36
|
+
cmdline["options"][keyval[0]]=keyval[1]
|
|
37
|
+
elif s[0]=='-':
|
|
38
|
+
i+=1
|
|
39
|
+
val=sys.argv[i]
|
|
40
|
+
key=s[1:]
|
|
41
|
+
if (key[0]=='-'):
|
|
42
|
+
key=key[1:]
|
|
43
|
+
cmdline["options"][key]=val
|
|
44
|
+
else:
|
|
45
|
+
cmdline["params"].append(s)
|
|
46
|
+
if not cmdline["params"]:
|
|
47
|
+
cmdline["cmd"]=""
|
|
48
|
+
else:
|
|
49
|
+
cmdline["cmd"]=cmdline["params"][0]
|
|
50
|
+
return cmdline
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
|
|
6
|
+
def creation_date(path_to_file):
|
|
7
|
+
"""
|
|
8
|
+
Try to get the date that a file was created, falling back to when it was
|
|
9
|
+
last modified if that isn't possible.
|
|
10
|
+
See http://stackoverflow.com/a/39501288/1709587 for explanation.
|
|
11
|
+
"""
|
|
12
|
+
if platform.system() == 'Windows':
|
|
13
|
+
return os.path.getctime(path_to_file)
|
|
14
|
+
else:
|
|
15
|
+
stat = os.stat(path_to_file)
|
|
16
|
+
try:
|
|
17
|
+
return stat.st_birthtime
|
|
18
|
+
except AttributeError:
|
|
19
|
+
# We're probably on Linux. No easy way to get creation dates here,
|
|
20
|
+
# so we'll settle for when its content was last modified.
|
|
21
|
+
return stat.st_mtime
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 1.2
|
|
2
|
+
Name: pydan
|
|
3
|
+
Version: 1.7
|
|
4
|
+
Summary: Python3 Data Utils
|
|
5
|
+
Home-page: UNKNOWN
|
|
6
|
+
Author: Jose Biosca Martín
|
|
7
|
+
Author-email: jbiosca@zone-sys.net
|
|
8
|
+
License: UNKNOWN
|
|
9
|
+
Description: UNKNOWN
|
|
10
|
+
Platform: UNKNOWN
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Requires-Python: >=3.6
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
setup.py
|
|
2
|
+
pydan.egg-info/PKG-INFO
|
|
3
|
+
pydan.egg-info/SOURCES.txt
|
|
4
|
+
pydan.egg-info/dependency_links.txt
|
|
5
|
+
pydan.egg-info/requires.txt
|
|
6
|
+
pydan.egg-info/top_level.txt
|
|
7
|
+
src/__init__.py
|
|
8
|
+
src/jdata.py
|
|
9
|
+
src/run.py
|
|
10
|
+
src/script.py
|
|
11
|
+
src/utils.py
|
|
12
|
+
test/test-jdata.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pydan
|