Skip to content

Commit 0aea2af

Browse files
crazyengDorian Birraux
authored and
Dorian Birraux
committed
adding python modules
1 parent 29bfaa7 commit 0aea2af

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2707
-283
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
__pycache__
22
*.pyc
3-
*.class
3+
*$py.class

run.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import absolute_import, print_function, unicode_literals
4+
5+
if __name__ == '__main__':
6+
7+
#this will perform an auto install of missing modules using PIP
8+
#this won't be used in production, but it's handy when we are ginving this paclet to other developers
9+
10+
from wolframclient.cli.dispatch import execute_from_command_line
11+
12+
execute_from_command_line()

wolframclient/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-

wolframclient/cli/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-
+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import absolute_import, print_function, unicode_literals
4+
5+
from wolframclient.cli.utils import SimpleCommand
6+
from wolframclient.language.expression import wl
7+
from wolframclient.serializers import export
8+
from wolframclient.utils.debug import timed
9+
from wolframclient.utils.decorators import to_tuple
10+
from wolframclient.utils.encoding import force_text
11+
from wolframclient.utils.functional import first
12+
13+
import os
14+
import tempfile
15+
16+
class Command(SimpleCommand):
17+
18+
col_size = 8
19+
repetitions = 10
20+
complexity = [1, 2, 5, 10, 100, 1000]
21+
22+
@to_tuple
23+
def complexity_handler(self, complexity):
24+
for i in range(complexity):
25+
yield [wl.Symbol, {"a": [1, 2, 3], 2:2}]
26+
27+
@timed
28+
def export(self, *args, **opts):
29+
return export(*args, **opts)
30+
31+
def formatted_time(self, *args, **opts):
32+
33+
time = sum(
34+
first(self.export(*args, **opts))
35+
for i in range(self.repetitions)
36+
)
37+
38+
return '%.5f' % (time / self.repetitions)
39+
40+
def table_line(self, *iterable):
41+
self.print(*(force_text(c).ljust(self.col_size) for c in iterable))
42+
43+
def table_divider(self, length):
44+
self.print(*("-" * self.col_size for i in range(length)))
45+
46+
def handle(self, *args):
47+
48+
path = tempfile.gettempdir()
49+
50+
benchmarks = [
51+
(c, self.complexity_handler(c))
52+
for c in self.complexity
53+
]
54+
55+
self.print('dumping results in', path)
56+
57+
self.table_line("", *(force_text(c).ljust(self.col_size) for c in self.complexity))
58+
self.table_divider(len(self.complexity) + 1)
59+
60+
for export_format, opts in (
61+
("wl", dict()),
62+
("wxf", dict()),
63+
("wxf", dict(compress = True)),
64+
):
65+
self.table_line(export_format, *(
66+
self.formatted_time(
67+
expr,
68+
stream = os.path.join(path, 'benchmark-test-%s.%s' % (force_text(complexity).zfill(7), export_format)),
69+
format = export_format,
70+
**opts
71+
)
72+
for complexity, expr in benchmarks
73+
))
74+
75+
self.table_line()

wolframclient/cli/commands/test.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import absolute_import, print_function, unicode_literals
4+
5+
from wolframclient.cli.utils import discover_with_convention, SimpleCommand
6+
from wolframclient.utils import six
7+
from wolframclient.utils.importutils import import_string
8+
from wolframclient.utils.require import require_module
9+
10+
import sys
11+
import unittest
12+
13+
class Command(SimpleCommand):
14+
15+
modules = ['wolframclient.tests']
16+
class_name = 'TestCase'
17+
18+
if six.JYTHON:
19+
dependencies = (
20+
("pytz", None),
21+
)
22+
else:
23+
dependencies = (
24+
("pytz", None),
25+
("numpy", None),
26+
)
27+
28+
@property
29+
def available_test_cases(self):
30+
try:
31+
return self._test_cases
32+
except AttributeError:
33+
self._test_cases = discover_with_convention(self.modules, self.class_name)
34+
return self._test_cases
35+
36+
def add_arguments(self, parser):
37+
parser.add_argument('args', nargs='*')
38+
39+
def import_test_case(self, name):
40+
41+
if not name in self.available_test_cases:
42+
43+
#we need to validate names manually, I was not able to use .add_argument(choices = ...)
44+
45+
self.print('Available test suites:')
46+
for t in sorted(self.available_test_cases.keys()):
47+
self.print(' -', t)
48+
49+
self.print()
50+
self.print('%s is not a defined test suite. Create a TestCase in %s' % (
51+
name,
52+
" or ".join('%s.%s.%s' % (m, name, self.class_name) for m in self.modules)
53+
))
54+
55+
sys.exit(1)
56+
57+
return import_string(self.available_test_cases[name])
58+
59+
def handle(self, *args):
60+
61+
require_module(*self.dependencies)
62+
63+
suite = unittest.TestSuite()
64+
65+
for arg in (args or self.available_test_cases.keys()):
66+
test_case = self.import_test_case(arg)
67+
68+
for func in test_case.discover_tests():
69+
suite.addTest(test_case(func))
70+
71+
runner = unittest.TextTestRunner()
72+
result = runner.run(suite)
73+
if not result.wasSuccessful():
74+
sys.exit(1)

wolframclient/cli/dispatch.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import absolute_import, print_function, unicode_literals
4+
5+
from wolframclient.cli.utils import discover_with_convention, SimpleCommand
6+
from wolframclient.utils.importutils import import_string
7+
8+
import sys
9+
10+
class DispatchCommand(SimpleCommand):
11+
12+
modules = ['wolframclient.cli.commands']
13+
class_name = 'Command'
14+
15+
def subcommands(self):
16+
return discover_with_convention(self.modules, self.class_name)
17+
18+
def handle(self, attr = None):
19+
all_commands = self.subcommands()
20+
21+
if attr in all_commands:
22+
return import_string(all_commands[attr])(self.subcommand_args(), name = all_commands[attr]).main()
23+
24+
self.print('Select one of the following commands:')
25+
for command in sorted(all_commands.keys()):
26+
self.print(' -', command)
27+
28+
sys.exit(1)
29+
30+
def subcommand_args(self):
31+
argv = list(self.argv)
32+
if len(argv) > 1:
33+
argv.pop(1)
34+
return argv
35+
36+
def main(self):
37+
if len(self.argv) > 1 and self.argv[1]:
38+
return self.handle(self.argv[1])
39+
return self.handle()
40+
41+
def execute_from_command_line(argv = None, **opts):
42+
return DispatchCommand(argv).main()

wolframclient/cli/utils.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import absolute_import, print_function, unicode_literals
4+
5+
from wolframclient.utils.decorators import to_dict
6+
from wolframclient.utils.importutils import module_path
7+
8+
import argparse
9+
import os
10+
import sys
11+
12+
@to_dict
13+
def discover_with_convention(modules, import_name):
14+
for module in modules:
15+
for filename in os.listdir(module_path(module)):
16+
basename, ext = os.path.splitext(filename)
17+
if ext == '.py' and not basename == '__init__':
18+
yield basename, '%s.%s.%s' % (module, basename, import_name)
19+
20+
class SimpleCommand(object):
21+
22+
help = None
23+
print = print
24+
25+
def __init__(self, argv = None, name = None):
26+
if argv is None:
27+
self.argv = tuple(sys.argv)
28+
else:
29+
self.argv = argv
30+
31+
self.name = name
32+
33+
def create_parser(self):
34+
return argparse.ArgumentParser(prog = self.name, description=self.help)
35+
36+
def add_arguments(self, parser):
37+
pass
38+
39+
def handle(self, *args, **opts):
40+
pass
41+
42+
def main(self):
43+
parser = self.create_parser()
44+
if parser:
45+
self.add_arguments(parser)
46+
47+
cmd_options = vars(parser.parse_args(self.argv[1:]))
48+
args = cmd_options.pop('args', ())
49+
return self.handle(*args, **cmd_options)
50+
51+
return self.handle()

wolframclient/language/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-

wolframclient/language/decorators.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import absolute_import, print_function, unicode_literals
4+
5+
from functools import wraps
6+
7+
from wolframclient.language.exceptions import WolframLanguageExceptionBase, WolframLanguageExceptionFromPython
8+
from wolframclient.serializers import export
9+
10+
import sys
11+
12+
def safe_wl_execute(function, args = (), opts = {}, export_opts = {}):
13+
try:
14+
return export(function(*args, **opts), **export_opts)
15+
except WolframLanguageExceptionBase as e:
16+
e.set_traceback(*sys.exc_info())
17+
return export(e, **export_opts)
18+
except Exception as e:
19+
return export(WolframLanguageExceptionFromPython(e, exec_info = sys.exc_info()), **export_opts)
20+
21+
def to_wl(**export_opts):
22+
def outer(function):
23+
@wraps(function)
24+
def inner(*args, **opts):
25+
return safe_wl_execute(
26+
function = function,
27+
args = args,
28+
opts = opts,
29+
export_opts = export_opts,
30+
)
31+
return inner
32+
return outer

wolframclient/language/exceptions.py

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import absolute_import, print_function, unicode_literals
4+
5+
from wolframclient.language.expression import wl
6+
from wolframclient.serializers.serializable import WLSerializable
7+
from wolframclient.utils.decorators import to_dict
8+
from wolframclient.utils.encoding import safe_force_text
9+
10+
class WolframLanguageExceptionBase(WLSerializable):
11+
12+
def __init__(self):
13+
raise NotImplementedError
14+
15+
def failure_tag(self):
16+
raise NotImplementedError
17+
18+
def failure_template(self):
19+
raise NotImplementedError
20+
21+
def failure_parameters(self):
22+
return {}
23+
24+
def set_traceback(self, exc_type, exc_value, tb):
25+
self.exc_type, self.exc_value, self.tb = exc_type, exc_value, tb
26+
27+
def to_wl(self, **opts):
28+
return wl.Failure(
29+
self.failure_tag(),
30+
wl.Association(*(
31+
wl.RuleDelayed(key, value)
32+
for key, value in self.failure_meta().items()
33+
))
34+
)
35+
36+
def add_traceback(self):
37+
return True
38+
39+
@to_dict
40+
def failure_meta(self):
41+
42+
template, parameters = self.failure_template(), self.failure_parameters()
43+
44+
if template:
45+
yield "MessageTemplate", template
46+
47+
if parameters:
48+
yield "MessageParameters", parameters
49+
50+
if self.add_traceback() and self.tb:
51+
52+
from wolframclient.language.traceback import serialize_traceback
53+
54+
yield "Traceback", serialize_traceback(self.exc_type, self.exc_value, self.tb)
55+
56+
class WolframLanguageExceptionFromPython(WolframLanguageExceptionBase):
57+
58+
def __init__(self, exception, exec_info = None):
59+
self.original_exception = exception
60+
61+
if exec_info:
62+
self.set_traceback(*exec_info)
63+
else:
64+
self.set_traceback(None, None, None)
65+
66+
def failure_tag(self):
67+
return safe_force_text(self.original_exception.__class__.__name__)
68+
69+
def failure_template(self):
70+
return safe_force_text(self.original_exception)

0 commit comments

Comments
 (0)