/
femhub_run.py
executable file
·678 lines (608 loc) · 23 KB
/
femhub_run.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
#! /usr/bin/env python
import os
from time import sleep
from glob import glob
from os.path import expandvars
from optparse import OptionParser
import tempfile
import subprocess
import time
version = "0.9.10.beta1"
release_date = "November 21, 2010"
class CmdException(Exception):
pass
class PackageBuildFailed(Exception):
pass
def main():
systemwide_python = (os.environ["FEMHUB_SYSTEMWIDE_PYTHON"] == "yes")
if systemwide_python:
print """\
***************************************************
FEMhub is not installed. Running systemwide Python.
Only use this mode to install FEMhub.
***************************************************"""
parser = OptionParser(usage="[options] args")
parser.add_option("-i", "--install",
action="store", type="str", dest="install", metavar="PACKAGE",
default="", help="install a spkg package")
parser.add_option("-f", "--force",
action="store_true", dest="force",
default=False, help="force the installation")
parser.add_option("-d", "--download_packages",
action="store_true", dest="download",
default=False, help="download standard spkg packages")
parser.add_option("-b", "--build",
action="store_true", dest="build",
default=False, help="build FEMhub")
parser.add_option("-j",
action="store", type="int", dest="cpu_count", metavar="NCPU",
default=0, help="number of cpu to use (0 = all)")
parser.add_option("--shell",
action="store_true", dest="shell",
default=False, help="starts a FEMhub shell")
parser.add_option("-s", "--script",
action="store", type="str", dest="script", metavar="SCRIPT",
default=None, help="runs '/bin/bash SCRIPT' in a FEMhub shell")
parser.add_option("--python",
action="store", type="str", dest="python", metavar="SCRIPT",
default=None, help="runs 'python SCRIPT' in a FEMhub shell")
parser.add_option("--unpack",
action="store", type="str", dest="unpack", metavar="PACKAGE",
default=None, help="unpacks the PACKAGE into the 'devel/' dir")
parser.add_option("--pack",
action="store", type="str", dest="pack", metavar="PACKAGE",
default=None, help="creates 'devel/PACKAGE.spkg' from 'devel/PACKAGE'")
parser.add_option("--devel-install",
action="store", type="str", dest="devel_install", metavar="PACKAGE",
default=None, help="installs 'devel/PACKAGE' into FEMhub directly")
parser.add_option("--create-package",
action="store", type="str", dest="create_package",
metavar="PACKAGE", default=None,
help="creates 'PACKAGE.spkg' in the current directory using the official git repository sources")
parser.add_option("--upload-package",
action="store", type="str", dest="upload_package",
metavar="PACKAGE", default=None,
help="upload 'PACKAGE.spkg' from the current directory to the server (for FEMhub developers only)")
parser.add_option("--release-binary",
action="store_true", dest="release_binary",
default=False, help="Creates a binary release using the current state (for FEMhub developers only)")
options, args = parser.parse_args()
if options.download:
download_packages()
return
if options.install:
try:
install_package(options.install, cpu_count=options.cpu_count,
force_install=options.force)
except PackageBuildFailed:
pass
return
if options.build:
build(cpu_count=options.cpu_count)
return
if options.shell:
print "Type CTRL-D to exit the FEMhub shell."
cmd("cd $CUR; /bin/bash --rcfile $FEMHUB_ROOT/spkg/base/femhub-shell-rc")
return
if options.script:
setup_cpu(options.cpu_count)
try:
cmd("cd $CUR; /bin/bash " + options.script)
except CmdException:
print "FEMhub script exited with an error."
return
if options.python:
cmd("cd $CUR; /usr/bin/env python " + options.python)
return
if options.unpack:
pkg = pkg_make_absolute(options.unpack)
print "Unpacking '%(pkg)s' into 'devel/'" % {"pkg": pkg}
cmd("mkdir -p $FEMHUB_ROOT/devel")
cmd("cd $FEMHUB_ROOT/devel; tar xjf %s" % pkg)
return
if options.pack:
dir = options.pack
if not os.path.exists(dir):
dir = expandvars("$FEMHUB_ROOT/devel/%s" % dir)
if not os.path.exists(dir):
raise Exception("Unknown package to pack")
dir = os.path.split(dir)[1]
print "Creating devel/%(dir)s.spkg from devel/%(dir)s" % {"dir": dir}
cmd("cd $FEMHUB_ROOT/devel; tar cjf %(dir)s.spkg %(dir)s" % \
{"dir": dir})
return
if options.devel_install:
dir = options.devel_install
if not os.path.exists(dir):
dir = expandvars("$FEMHUB_ROOT/devel/%s" % dir)
if not os.path.exists(dir):
raise Exception("Unknown package to pack")
dir = os.path.normpath(dir)
dir = os.path.split(dir)[1]
print "Installing devel/%(dir)s into FEMhub" % {"dir": dir}
cmd("mkdir -p $FEMHUB_ROOT/spkg/build/")
cmd("rm -rf $FEMHUB_ROOT/spkg/build/%(dir)s" % {"dir": dir})
cmd("cp -r $FEMHUB_ROOT/devel/%(dir)s $FEMHUB_ROOT/spkg/build/" % \
{"dir": dir})
setup_cpu(options.cpu_count)
cmd("cd $FEMHUB_ROOT/spkg/build/%(dir)s; /bin/bash spkg-install" % \
{"dir": dir})
cmd("rm -rf $FEMHUB_ROOT/spkg/build/%(dir)s" % {"dir": dir})
return
if options.create_package:
create_package(options.create_package)
return
if options.upload_package:
upload_package(options.upload_package)
return
if options.release_binary:
release_binary()
return
if systemwide_python:
parser.print_help()
else:
start_femhub()
def setup_cpu(cpu_count):
if cpu_count == 0:
try:
import multiprocessing
cpu_count = multiprocessing.cpu_count() + 1
except ImportError:
cpu_count = 1
if cpu_count > 1:
os.environ["MAKEFLAGS"] = "-j %d" % cpu_count
def cmd(s, capture=False):
s = expandvars(s)
if capture:
p = subprocess.Popen(s, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
output = p.communicate()[0]
r = p.returncode
else:
output = None
r = os.system(s)
if r != 0:
raise CmdException("Command '%s' failed with err=%d." % (s, r))
return output
def create_package(package):
packages = {
"libfemhub": "git://github.com/hpfem/libfemhub.git",
"onlinelab": "git://github.com/hpfem/femhub-online-lab.git",
"phaml": "git://github.com/hpfem/phaml.git",
"arpack": "git://github.com/hpfem/arpack.git",
"mesheditorflex": "git://github.com/hpfem/mesheditor-flex.git",
"cython": "git://github.com/hpfem/cython.git",
"hermes2d": "git://github.com/hpfem/hermes.git",
}
if package not in packages:
raise Exception("Unknown package")
git_repo = packages[package]
a = git_repo.rfind("/") + 1
b = git_repo.rfind(".git")
dir_name = git_repo[a:b]
print "Creating a package in the current directory."
print "Package name:", package
print "Git repository:", git_repo
tmp = tempfile.mkdtemp()
print "Using temporary directory:", tmp
cur = cmd("echo $CUR", capture=True).strip()
cmd("cd %s; git clone %s" % (tmp, git_repo))
commit = cmd("cd %s/%s; git rev-parse HEAD" % (tmp, dir_name),
capture=True).strip()
sha = commit[:7]
if os.path.exists("%s/%s/spkg-prepare" % (tmp, dir_name)):
print "spkg-prepare found, running it..."
cmd("cd %s/%s; sh spkg-prepare" % (tmp, dir_name))
# hermes packages require special handling:
if package == "hermes2d":
# The spkg-prepare script is in the "hermes2d" subdirectory:
print "Preparing the hermes2d package..."
cmd("cd %s/%s; rm -rf hermes1d hermes3d doc .git" % (tmp, dir_name))
cmd("cd %s/%s; cp hermes2d/spkg-install ." % (tmp, dir_name))
datetimestr = time.strftime("%Y%m%d%M%S")
new_dir_name = "%s-%s_%s" % (package, datetimestr, sha)
pkg_filename = "%s.spkg" % (new_dir_name)
cmd("cd %s; mv %s %s" % (tmp, dir_name, new_dir_name))
print "Creating the spkg package..."
cmd("cd %s; tar cjf %s %s" % (tmp, pkg_filename, new_dir_name))
cmd("cp %s/%s %s/%s" % (tmp, pkg_filename, cur, pkg_filename))
print
print "Package created: %s" % (pkg_filename)
def upload_package(package):
cmd("cd $CUR; scp %s spilka.math.unr.edu:/var/www3/femhub.org/packages/femhub_st/" % (package))
print "Package uploaded: %s" % (package)
def release_binary():
tmp = tempfile.mkdtemp()
femhub_dir = "femhub-%s" % version
print "Using temporary directory:", tmp
cur = cmd("echo $CUR", capture=True).strip()
cmd("mkdir %s/%s" % (tmp, femhub_dir))
print "Copying femhub into the temporary directory..."
cmd("cp -r * %s/%s/" % (tmp, femhub_dir))
print "Removing source SPKG packages"
cmd("rm -f %s/%s/spkg/standard/*" % (tmp, femhub_dir))
print "Creating a binary tarball"
cmd("cd %s; tar czf %s.tar.gz %s" % (tmp, femhub_dir, femhub_dir))
cmd("cp %s/%s.tar.gz ." % (tmp, femhub_dir))
print
print "Package created: %s.tar.gz" % (femhub_dir)
def start_femhub(debug=False):
if debug:
print "Loading IPython..."
try:
import IPython
except ImportError:
raise Exception("You need to install 'ipython'")
if debug:
print " Done."
banner_length = 70
l = "| FEMhub Version %s, Release Date: %s" % (version, release_date)
l += " " * (banner_length - len(l) - 1) + "|"
banner = "-" * banner_length + "\n" + l + "\n"
l = "| Type lab() for the GUI."
l += " " * (banner_length - len(l) - 1) + "|"
banner += l + "\n" + "-" * banner_length + "\n"
def lab_wrapper(old = False, auth=True, *args, **kwargs):
if old:
from sagenb.notebook.notebook_object import lab
lab(*args, **kwargs)
else:
run_lab(auth=auth)
namespace = {"lab": lab_wrapper}
os.environ["IPYTHONDIR"] = expandvars("$DOT_SAGE/ipython")
os.environ["IPYTHONRC"] = "ipythonrc"
if not os.path.exists(os.environ["IPYTHONRC"]):
cmd('mkdir -p "$DOT_SAGE"')
cmd('cp -r "$FEMHUB_ROOT/spkg/base/ipython" "$DOT_SAGE/"')
os.environ["MPLCONFIGDIR"] = expandvars("$DOT_SAGE/matplotlib")
if not os.path.exists(os.environ["MPLCONFIGDIR"]):
cmd('cp -r "$FEMHUB_ROOT/spkg/base/matplotlib" "$DOT_SAGE/"')
if debug:
print "Starting the main loop..."
IPython.Shell.start(user_ns=namespace).mainloop(banner=banner)
def download_packages():
print "Downloading standard spkg packages"
cmd("mkdir -p $FEMHUB_ROOT/spkg/standard")
packages = get_standard_packages()
for p in packages:
cmd("cd $FEMHUB_ROOT/spkg/standard; ../base/femhub-wget %s" % p)
def install_package(pkg, install_dependencies=True, force_install=False,
cpu_count=0):
"""
Installs the package "pkg".
"pkg" can be either a full path, or just the name of the package (with or
without a version).
"install_dependencies" ... if True, it will also install all dependencies
"force_install" ... if True, it will install the package even if it has
been already installed
"cpu_count" ... number of processors to use (0 means the number of
processors in the machine)
Examples:
>>> install_package("http://femhub.org/stpack/python-2.6.4.p9.spkg")
>>> install_package("spkg/standard/readline-6.0.spkg")
>>> install_package("readline-6.0.spkg")
>>> install_package("readline")
"""
if pkg.startswith(("http", "www")):
remote = True
import tempfile
tmpdir = tempfile.mkdtemp()
cmd("wget --directory-prefix=" + tmpdir + " " + pkg)
pkg_name = os.path.split(pkg)
pkg = os.path.join(tmpdir,pkg_name[1])
else:
remote = False
pkg = pkg_make_absolute(pkg)
if is_installed(pkg):
if not force_install:
print "Package '%s' is already installed" % pkg_make_relative(pkg)
return
if install_dependencies:
print "Installing dependencies for %s..." % pkg
for dep in get_dependencies(pkg):
install_package(dep, install_dependencies=False,
cpu_count=cpu_count)
print "Installing %s..." % pkg
femhub_scripts = ["femhub-env", "femhub-make_relative"]
setup_cpu(cpu_count)
# Create the standard POSIX directories:
for d in ["bin", "doc", "include", "lib", "man", "share"]:
cmd("mkdir -p $FEMHUB_ROOT/local/%s" % d)
for script in femhub_scripts:
cmd("cp $FEMHUB_ROOT/spkg/base/%s $FEMHUB_ROOT/local/bin/" % script)
try:
cmd("$FEMHUB_ROOT/spkg/base/femhub-spkg %s" % pkg)
except CmdException:
#print "Package %s failed to install" % pkg
raise PackageBuildFailed()
cmd("touch $FEMHUB_ROOT/spkg/installed/%s" % pkg_make_relative(pkg))
if remote:
from shutil import rmtree
rmtree(tmpdir)
def is_installed(pkg):
pkg = pkg_make_relative(pkg)
candidates = glob(expandvars("$FEMHUB_ROOT/spkg/installed/%s" % pkg))
if len(candidates) == 1:
return True
elif len(candidates) == 0:
return False
else:
raise Exception("Internal error: got more candidates in is_installed")
def pkg_make_absolute(pkg):
if os.path.exists(pkg):
return os.path.abspath(pkg)
pkg_current = expandvars("$CUR/%s" % pkg)
if os.path.exists(pkg_current):
return pkg_current
pkg_default = "$FEMHUB_ROOT/spkg/standard"
if os.path.exists(pkg_default):
return pkg_default
candidates = glob(expandvars("$FEMHUB_ROOT/spkg/standard/*.spkg"))
if len(candidates) == 0:
raise Exception("Package '%s' not found" % pkg)
cands = []
for p in candidates:
path, ext = os.path.splitext(p)
assert ext == ".spkg"
directory, filename = os.path.split(path)
name, version = extract_name_version(filename)
if name == pkg:
return p
if pkg in name:
cands.append(p)
if len(cands) == 1:
return cands[0]
print "Too many candidates:"
print " " + "\n ".join(cands)
raise Exception("Ambiguous package name.")
def pkg_make_relative(pkg):
# TODO: look at this part:
pkg = pkg_make_absolute(pkg)
# This is quite robust:
pkg_with_version = pkg[pkg.rfind("/")+1:pkg.rfind(".spkg")]
# This might be a bit fragile:
pkg_name = pkg_with_version[:pkg_with_version.find("-")]
return pkg_name
def make_unique(l):
m = []
for item in l:
if item not in m:
m.append(item)
return m
def get_dependencies(pkg):
"""
Gets all (including indirect) dependencies for the package "pkg".
For simplicity, the dependency graph is currently hardwired in this
function.
"""
pkg_name = pkg_make_relative(pkg)
dependency_graph = {
"python": ["termcap", "zlib", "readline", "bzip2", "gnutls",
"libpng"],
"ipython": ["python"],
"cython": ["python"],
"sympy": ["python"],
"lapack": ["fortran"],
"arpack": ["fortran"],
"blas": ["fortran", "lapack"],
"numpy": ["python", "lapack", "blas"],
"scipy": ["numpy"],
"matplotlib": ["freetype", "libpng", "python", "numpy"],
"hermes1d": ["cmake", "scipy", "cython", "matplotlib"],
"hermes2d": ["cmake", "scipy", "judy", "cython", "matplotlib"],
"vtk-cvs": ["mesa", "cmake"],
"mayavi": ["python", "configobj", "vtk-cvs", "setuptools"],
"pyparsing": ["python"],
"pysparse": ["python"],
"swig": ["python"],
"sfepy": ["swig", "scipy"],
"py": ["setuptools"],
"setuptools": ["python"],
"fipy": ["pysparse", "setuptools"],
"libfemhub": ["python", "matplotlib"],
"libgcrypt": ["libgpg_error"],
"opencdk": ["zlib", "libgcrypt"],
"gnutls": ["libgcrypt", "opencdk"],
"python_gnutls": ["gnutls"],
"python_django": ["python",],
"simplejson": ["python", "setuptools"],
"sqlite": ["python",],
"pysqlite": ["python", "sqlite",],
"python_tornado": ["python_pycurl"],
"python_pycurl": ["curl"],
"onlinelab": ["python", "python_django", "simplejson", "pysqlite",
"pyinotify", "python_argparse", "python_lockfile", "python_daemon", "python_psutil",
"python_tornado", "docutils", "pygments",
],
"trilinos": ["python", "blas"],
"proteus": ["numpy", "cython"],
"phaml": ["blas", "lapack", "cmake", "numpy", "arpack"],
"umfpack": ["blas"],
}
deps = []
for dep in dependency_graph.get(pkg_name, []):
deps.extend(get_dependencies(dep))
deps.append(dep)
deps = make_unique(deps)
return deps
def get_standard_packages(just_names=False):
"""
Returns the list of standard packages.
just_names ... if True, only the names of the packages are returned
Packages are copied from various sources (see the *_STANDARD variables
below). You can also check (and update) the versions on the web:
FEMhub: http://femhub.org/stpack
"""
FEMHUB_STANDARD = "http://femhub.org/stpack"
femhub_packages = [
"termcap-1.3.1.p1",
"zlib-1.2.5",
"python-2.6.4.p9",
"cython-201012090206_a60b316",
"twisted-9.0.p2",
"jinja-1.2.p0",
"jinja2-2.1.1.p0",
"python_gnutls-1.1.4.p7",
"docutils-0.5.p0",
"pygments-0.11.1.p0",
"sphinx-0.6.3.p4",
"lapack-20071123.p1",
"blas-20070724",
"scipy-0.8",
"freetype-2.3.5.p2",
"libpng-1.2.35.p2",
"opencdk-0.6.6.p5",
"ipython-bzr1174",
"readline-6.0",
"bzip2-1.0.5",
"pexpect-2.0.p3",
"setuptools-0.6c11.p0",
"libgpg_error-1.6.p2.f1",
"libgcrypt-1.4.3.p2",
"gnutls-2.2.1.p3",
"pyinotify-0.7.2",
"python_argparse-1.1",
"python_lockfile-0.8",
"python_daemon-1.5.5",
"python_psutil-0.1.3",
"python_tornado-f732f98",
"onlinelab-201012090744_c4e10e9",
"py-1.3.1",
"fortran-814646f",
"f2py-9de8d45",
"numpy-1.5.0",
"matplotlib-0.99.1.p4",
"sympy-5d78c29",
"cmake-2.8.1.p2",
"judy-1.0.5.p1",
"mesa-7.4.4.p3",
"vtk-cvs-20090316-minimal.p6",
"configobj-4.5.3",
"mayavi-3.3.1.p2",
"pyparsing-1.5.2",
"swig-1.3.36",
"sfepy-2010.1",
"hermes1d-fb8163f",
"hermes2d-201012090547_4c365d1",
"pysparse-1.1-6301cea",
"phaml-201011190816_71974f0",
"arpack-201011191133_0ea3296",
"fipy-2.1-51f1360",
"libfemhub-201011294106_6e289eb",
"hdf5-1.6.9",
"h5py-1.2.1.p1",
"pytables-2.1",
"nose-0.11.1.p0",
"python_django-1.2.1",
"simplejson-2.1.1",
"sqlite-3.7.2",
"pysqlite-2.6.0",
"mesheditorflex-201012081048_d6f12f0",
"curl-7.21.1",
"python_pycurl-7.19.0",
"umfpack-5.5.0",
]
if just_names:
packages = \
[p + ".spkg" for p in femhub_packages]
else:
packages = \
[FEMHUB_STANDARD + "/" + p + ".spkg" for p in femhub_packages]
return packages
def build(cpu_count=0):
print "Building FEMhub"
# Only add the packages that you want to have in FEMhub. Don't add
# dependencies (those are handled in the get_dependencies() function)
packages_list = [
"ipython",
"hermes1d",
"hermes2d",
# requires: setupdocs>=1.0, doesn't work without a net...
"mayavi",
"phaml",
"libfemhub",
"fipy",
"sfepy",
"sympy",
"hdf5",
"h5py",
"pytables",
"nose",
"onlinelab",
"mesheditorflex",
]
try:
for pkg in packages_list:
install_package(pkg, cpu_count=cpu_count)
print
print "Finished building FEMhub."
except PackageBuildFailed:
print "FEMhub build failed."
def wait_for_ctrl_c():
try:
while 1:
sleep(1)
except KeyboardInterrupt:
pass
def run_lab(auth=False):
"""
Runs the online lab.
"""
print "Starting Online Lab: Open your web browser at http://localhost:8000/"
print "Press CTRL+C to kill it"
print
if auth:
cmd("onlinelab core start --home=$SPKG_LOCAL/share/onlinelab/core-home")
else:
cmd("onlinelab core start --no-auth --home=$SPKG_LOCAL/share/onlinelab/core-home")
cmd("onlinelab service start --home=$SPKG_LOCAL/share/onlinelab/service-home")
try:
wait_for_ctrl_c()
finally:
cmd("onlinelab core stop --home=$SPKG_LOCAL/share/onlinelab/core-home")
cmd("onlinelab service stop --home=$SPKG_LOCAL/share/onlinelab/service-home")
def extract_version(package_name):
"""
Extracts the version from the package_name.
The version is defined as one of the following:
-3245s
-ab434
-1.1-343s
-2.3-4
-134-minimal-24
but not:
-ab-13
-ab-ab
-m14-m16
The leading "-" is discarded.
Example:
>>> extract_version("jinja-2.5")
'2.5'
"""
def numeric(c):
if c in ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]:
return True
return False
first_dash = package_name.find("-")
last_dash = package_name.rfind("-")
if first_dash == last_dash:
return package_name[first_dash+1:]
while not numeric(package_name[first_dash + 1]):
package_name = package_name[first_dash+1:]
first_dash = package_name.find("-")
last_dash = package_name.rfind("-")
if first_dash == last_dash:
return package_name[first_dash+1:]
return package_name[first_dash + 1:]
def extract_name_version(package_name):
"""
Extracts the name and the version.
Example:
>>> extract_name_version("jinja-2.5")
('jinja', '2.5')
"""
version = extract_version(package_name)
name = package_name[:-len(version)-1]
return name, version
if __name__ == "__main__":
main()