Merge lp:~openerp-dev/openerp-command/trunk-entry-points-cto into lp:openerp-command

Proposed by Samus CTO (OpenERP)
Status: Work in progress
Proposed branch: lp:~openerp-dev/openerp-command/trunk-entry-points-cto
Merge into: lp:openerp-command
Diff against target: 1406 lines (+518/-472)
30 files modified
README (+1/-1)
openerpcommand/__init__.py (+95/-52)
openerpcommand/addons/bench_sale_mrp/data.yml (+1/-1)
openerpcommand/benchmark/__init__.py (+111/-0)
openerpcommand/benchmark/dummy.py (+18/-0)
openerpcommand/benchmark/fields_view_get.py (+20/-0)
openerpcommand/benchmark/login.py (+13/-0)
openerpcommand/benchmark/read.py (+20/-0)
openerpcommand/benchmark/sale_mrp.py (+14/-18)
openerpcommand/benchmarks.py (+0/-166)
openerpcommand/call.py (+11/-20)
openerpcommand/client.py (+0/-137)
openerpcommand/common.py (+49/-14)
openerpcommand/conf.py (+5/-10)
openerpcommand/consume_cpu.py (+16/-0)
openerpcommand/consume_memory.py (+16/-0)
openerpcommand/consume_nothing.py (+11/-0)
openerpcommand/drop.py (+2/-6)
openerpcommand/initialize.py (+10/-8)
openerpcommand/leak_memory.py (+11/-0)
openerpcommand/model.py (+2/-5)
openerpcommand/module.py (+4/-5)
openerpcommand/open.py (+29/-0)
openerpcommand/read.py (+1/-4)
openerpcommand/run_tests.py (+4/-6)
openerpcommand/scaffold.py (+1/-5)
openerpcommand/show.py (+23/-0)
openerpcommand/uninstall.py (+4/-7)
openerpcommand/update.py (+1/-3)
setup.py (+25/-4)
To merge this branch: bzr merge lp:~openerp-dev/openerp-command/trunk-entry-points-cto
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+135720@code.launchpad.net
To post a comment you must log in.
187. By Samus CTO (OpenERP)

[IMP] Missing calls to expand_path for addons paths

Unmerged revisions

187. By Samus CTO (OpenERP)

[IMP] Missing calls to expand_path for addons paths

186. By Samus CTO (OpenERP)

[IMP] Modules now use entry points and OE populate automatically

185. By Samus CTO (OpenERP)

[FIX] Agrolait's id has changed in default server demo data

184. By Samus CTO (OpenERP)

Updated TODO

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'README'
--- README 2012-10-31 10:52:02 +0000
+++ README 2012-11-27 15:42:19 +0000
@@ -4,6 +4,6 @@
4----4----
55
6- Make sure to have proper return code for success/failure.6- Make sure to have proper return code for success/failure.
7- `oe --help` is a mess (it seems argparse doesn't try to do something sensible).
8- Have a flag for `run-tests` to drop in the debugger (to be combined with7- Have a flag for `run-tests` to drop in the debugger (to be combined with
9 unittest2 fail-fast mode?).8 unittest2 fail-fast mode?).
9- Make sure oe can do everything openerp-server can do
1010
=== modified file 'openerpcommand/__init__.py'
--- openerpcommand/__init__.py 2012-11-05 11:27:01 +0000
+++ openerpcommand/__init__.py 2012-11-27 15:42:19 +0000
@@ -1,61 +1,104 @@
1"""
2OpenERP Command provides a set of command-line tools around the OpenERP
3framework: openobject-server. All the tools are sub-commands of a single
4oe executable.
5"""
6import pkg_resources
7import sys
8import os
1import argparse9import argparse
2import textwrap10
311command_list = []
4from .call import Call12base_group = '%s.subcommands' % __name__
5from .client import Open, Show, ConsumeNothing, ConsumeMemory, LeakMemory, ConsumeCPU13toplevel_mark = '==toplevel=='
6from .benchmarks import Bench, BenchRead, BenchFieldsViewGet, BenchDummy, BenchLogin14
7from .bench_sale_mrp import BenchSaleMrp15for group, entry_points in pkg_resources.get_entry_map(pkg_resources.get_distribution('openerp-command')).items():
8from . import common16 if group.startswith(base_group):
917 container = group[len(base_group)+1:] or None
10from . import conf # Not really server-side (in the `for` below).18 for name, entry_point in entry_points.items():
11from . import drop19 try:
12from . import initialize20 init_parser = entry_point.load()
13from . import model21 pkg = sys.modules[init_parser.__module__.rsplit('.', 1)[0]]
14from . import module22 description = unicode(sys.modules[init_parser.__module__].__doc__).strip()
15from . import read23 command_list.append( (name.replace('_', '-'), container, description, init_parser, pkg) )
16from . import run_tests24 except ImportError, e:
17from . import scaffold25 sys.stderr.write("Invalid entry point: %s" % e.message + os.linesep)
18from . import uninstall
19from . import update
20
21command_list_server = (conf, drop, initialize, model, module, read, run_tests,
22 scaffold, uninstall, update, )
23
24command_list_client = (Call, Open, Show, ConsumeNothing, ConsumeMemory,
25 LeakMemory, ConsumeCPU, Bench, BenchRead,
26 BenchFieldsViewGet, BenchDummy, BenchLogin,
27 BenchSaleMrp, )
2826
29def main_parser():27def main_parser():
28
29 def format_command(name, description):
30 text = [name]
31 if description:
32 text.extend([
33 ":", os.linesep,
34 " " + description.strip().replace("\n", "\n "),
35 ])
36 return "".join(text)
37
30 parser = argparse.ArgumentParser(38 parser = argparse.ArgumentParser(
31 usage=argparse.SUPPRESS,39 usage=argparse.SUPPRESS,
32 description=textwrap.fill(textwrap.dedent("""\40 description=__doc__,
33 OpenERP Command provides a set of command-line tools around
34 the OpenERP framework: openobject-server. All the tools are
35 sub-commands of a single oe executable.""")),
36 epilog="""Use <command> --help to get information about the command.""",41 epilog="""Use <command> --help to get information about the command.""",
37 formatter_class=argparse.RawDescriptionHelpFormatter,42 formatter_class=argparse.RawDescriptionHelpFormatter,
38 )43 )
39 description = []44 command_list.sort(key=lambda x:(x[1], x[0]))
40 for x in command_list_server:45 container_help = {}
41 description.append(x.__name__[len(__package__)+1:])46 for name, container, description, _, pkg in command_list:
42 if x.__doc__:47 # Update parent subparser help_text
43 description.extend([48 container = container or toplevel_mark
44 ":\n",49 if container in container_help or container is toplevel_mark:
45 textwrap.fill(str(x.__doc__).strip(),50 help_text = container_help.setdefault(container, [])
46 subsequent_indent=' ',51 else:
47 initial_indent=' '),52 parent_container = container.rsplit('.', 1)[0] if '.' in container else toplevel_mark
48 ])53 container_name = container.rsplit('.', 1)[1] if '.' in container else container
49 description.append("\n\n")54 parent_text = container_help.setdefault(parent_container, [])
50 subparsers = parser.add_subparsers(55 parent_text.extend([format_command(container_name, pkg.__doc__), os.linesep * 2])
51 title="Available commands",56 # Make subcommand help
52 help=argparse.SUPPRESS,57 help_text = container_help.setdefault(container or toplevel_mark, [])
53 description="".join(description[:-1]),58 help_text.extend([format_command(name, description), os.linesep * 2])
54 )59 subparsers = {toplevel_mark : parser.add_subparsers(
55 # Server-side commands.60 title="Available commands",
56 for x in command_list_server:61 help=argparse.SUPPRESS,
57 x.add_parser(subparsers)62 description="".join(container_help[toplevel_mark][:-1])),
58 # Client-side commands. TODO one per .py file.63 }
59 for x in command_list_client:64 for _, container, _, _, pkg in command_list:
60 x(subparsers)65 if container is not None and container not in subparsers:
66 path, name = container.rsplit('.', 1) if '.' in container else (toplevel_mark, container)
67 parent_subparser = subparsers[path]
68 parent_parser = parent_subparser.add_parser(name, description=pkg.__doc__,
69 formatter_class=argparse.RawDescriptionHelpFormatter)
70 subparsers[container] = parent_parser.add_subparsers(
71 title="Available commands",
72 help=argparse.SUPPRESS,
73 description="".join(container_help[container][:-1]),
74 )
75 for name, container, description, init_parser, _ in command_list:
76 subparser = subparsers[container or toplevel_mark]
77 command_parser = subparser.add_parser(name, description=description)
78 init_parser(command_parser)
61 return parser79 return parser
80
81def make_entry_points(path='.'):
82 import pkgutil
83 import pprint
84 res = {}
85 for importer, fullname, is_pkg in pkgutil.walk_packages(path):
86 try:
87 module_path = fullname.split('.')
88 prefix, name = module_path[0], module_path[-1]
89 if not prefix == __name__:
90 continue
91 module_container = ".".join(['openerpcommand','subcommands']+module_path[1:-1])
92 if is_pkg:
93 # Needed to display importation errors
94 __import__(fullname, globals(), locals(), [], -1)
95 else:
96 module = __import__(fullname, globals(), locals(), [name.split('.')[-1]], -1)
97 entry_point_string = "%s = %s:init_parser" % (name, fullname)
98 if not hasattr(module, 'init_parser'):
99 print "#", entry_point_string
100 else:
101 res.setdefault(module_container, []).append( entry_point_string )
102 except ValueError:
103 pass
104 pprint.pprint(res, indent=4)
62105
=== modified file 'openerpcommand/addons/bench_sale_mrp/data.yml'
--- openerpcommand/addons/bench_sale_mrp/data.yml 2012-02-06 14:54:54 +0000
+++ openerpcommand/addons/bench_sale_mrp/data.yml 2012-11-27 15:42:19 +0000
@@ -18,7 +18,7 @@
18 seller_delay: '1'18 seller_delay: '1'
19 seller_ids:19 seller_ids:
20 - delay: 120 - delay: 1
21 name: base.res_partner_agrolait21 name: base.res_partner_2
22 min_qty: 2.022 min_qty: 2.0
23 qty: 5.023 qty: 5.0
24 standard_price: 189.024 standard_price: 189.0
2525
=== added directory 'openerpcommand/benchmark'
=== added file 'openerpcommand/benchmark/__init__.py'
--- openerpcommand/benchmark/__init__.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/benchmark/__init__.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,111 @@
1"""
2Base class for benchmark
3"""
4import sys
5import hashlib
6import multiprocessing
7import time
8
9from openerpcommand.common import Client
10
11class Benchmark(Client):
12 """
13 Base class for concurrent benchmarks. The measure_once() method must be
14 overriden.
15
16 Each sub-benchmark will be run in its own process then a report is done
17 with all the results (shared with the main process using a
18 `multiprocessing.Array`).
19 """
20
21 def __init__(self, parser):
22 super(Benchmark, self).__init__(parser)
23 self.parser.add_argument('-n', '--samples', metavar='SAMPLES',
24 default=100, help='number of measurements to take.')
25 # TODO if -n <samples>s is given (instead of -n <samples>), run the
26 # benchmark for <samples> seconds and return the number of iterations.
27 self.parser.add_argument('-o', '--output', metavar='FILE',
28 required=True, help='path to save the generated report.')
29 self.parser.add_argument('--append', action='store_true',
30 default=False, help='append the report to an existing file.')
31 self.parser.add_argument('-j', '--jobs', metavar='JOBS',
32 default=1, help='number of concurrent workers')
33 self.parser.add_argument('--seed', metavar='SEED',
34 default=0, help='a value to ensure different runs can create unique data.')
35 self.worker = -1
36
37 def work(self, iarr=None):
38 if iarr:
39 # If an array is given, it means we are a worker process...
40 self.work_slave(iarr)
41 else:
42 # ... else we are the main process and we will spawn workers,
43 # passing them an array.
44 self.work_master()
45
46 def work_master(self):
47 N = int(self.args.samples)
48 self.arrs = [(i, multiprocessing.Array('f', range(N)))
49 for i in xrange(int(self.args.jobs))]
50 ps = [multiprocessing.Process(target=self.run, args=(arr,))
51 for arr in self.arrs]
52 [p.start() for p in ps]
53 [p.join() for p in ps]
54
55 self.report_html()
56
57 def work_slave(self, iarr):
58 j, arr = iarr
59 self.worker = j
60 N = int(self.args.samples)
61 total_t0 = time.time()
62 for i in xrange(N):
63 t0 = time.time()
64 self.measure_once(i)
65 t1 = time.time()
66 arr[i] = t1 - t0
67 print >> sys.stdout, '\r%s' % ('|' * (i * 60 / N)),
68 print >> sys.stdout, '%s %s%%' % \
69 (' ' * (60 - (i * 60 / N)), int(float(i+1)/N*100)),
70 sys.stdout.flush()
71 total_t1 = time.time()
72 print '\nDone in %ss.' % (total_t1 - total_t0)
73
74 def report_html(self):
75 series = []
76 for arr in self.arrs:
77 serie = """{
78 data: %s,
79 points: { show: true }
80 }""" % ([[x, i] for i, x in enumerate(arr)],)
81 series.append(serie)
82 chart_id = hashlib.md5(" ".join(sys.argv)).hexdigest()
83 HEADER = """<!doctype html>
84<title>Benchmarks</title>
85<meta charset=utf-8>
86<script type="text/javascript" src="js/jquery.min.js"></script>
87<script type="text/javascript" src="js/jquery.flot.js"></script>
88"""
89
90 CONTENT = """<h1>%s</h1>
91%s
92<div id='chart_%s' style='width:400px;height:300px;'>...</div>
93<script type="text/javascript">
94$.plot($("#chart_%s"), [%s],
95 {yaxis: { ticks: false }});
96</script>""" % (self.bench_name, ' '.join(sys.argv), chart_id, chart_id,
97 ','.join(series))
98 if self.args.append:
99 with open(self.args.output, 'a') as f:
100 f.write(CONTENT,)
101 else:
102 with open(self.args.output, 'w') as f:
103 f.write(HEADER + CONTENT,)
104
105 def measure_once(self, i):
106 """
107 The `measure_once` method is called --jobs times. A `i` argument is
108 supplied to allow to create unique values for each execution (e.g. to
109 supply fresh identifiers to a `create` method.
110 """
111 pass
0112
=== added file 'openerpcommand/benchmark/dummy.py'
--- openerpcommand/benchmark/dummy.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/benchmark/dummy.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,18 @@
1"""
2Dummy (call test.limits.model.consume_nothing()).
3"""
4from openerpcommand.benchmark import Benchmark
5
6class Dummy(Benchmark):
7 bench_name = 'test.limits.model.consume_nothing()'
8
9 def __init__(self, parser):
10 super(Dummy, self).__init__(parser)
11 self.parser.add_argument('-a', '--args', metavar='ARGS',
12 default='', help='some arguments to serialize')
13
14 def measure_once(self, i):
15 self.execute('test.limits.model', 'consume_nothing')
16
17def init_parser(parser):
18 Dummy(parser)
019
=== added file 'openerpcommand/benchmark/fields_view_get.py'
--- openerpcommand/benchmark/fields_view_get.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/benchmark/fields_view_get.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,20 @@
1"""
2Read a record's fields and view architecture repeatedly.
3"""
4from openerpcommand.benchmark import Benchmark
5
6class FieldsViewGet(Benchmark):
7 bench_name = 'res.users.fields_view_get(1)'
8
9 def __init__(self, parser):
10 super(FieldsViewGet, self).__init__(parser)
11 self.parser.add_argument('-m', '--model', metavar='MODEL',
12 required=True, help='the model')
13 self.parser.add_argument('-i', '--id', metavar='RECORDID',
14 required=True, help='the record id')
15
16 def measure_once(self, i):
17 self.execute(self.args.model, 'fields_view_get', self.args.id)
18
19def init_parser(parser):
20 FieldsViewGet(parser)
021
=== added file 'openerpcommand/benchmark/login.py'
--- openerpcommand/benchmark/login.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/benchmark/login.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,13 @@
1"""
2Login (update res_users.date).
3"""
4from openerpcommand.benchmark import Benchmark
5
6class Login(Benchmark):
7 bench_name = 'res.users.login(1)'
8
9 def measure_once(self, i):
10 self.common_proxy.login(self.database, self.user, self.password)
11
12def init_parser(parser):
13 Login(parser)
014
=== added file 'openerpcommand/benchmark/read.py'
--- openerpcommand/benchmark/read.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/benchmark/read.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,20 @@
1"""
2Define a base class for client-side benchmarking.
3"""
4from openerpcommand.benchmark import Benchmark
5
6class Read(Benchmark):
7 bench_name = 'res.users.read(1)'
8
9 def __init__(self, parser):
10 super(Read, self).__init__(parser)
11 self.parser.add_argument('-m', '--model', metavar='MODEL',
12 required=True, help='the model')
13 self.parser.add_argument('-i', '--id', metavar='RECORDID',
14 required=True, help='the record id')
15
16 def measure_once(self, i):
17 self.execute(self.args.model, 'read', [self.args.id], [])
18
19def init_parser(parser):
20 Read(parser)
021
=== renamed file 'openerpcommand/bench_sale_mrp.py' => 'openerpcommand/benchmark/sale_mrp.py'
--- openerpcommand/bench_sale_mrp.py 2012-02-06 14:54:54 +0000
+++ openerpcommand/benchmark/sale_mrp.py 2012-11-27 15:42:19 +0000
@@ -1,23 +1,17 @@
1"""1"""\
2Benchmark based on the `sale_mrp` addons (in `sale_mrp/test/sale_mrp.yml`).2Similar to `sale_mrp/test/sale_mrp.yml`.
3"""
43
4This benchmarks the OpenERP server `sale_mrp` module by creating and
5confirming a sale order. As it creates data in the server, it is necessary
6to ensure unique names for the newly created data. You can use the --seed
7argument to give a lower bound to those names. (The number of generated
8names is JOBS * SAMPLES.)
9"""
5import time10import time
611
7from .benchmarks import Bench12from openerpcommand.benchmark import Benchmark
813
9class BenchSaleMrp(Bench):14class SaleMrp(Benchmark):
10 """\
11 Similar to `sale_mrp/test/sale_mrp.yml`.
12
13 This benchmarks the OpenERP server `sale_mrp` module by creating and
14 confirming a sale order. As it creates data in the server, it is necessary
15 to ensure unique names for the newly created data. You can use the --seed
16 argument to give a lower bound to those names. (The number of generated
17 names is --jobs * --samples.)
18 """
19
20 command_name = 'bench-sale-mrp'
21 bench_name = '`sale_mrp/test/sale_mrp.yml`'15 bench_name = '`sale_mrp/test/sale_mrp.yml`'
2216
23 def measure_once(self, i):17 def measure_once(self, i):
@@ -33,7 +27,7 @@
33 res_partner_4 = self.execute('ir.model.data', 'get_object_reference', 'base', 'res_partner_4')[1]27 res_partner_4 = self.execute('ir.model.data', 'get_object_reference', 'base', 'res_partner_4')[1]
34 res_partner_address_7 = self.execute('ir.model.data', 'get_object_reference', 'base', 'res_partner_address_7')[1]28 res_partner_address_7 = self.execute('ir.model.data', 'get_object_reference', 'base', 'res_partner_address_7')[1]
35 list0 = self.execute('ir.model.data', 'get_object_reference', 'product', 'list0')[1]29 list0 = self.execute('ir.model.data', 'get_object_reference', 'product', 'list0')[1]
36 shop = self.execute('ir.model.data', 'get_object_reference', 'sale', 'shop')[1]30 shop = self.execute('ir.model.data', 'get_object_reference', 'sale', 'sale_shop_1')[1]
3731
38 # Create a sale order for the product `Slider Mobile`.32 # Create a sale order for the product `Slider Mobile`.
39 data = {33 data = {
@@ -66,3 +60,5 @@
66 # Confirm the sale order.60 # Confirm the sale order.
67 self.object_proxy.exec_workflow(self.database, self.uid, self.password, 'sale.order', 'order_confirm', sale_order_id, {})61 self.object_proxy.exec_workflow(self.database, self.uid, self.password, 'sale.order', 'order_confirm', sale_order_id, {})
6862
63def init_parser(parser):
64 SaleMrp(parser)
6965
=== removed file 'openerpcommand/benchmarks.py'
--- openerpcommand/benchmarks.py 2012-07-23 09:51:09 +0000
+++ openerpcommand/benchmarks.py 1970-01-01 00:00:00 +0000
@@ -1,166 +0,0 @@
1"""
2Define a base class for client-side benchmarking.
3"""
4import hashlib
5import multiprocessing
6import sys
7import time
8
9from .client import Client
10
11class Bench(Client):
12 """
13 Base class for concurrent benchmarks. The measure_once() method must be
14 overriden.
15
16 Each sub-benchmark will be run in its own process then a report is done
17 with all the results (shared with the main process using a
18 `multiprocessing.Array`).
19 """
20
21 def __init__(self, subparsers=None):
22 super(Bench, self).__init__(subparsers)
23 self.parser.add_argument('-n', '--samples', metavar='INT',
24 default=100, help='number of measurements to take')
25 # TODO if -n <int>s is given (instead of -n <int>), run the
26 # benchmark for <int> seconds and return the number of iterations.
27 self.parser.add_argument('-o', '--output', metavar='PATH',
28 required=True, help='path to save the generated report')
29 self.parser.add_argument('--append', action='store_true',
30 default=False, help='append the report to an existing file')
31 self.parser.add_argument('-j', '--jobs', metavar='JOBS',
32 default=1, help='number of concurrent workers')
33 self.parser.add_argument('--seed', metavar='SEED',
34 default=0, help='a value to ensure different runs can create unique data')
35 self.worker = -1
36
37 def work(self, iarr=None):
38 if iarr:
39 # If an array is given, it means we are a worker process...
40 self.work_slave(iarr)
41 else:
42 # ... else we are the main process and we will spawn workers,
43 # passing them an array.
44 self.work_master()
45
46 def work_master(self):
47 N = int(self.args.samples)
48 self.arrs = [(i, multiprocessing.Array('f', range(N)))
49 for i in xrange(int(self.args.jobs))]
50 ps = [multiprocessing.Process(target=self.run, args=(arr,))
51 for arr in self.arrs]
52 [p.start() for p in ps]
53 [p.join() for p in ps]
54
55 self.report_html()
56
57 def work_slave(self, iarr):
58 j, arr = iarr
59 self.worker = j
60 N = int(self.args.samples)
61 total_t0 = time.time()
62 for i in xrange(N):
63 t0 = time.time()
64 self.measure_once(i)
65 t1 = time.time()
66 arr[i] = t1 - t0
67 print >> sys.stdout, '\r%s' % ('|' * (i * 60 / N)),
68 print >> sys.stdout, '%s %s%%' % \
69 (' ' * (60 - (i * 60 / N)), int(float(i+1)/N*100)),
70 sys.stdout.flush()
71 total_t1 = time.time()
72 print '\nDone in %ss.' % (total_t1 - total_t0)
73
74 def report_html(self):
75 series = []
76 for arr in self.arrs:
77 serie = """{
78 data: %s,
79 points: { show: true }
80 }""" % ([[x, i] for i, x in enumerate(arr)],)
81 series.append(serie)
82 chart_id = hashlib.md5(" ".join(sys.argv)).hexdigest()
83 HEADER = """<!doctype html>
84<title>Benchmarks</title>
85<meta charset=utf-8>
86<script type="text/javascript" src="js/jquery.min.js"></script>
87<script type="text/javascript" src="js/jquery.flot.js"></script>
88"""
89
90 CONTENT = """<h1>%s</h1>
91%s
92<div id='chart_%s' style='width:400px;height:300px;'>...</div>
93<script type="text/javascript">
94$.plot($("#chart_%s"), [%s],
95 {yaxis: { ticks: false }});
96</script>""" % (self.bench_name, ' '.join(sys.argv), chart_id, chart_id,
97 ','.join(series))
98 if self.args.append:
99 with open(self.args.output, 'a') as f:
100 f.write(CONTENT,)
101 else:
102 with open(self.args.output, 'w') as f:
103 f.write(HEADER + CONTENT,)
104
105 def measure_once(self, i):
106 """
107 The `measure_once` method is called --jobs times. A `i` argument is
108 supplied to allow to create unique values for each execution (e.g. to
109 supply fresh identifiers to a `create` method.
110 """
111 pass
112
113class BenchRead(Bench):
114 """Read a record repeatedly."""
115
116 command_name = 'bench-read'
117 bench_name = 'res.users.read(1)'
118
119 def __init__(self, subparsers=None):
120 super(BenchRead, self).__init__(subparsers)
121 self.parser.add_argument('-m', '--model', metavar='MODEL',
122 required=True, help='the model')
123 self.parser.add_argument('-i', '--id', metavar='RECORDID',
124 required=True, help='the record id')
125
126 def measure_once(self, i):
127 self.execute(self.args.model, 'read', [self.args.id], [])
128
129class BenchFieldsViewGet(Bench):
130 """Read a record's fields and view architecture repeatedly."""
131
132 command_name = 'bench-view'
133 bench_name = 'res.users.fields_view_get(1)'
134
135 def __init__(self, subparsers=None):
136 super(BenchFieldsViewGet, self).__init__(subparsers)
137 self.parser.add_argument('-m', '--model', metavar='MODEL',
138 required=True, help='the model')
139 self.parser.add_argument('-i', '--id', metavar='RECORDID',
140 required=True, help='the record id')
141
142 def measure_once(self, i):
143 self.execute(self.args.model, 'fields_view_get', self.args.id)
144
145class BenchDummy(Bench):
146 """Dummy (call test.limits.model.consume_nothing())."""
147
148 command_name = 'bench-dummy'
149 bench_name = 'test.limits.model.consume_nothing()'
150
151 def __init__(self, subparsers=None):
152 super(BenchDummy, self).__init__(subparsers)
153 self.parser.add_argument('-a', '--args', metavar='ARGS',
154 default='', help='some arguments to serialize')
155
156 def measure_once(self, i):
157 self.execute('test.limits.model', 'consume_nothing')
158
159class BenchLogin(Bench):
160 """Login (update res_users.date)."""
161
162 command_name = 'bench-login'
163 bench_name = 'res.users.login(1)'
164
165 def measure_once(self, i):
166 self.common_proxy.login(self.database, self.user, self.password)
1670
=== modified file 'openerpcommand/call.py'
--- openerpcommand/call.py 2012-02-10 16:19:48 +0000
+++ openerpcommand/call.py 2012-11-27 15:42:19 +0000
@@ -1,29 +1,18 @@
1"""1"""
2Call an arbitrary model's method.2Call an arbitrary model's method.
3
4Example:
5 > oe call res.users.read '[1, 3]' '[]' -u 1 -p admin
3"""6"""
4import ast7import ast
5import os
6import pprint8import pprint
7import sys9import sys
8import time10
9import xmlrpclib11from openerpcommand.common import Client
1012
11import client13class Call(Client):
1214 def __init__(self, parser):
13class Call(client.Client):15 super(Call, self).__init__(parser)
14 """\
15 Call an arbitrary model's method.
16
17 Example:
18 > oe call res.users.read '[1, 3]' '[]' -u 1 -p admin
19 """
20 # TODO The above docstring is completely borked in the
21 # --help message.
22
23 command_name = 'call'
24
25 def __init__(self, subparsers=None):
26 super(Call, self).__init__(subparsers)
27 self.parser.add_argument('call', metavar='MODEL.METHOD',16 self.parser.add_argument('call', metavar='MODEL.METHOD',
28 help='the model and the method to call, using the '17 help='the model and the method to call, using the '
29 '<model>.<method> format.')18 '<model>.<method> format.')
@@ -42,3 +31,5 @@
42 x = self.execute(model, method, *args)31 x = self.execute(model, method, *args)
43 pprint.pprint(x, indent=4)32 pprint.pprint(x, indent=4)
4433
34def init_parser(parser):
35 Call(parser)
4536
=== removed file 'openerpcommand/client.py'
--- openerpcommand/client.py 2012-01-20 15:41:17 +0000
+++ openerpcommand/client.py 1970-01-01 00:00:00 +0000
@@ -1,137 +0,0 @@
1"""
2Define a few common arguments for client-side command-line tools.
3"""
4import os
5import sys
6import time
7import xmlrpclib
8
9import common
10
11class Client(common.Command):
12 """
13 Base class for XML-RPC command-line clients. It must be inherited and the
14 work() method overriden.
15 """
16
17 def __init__(self, subparsers=None):
18 super(Client, self).__init__(subparsers)
19 required_or_default = common.required_or_default
20 self.parser.add_argument('-H', '--host', metavar='HOST',
21 **required_or_default('HOST', 'the server host'))
22 self.parser.add_argument('-P', '--port', metavar='PORT',
23 **required_or_default('PORT', 'the server port'))
24
25 def execute(self, *args):
26 return self.object_proxy.execute(self.database, self.uid, self.password, *args)
27
28 def initialize(self):
29 self.host = self.args.host
30 self.port = int(self.args.port)
31 self.database = self.args.database
32 self.user = self.args.user
33 self.password = self.args.password
34
35 self.url = 'http://%s:%d/xmlrpc/' % (self.host, self.port)
36 self.common_proxy = xmlrpclib.ServerProxy(self.url + 'common')
37 self.object_proxy = xmlrpclib.ServerProxy(self.url + 'object')
38
39 try:
40 self.uid = int(self.user)
41 except ValueError, e:
42 self.uid = self.common_proxy.login(self.database, self.user, self.password)
43
44 def run(self, *args):
45 self.initialize()
46 self.work(*args)
47
48 def work(self, *args):
49 pass
50
51class Open(Client):
52 """Get the web client's URL to view a specific model."""
53
54 command_name = 'open'
55
56 def __init__(self, subparsers=None):
57 super(Open, self).__init__(subparsers)
58 self.parser.add_argument('-m', '--model', metavar='MODEL',
59 required=True, help='the view type')
60 self.parser.add_argument('-v', '--view-mode', metavar='VIEWMODE',
61 default='tree', help='the view mode')
62
63 def work(self):
64 ids = self.execute('ir.actions.act_window', 'search', [
65 ('res_model', '=', self.args.model),
66 ('view_mode', 'like', self.args.view_mode),
67 ])
68 xs = self.execute('ir.actions.act_window', 'read', ids, [])
69 for x in xs:
70 print x['id'], x['name']
71 d = {}
72 d['host'] = self.host
73 d['port'] = self.port
74 d['action_id'] = x['id']
75 print " http://%(host)s:%(port)s/web/webclient/home#action_id=%(action_id)s" % d
76
77class Show(Client):
78 """Display a record."""
79
80 command_name = 'show'
81
82 def __init__(self, subparsers=None):
83 super(Show, self).__init__(subparsers)
84 self.parser.add_argument('-m', '--model', metavar='MODEL',
85 required=True, help='the model')
86 self.parser.add_argument('-i', '--id', metavar='RECORDID',
87 required=True, help='the record id')
88
89 def work(self):
90 xs = self.execute(self.args.model, 'read', [self.args.id], [])
91 if xs:
92 x = xs[0]
93 print x['name']
94 else:
95 print "Record not found."
96
97class ConsumeNothing(Client):
98 """Call test.limits.model.consume_nothing()."""
99
100 command_name = 'consume-nothing'
101
102 def work(self):
103 xs = self.execute('test.limits.model', 'consume_nothing')
104
105class ConsumeMemory(Client):
106 """Call test.limits.model.consume_memory()."""
107
108 command_name = 'consume-memory'
109
110 def __init__(self, subparsers=None):
111 super(ConsumeMemory, self).__init__(subparsers)
112 self.parser.add_argument('--size', metavar='SIZE',
113 required=True, help='size of the list to allocate')
114
115 def work(self):
116 xs = self.execute('test.limits.model', 'consume_memory', int(self.args.size))
117
118class LeakMemory(ConsumeMemory):
119 """Call test.limits.model.leak_memory()."""
120
121 command_name = 'leak-memory'
122
123 def work(self):
124 xs = self.execute('test.limits.model', 'leak_memory', int(self.args.size))
125
126class ConsumeCPU(Client):
127 """Call test.limits.model.consume_cpu_time()."""
128
129 command_name = 'consume-cpu'
130
131 def __init__(self, subparsers=None):
132 super(ConsumeCPU, self).__init__(subparsers)
133 self.parser.add_argument('--seconds', metavar='INT',
134 required=True, help='how much CPU time to consume')
135
136 def work(self):
137 xs = self.execute('test.limits.model', 'consume_cpu_time', int(self.args.seconds))
1380
=== modified file 'openerpcommand/common.py'
--- openerpcommand/common.py 2012-10-30 15:11:48 +0000
+++ openerpcommand/common.py 2012-11-27 15:42:19 +0000
@@ -1,9 +1,9 @@
1"""1"""
2Define a few common arguments for server-side command-line tools.2Define a few common arguments for server-side (Command) and client-side (Client) command-line tools.
3"""3"""
4import argparse
5import os4import os
6import sys5import sys
6import xmlrpclib
77
8def add_addons_argument(parser):8def add_addons_argument(parser):
9 """9 """
@@ -37,28 +37,24 @@
37 a mandatory argument.37 a mandatory argument.
38 """38 """
39 if os.environ.get('OPENERP_' + name.upper()):39 if os.environ.get('OPENERP_' + name.upper()):
40 d = {'default': os.environ['OPENERP_' + name.upper()]}40 d = {'default': os.environ['OPENERP_' + name.upper()]}
41 else:41 else:
42 d = {'required': True}42 d = {'required': True}
43 d['help'] = h + '. The environment variable OPENERP_' + \43 d['help'] = h + '. The environment variable OPENERP_' + \
44 name.upper() + ' can be used instead.'44 name.upper() + ' can be used instead.'
45 return d45 return d
4646
47def expand_path(path):
48 return os.path.expanduser(os.path.expandvars(path))
49
47class Command(object):50class Command(object):
48 """51 """
49 Base class to create command-line tools. It must be inherited and the52 Base class to create command-line tools. It must be inherited and the
50 run() method overriden.53 run() method overriden.
51 """54 """
5255
53 command_name = 'stand-alone'56 def __init__(self, parser):
5457 self.parser = parser
55 def __init__(self, subparsers=None):
56 if subparsers:
57 self.parser = parser = subparsers.add_parser(self.command_name,
58 description=self.__class__.__doc__)
59 else:
60 self.parser = parser = argparse.ArgumentParser(
61 description=self.__class__.__doc__)
6258
63 parser.add_argument('-d', '--database', metavar='DATABASE',59 parser.add_argument('-d', '--database', metavar='DATABASE',
64 **required_or_default('DATABASE', 'the database to connect to'))60 **required_or_default('DATABASE', 'the database to connect to'))
@@ -86,3 +82,42 @@
86 command = cls()82 command = cls()
87 args = command.parser.parse_args()83 args = command.parser.parse_args()
88 args.run(args)84 args.run(args)
85
86class Client(Command):
87 """
88 Base class for XML-RPC command-line clients. It must be inherited and the
89 work() method overriden.
90 """
91
92 def __init__(self, parser):
93 super(Client, self).__init__(parser)
94 self.parser.add_argument('-H', '--host', metavar='HOST',
95 **required_or_default('HOST', 'the server host'))
96 self.parser.add_argument('-P', '--port', metavar='PORT',
97 **required_or_default('PORT', 'the server port'))
98
99 def execute(self, *args):
100 return self.object_proxy.execute(self.database, self.uid, self.password, *args)
101
102 def initialize(self):
103 self.host = self.args.host
104 self.port = int(self.args.port)
105 self.database = self.args.database
106 self.user = self.args.user
107 self.password = self.args.password
108
109 self.url = 'http://%s:%d/xmlrpc/' % (self.host, self.port)
110 self.common_proxy = xmlrpclib.ServerProxy(self.url + 'common')
111 self.object_proxy = xmlrpclib.ServerProxy(self.url + 'object')
112
113 try:
114 self.uid = int(self.user)
115 except ValueError, e:
116 self.uid = self.common_proxy.login(self.database, self.user, self.password)
117
118 def run(self, *args):
119 self.initialize()
120 self.work(*args)
121
122 def work(self, *args):
123 pass
89124
=== modified file 'openerpcommand/conf.py'
--- openerpcommand/conf.py 2012-10-31 11:26:36 +0000
+++ openerpcommand/conf.py 2012-11-27 15:42:19 +0000
@@ -1,13 +1,11 @@
1"""1"""
2Display the currently used configuration. The configuration for any2Display the currently used configuration. The configuration for any
3sub-command is normally given by options. But some options can be specified3sub-command is normally given by options. But some options can be
4using environment variables. This sub-command shows those variables.4specified using environment variables. This sub-command shows those
5A `set` sub-command should be provided when the configuration is in a real5variables. A `set` sub-command should be provided when the configuration
6configuration file instead of environment variables.6is in a real configuration file instead of environment variables.
7"""7"""
8import os8import os
9import sys
10import textwrap
119
12def run(args):10def run(args):
13 for x in ('database', 'addons', 'host', 'port'):11 for x in ('database', 'addons', 'host', 'port'):
@@ -18,8 +16,5 @@
18 print '%s: <not set>' % (x, )16 print '%s: <not set>' % (x, )
19 os.environ['OPENERP_DATABASE'] = 'yeah'17 os.environ['OPENERP_DATABASE'] = 'yeah'
2018
21def add_parser(subparsers):19def init_parser(parser):
22 parser = subparsers.add_parser('conf',
23 description='Display the currently used configuration.')
24
25 parser.set_defaults(run=run)20 parser.set_defaults(run=run)
2621
=== added file 'openerpcommand/consume_cpu.py'
--- openerpcommand/consume_cpu.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/consume_cpu.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,16 @@
1"""
2Call test.limits.model.consume_cpu_time().
3"""
4from openerpcommand.common import Client
5
6class ConsumeCPU(Client):
7 def __init__(self, parser):
8 super(ConsumeCPU, self).__init__(parser)
9 self.parser.add_argument('--seconds', metavar='INT',
10 required=True, help='how much CPU time to consume')
11
12 def work(self):
13 xs = self.execute('test.limits.model', 'consume_cpu_time', int(self.args.seconds))
14
15def init_parser(parser):
16 ConsumeCPU(parser)
017
=== added file 'openerpcommand/consume_memory.py'
--- openerpcommand/consume_memory.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/consume_memory.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,16 @@
1"""
2Call test.limits.model.consume_memory().
3"""
4from openerpcommand.common import Client
5
6class ConsumeMemory(Client):
7 def __init__(self, parser):
8 super(ConsumeMemory, self).__init__(parser)
9 self.parser.add_argument('--size', metavar='SIZE',
10 required=True, help='size of the list to allocate')
11
12 def work(self):
13 xs = self.execute('test.limits.model', 'consume_memory', int(self.args.size))
14
15def init_parser(parser):
16 ConsumeMemory(parser)
017
=== added file 'openerpcommand/consume_nothing.py'
--- openerpcommand/consume_nothing.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/consume_nothing.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,11 @@
1"""
2Call test.limits.model.consume_nothing().
3"""
4from openerpcommand.common import Client
5
6class ConsumeNothing(Client):
7 def work(self):
8 xs = self.execute('test.limits.model', 'consume_nothing')
9
10def init_parser(parser):
11 ConsumeNothing(parser)
012
=== modified file 'openerpcommand/drop.py'
--- openerpcommand/drop.py 2012-08-23 09:25:05 +0000
+++ openerpcommand/drop.py 2012-11-27 15:42:19 +0000
@@ -1,8 +1,7 @@
1"""1"""
2Drop a database.2Drop a database.
3"""3"""
44from openerpcommand import common
5import common
65
7# TODO turn template1 in a parameter6# TODO turn template1 in a parameter
8# This should be exposed from openerp (currently in7# This should be exposed from openerp (currently in
@@ -36,10 +35,7 @@
36 assert args.database35 assert args.database
37 drop_database(args.database)36 drop_database(args.database)
3837
39def add_parser(subparsers):38def init_parser(parser):
40 parser = subparsers.add_parser('drop',
41 description='Drop a database.')
42 parser.add_argument('-d', '--database', metavar='DATABASE',39 parser.add_argument('-d', '--database', metavar='DATABASE',
43 **common.required_or_default('DATABASE', 'the database to create'))40 **common.required_or_default('DATABASE', 'the database to create'))
44
45 parser.set_defaults(run=run)41 parser.set_defaults(run=run)
4642
=== modified file 'openerpcommand/initialize.py'
--- openerpcommand/initialize.py 2012-11-05 17:34:39 +0000
+++ openerpcommand/initialize.py 2012-11-27 15:42:19 +0000
@@ -1,10 +1,9 @@
1"""1"""
2Install OpenERP on a new (by default) database.2Install OpenERP on a new (by default) database.
3Create and initialize a new OpenERP database.
3"""4"""
4import os
5import sys5import sys
66from openerpcommand import common
7import common
87
9def install_openerp(database_name, create_database_flag, module_names):8def install_openerp(database_name, create_database_flag, module_names):
10 import openerp9 import openerp
@@ -47,6 +46,10 @@
4746
48 config = openerp.tools.config47 config = openerp.tools.config
4948
49 if args.drop:
50 import drop
51 drop.drop_database(args.database)
52
50 if args.tests:53 if args.tests:
51 config['log_handler'] = [':TEST']54 config['log_handler'] = [':TEST']
52 config['test_enable'] = True55 config['test_enable'] = True
@@ -57,7 +60,7 @@
57 config['without_demo'] = True60 config['without_demo'] = True
5861
59 if args.addons:62 if args.addons:
60 args.addons = args.addons.split(':')63 args.addons = map(common.expand_path, args.addons.split(':'))
61 else:64 else:
62 args.addons = []65 args.addons = []
63 config['addons_path'] = ','.join(args.addons)66 config['addons_path'] = ','.join(args.addons)
@@ -77,11 +80,11 @@
77 if hasattr(registry, '_assertion_report'):80 if hasattr(registry, '_assertion_report'):
78 sys.exit(1 if registry._assertion_report.failures else 0)81 sys.exit(1 if registry._assertion_report.failures else 0)
7982
80def add_parser(subparsers):83def init_parser(parser):
81 parser = subparsers.add_parser('initialize',
82 description='Create and initialize a new OpenERP database.')
83 parser.add_argument('-d', '--database', metavar='DATABASE',84 parser.add_argument('-d', '--database', metavar='DATABASE',
84 **common.required_or_default('DATABASE', 'the database to create'))85 **common.required_or_default('DATABASE', 'the database to create'))
86 parser.add_argument('--drop', action='store_true',
87 default=False, help="Drop the database if exists")
85 common.add_addons_argument(parser)88 common.add_addons_argument(parser)
86 parser.add_argument('--module', metavar='MODULE', action='append',89 parser.add_argument('--module', metavar='MODULE', action='append',
87 help='specify a module to install'90 help='specify a module to install'
@@ -98,5 +101,4 @@
98 ' (use the `run-tests` command to choose specific'101 ' (use the `run-tests` command to choose specific'
99 ' tests to run against an existing database).'102 ' tests to run against an existing database).'
100 ' Demo data are installed.')103 ' Demo data are installed.')
101
102 parser.set_defaults(run=run)104 parser.set_defaults(run=run)
103105
=== added file 'openerpcommand/leak_memory.py'
--- openerpcommand/leak_memory.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/leak_memory.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,11 @@
1"""
2Call test.limits.model.leak_memory().
3"""
4from .consume_memory import ConsumeMemory
5
6class LeakMemory(ConsumeMemory):
7 def work(self):
8 xs = self.execute('test.limits.model', 'leak_memory', int(self.args.size))
9
10def init_parser(parser):
11 LeakMemory(parser)
012
=== modified file 'openerpcommand/model.py'
--- openerpcommand/model.py 2012-02-14 15:05:03 +0000
+++ openerpcommand/model.py 2012-11-27 15:42:19 +0000
@@ -1,7 +1,6 @@
1"""1"""
2Display information about a given model.2Display information about a given model for an existing database.
3"""3"""
4import os
5import sys4import sys
6import textwrap5import textwrap
76
@@ -46,9 +45,7 @@
46 if args.verbose and v.help:45 if args.verbose and v.help:
47 print textwrap.fill(v.help, initial_indent=' ', subsequent_indent=' ')46 print textwrap.fill(v.help, initial_indent=' ', subsequent_indent=' ')
4847
49def add_parser(subparsers):48def init_parser(parser):
50 parser = subparsers.add_parser('model',
51 description='Display information about a given model for an existing database.')
52 parser.add_argument('-d', '--database', metavar='DATABASE', required=True,49 parser.add_argument('-d', '--database', metavar='DATABASE', required=True,
53 help='the database to connect to')50 help='the database to connect to')
54 parser.add_argument('-m', '--model', metavar='MODEL', required=True,51 parser.add_argument('-m', '--model', metavar='MODEL', required=True,
5552
=== modified file 'openerpcommand/module.py'
--- openerpcommand/module.py 2012-08-23 09:25:05 +0000
+++ openerpcommand/module.py 2012-11-27 15:42:19 +0000
@@ -1,11 +1,12 @@
1"""1"""
2Show module information for a given database or from the file-system.2Show module information for a given database or from the file-system.
3Display modules known from a given database or on file-system.
3"""4"""
4import os5import os
5import sys6import sys
6import textwrap7import textwrap
78
8from . import common9from openerpcommand import common
910
10# TODO provide a --rpc flag to use XML-RPC (with a specific username) instead11# TODO provide a --rpc flag to use XML-RPC (with a specific username) instead
11# of server-side library.12# of server-side library.
@@ -16,7 +17,7 @@
16 config = openerp.tools.config17 config = openerp.tools.config
17 config['log_handler'] = [':CRITICAL']18 config['log_handler'] = [':CRITICAL']
18 if args.addons:19 if args.addons:
19 args.addons = args.addons.split(':')20 args.addons = map(common.expand_path, args.addons.split(':'))
20 else:21 else:
21 args.addons = []22 args.addons = []
22 config['addons_path'] = ','.join(args.addons)23 config['addons_path'] = ','.join(args.addons)
@@ -50,9 +51,7 @@
50 else:51 else:
51 print "No module found (database `%s`)." % (args.database,)52 print "No module found (database `%s`)." % (args.database,)
5253
53def add_parser(subparsers):54def init_parser(parser):
54 parser = subparsers.add_parser('module',
55 description='Display modules known from a given database or on file-system.')
56 parser.add_argument('-d', '--database', metavar='DATABASE',55 parser.add_argument('-d', '--database', metavar='DATABASE',
57 **common.required_or_default('DATABASE', 'the database to modify'))56 **common.required_or_default('DATABASE', 'the database to modify'))
58 common.add_addons_argument(parser)57 common.add_addons_argument(parser)
5958
=== added file 'openerpcommand/open.py'
--- openerpcommand/open.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/open.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,29 @@
1"""
2Get the web client's URL to view a specific model.
3"""
4from openerpcommand.common import Client
5
6class Open(Client):
7 def __init__(self, parser):
8 super(Open, self).__init__(parser)
9 self.parser.add_argument('-m', '--model', metavar='MODEL',
10 required=True, help='the view type')
11 self.parser.add_argument('-v', '--view-mode', metavar='VIEWMODE',
12 default='tree', help='the view mode')
13
14 def work(self):
15 ids = self.execute('ir.actions.act_window', 'search', [
16 ('res_model', '=', self.args.model),
17 ('view_mode', 'like', self.args.view_mode),
18 ])
19 xs = self.execute('ir.actions.act_window', 'read', ids, [])
20 for x in xs:
21 print x['id'], x['name']
22 d = {}
23 d['host'] = self.host
24 d['port'] = self.port
25 d['action_id'] = x['id']
26 print " http://%(host)s:%(port)s/web/webclient/home#action_id=%(action_id)s" % d
27
28def init_parser(parser):
29 Open(parser)
030
=== modified file 'openerpcommand/read.py'
--- openerpcommand/read.py 2012-11-05 17:34:39 +0000
+++ openerpcommand/read.py 2012-11-27 15:42:19 +0000
@@ -41,9 +41,7 @@
41 else:41 else:
42 print "Record not found."42 print "Record not found."
4343
44def add_parser(subparsers):44def init_parser(parser):
45 parser = subparsers.add_parser('read',
46 description='Display a record.')
47 parser.add_argument('-d', '--database', metavar='DATABASE', required=True,45 parser.add_argument('-d', '--database', metavar='DATABASE', required=True,
48 help='the database to connect to')46 help='the database to connect to')
49 parser.add_argument('-m', '--model', metavar='MODEL', required=True,47 parser.add_argument('-m', '--model', metavar='MODEL', required=True,
@@ -56,5 +54,4 @@
56 help='display less information')54 help='display less information')
57 parser.add_argument('-f', '--field', metavar='FIELD',55 parser.add_argument('-f', '--field', metavar='FIELD',
58 help='display information only for this particular field')56 help='display information only for this particular field')
59
60 parser.set_defaults(run=run)57 parser.set_defaults(run=run)
6158
=== modified file 'openerpcommand/run_tests.py'
--- openerpcommand/run_tests.py 2012-11-19 13:23:37 +0000
+++ openerpcommand/run_tests.py 2012-11-27 15:42:19 +0000
@@ -1,12 +1,13 @@
1"""1"""
2Execute the unittest2 tests available in OpenERP addons.2Execute the unittest2 tests available in OpenERP addons.
3Run the OpenERP server and/or addons tests.
3"""4"""
45
5import os6import os
6import sys7import sys
7import types8import types
89
9import common10from openerpcommand import common
1011
11def get_test_modules(module, submodule, explode):12def get_test_modules(module, submodule, explode):
12 """13 """
@@ -102,7 +103,7 @@
102 config['db_name'] = args.database103 config['db_name'] = args.database
103 config['addons_path'] = args.addons.replace(':',',')104 config['addons_path'] = args.addons.replace(':',',')
104 if args.addons:105 if args.addons:
105 args.addons = args.addons.split(':')106 args.addons = map(common.expand_path, args.addons.split(':'))
106 else:107 else:
107 args.addons = []108 args.addons = []
108 if args.sanity_checks and args.fast_suite:109 if args.sanity_checks and args.fast_suite:
@@ -169,9 +170,7 @@
169 for test_module in test_modules:170 for test_module in test_modules:
170 print ' ', test_module.__name__171 print ' ', test_module.__name__
171172
172def add_parser(subparsers):173def init_parser(parser):
173 parser = subparsers.add_parser('run-tests',
174 description='Run the OpenERP server and/or addons tests.')
175 parser.add_argument('-d', '--database', metavar='DATABASE', required=True,174 parser.add_argument('-d', '--database', metavar='DATABASE', required=True,
176 help='the database to test. Depending on the test suites, the '175 help='the database to test. Depending on the test suites, the '
177 'database must already exist or not.')176 'database must already exist or not.')
@@ -192,5 +191,4 @@
192 help='run only the sanity check tests')191 help='run only the sanity check tests')
193 parser.add_argument('--dry-run', action='store_true',192 parser.add_argument('--dry-run', action='store_true',
194 help='do not run the tests')193 help='do not run the tests')
195
196 parser.set_defaults(run=run)194 parser.set_defaults(run=run)
197195
=== modified file 'openerpcommand/scaffold.py'
--- openerpcommand/scaffold.py 2012-02-01 22:38:52 +0000
+++ openerpcommand/scaffold.py 2012-11-27 15:42:19 +0000
@@ -1,7 +1,6 @@
1"""1"""
2Generate an OpenERP module skeleton.2Generate an OpenERP module skeleton.
3"""3"""
4
5import os4import os
6import sys5import sys
76
@@ -22,12 +21,9 @@
22 with open(os.path.join(module, 'models', '__init__.py'), 'w') as h:21 with open(os.path.join(module, 'models', '__init__.py'), 'w') as h:
23 h.write(MODELS_PY % (module,))22 h.write(MODELS_PY % (module,))
2423
25def add_parser(subparsers):24def init_parser(parser):
26 parser = subparsers.add_parser('scaffold',
27 description='Generate an OpenERP module skeleton.')
28 parser.add_argument('module', metavar='MODULE',25 parser.add_argument('module', metavar='MODULE',
29 help='the name of the generated module')26 help='the name of the generated module')
30
31 parser.set_defaults(run=run)27 parser.set_defaults(run=run)
3228
33MANIFEST = """\29MANIFEST = """\
3430
=== added file 'openerpcommand/show.py'
--- openerpcommand/show.py 1970-01-01 00:00:00 +0000
+++ openerpcommand/show.py 2012-11-27 15:42:19 +0000
@@ -0,0 +1,23 @@
1"""
2Display a record.
3"""
4from openerpcommand.common import Client
5
6class Show(Client):
7 def __init__(self, parser):
8 super(Show, self).__init__(parser)
9 self.parser.add_argument('-m', '--model', metavar='MODEL',
10 required=True, help='the model')
11 self.parser.add_argument('-i', '--id', metavar='RECORDID',
12 required=True, help='the record id')
13
14 def work(self):
15 xs = self.execute(self.args.model, 'read', [self.args.id], [])
16 if xs:
17 x = xs[0]
18 print x['name']
19 else:
20 print "Record not found."
21
22def init_parser(parser):
23 Show(parser)
024
=== modified file 'openerpcommand/uninstall.py'
--- openerpcommand/uninstall.py 2012-08-22 17:20:15 +0000
+++ openerpcommand/uninstall.py 2012-11-27 15:42:19 +0000
@@ -1,10 +1,10 @@
1"""1"""
2Install OpenERP on a new (by default) database.2Uninstall some modules from an OpenERP database.
3"""3"""
4import os4import os
5import sys5import sys
66
7import common7from openerpcommand import common
88
9# TODO turn template1 in a parameter9# TODO turn template1 in a parameter
10# This should be exposed from openerp (currently in10# This should be exposed from openerp (currently in
@@ -30,7 +30,7 @@
30 config = openerp.tools.config30 config = openerp.tools.config
31 config['log_handler'] = [':CRITICAL']31 config['log_handler'] = [':CRITICAL']
32 if args.addons:32 if args.addons:
33 args.addons = args.addons.split(':')33 args.addons = map(common.expand_path, args.addons.split(':'))
34 else:34 else:
35 args.addons = []35 args.addons = []
36 config['addons_path'] = ','.join(args.addons)36 config['addons_path'] = ','.join(args.addons)
@@ -54,14 +54,11 @@
54 finally:54 finally:
55 cr.close()55 cr.close()
5656
57def add_parser(subparsers):57def init_parser(parser):
58 parser = subparsers.add_parser('uninstall',
59 description='Uninstall some modules from an OpenERP database.')
60 parser.add_argument('-d', '--database', metavar='DATABASE',58 parser.add_argument('-d', '--database', metavar='DATABASE',
61 **common.required_or_default('DATABASE', 'the database to modify'))59 **common.required_or_default('DATABASE', 'the database to modify'))
62 common.add_addons_argument(parser)60 common.add_addons_argument(parser)
63 parser.add_argument('--module', metavar='MODULE', action='append',61 parser.add_argument('--module', metavar='MODULE', action='append',
64 help='specify a module to uninstall'62 help='specify a module to uninstall'
65 ' (this option can be repeated)')63 ' (this option can be repeated)')
66
67 parser.set_defaults(run=run)64 parser.set_defaults(run=run)
6865
=== modified file 'openerpcommand/update.py'
--- openerpcommand/update.py 2012-02-14 15:05:03 +0000
+++ openerpcommand/update.py 2012-11-27 15:42:19 +0000
@@ -10,9 +10,7 @@
10 openerp.modules.registry.RegistryManager.get(10 openerp.modules.registry.RegistryManager.get(
11 args.database, update_module=True, pooljobs=False)11 args.database, update_module=True, pooljobs=False)
1212
13def add_parser(subparsers):13def init_parser(parser):
14 parser = subparsers.add_parser('update',
15 description='Update an existing OpenERP database.')
16 parser.add_argument('-d', '--database', metavar='DATABASE', required=True,14 parser.add_argument('-d', '--database', metavar='DATABASE', required=True,
17 help='the database to update')15 help='the database to update')
1816
1917
=== modified file 'setup.py' (properties changed: -x to +x)
--- setup.py 2012-01-31 17:55:23 +0000
+++ setup.py 2012-11-27 15:42:19 +0000
@@ -31,8 +31,29 @@
31 zip_safe = False,31 zip_safe = False,
32 packages = find_packages(),32 packages = find_packages(),
33 include_package_data = True,33 include_package_data = True,
34 entry_points="""34 entry_points={
35 [console_scripts]35 'console_scripts' : ['oe = openerpcommand.main:run'],
36 oe=openerpcommand.main:run36 'openerpcommand.subcommands': [ 'call = openerpcommand.call:init_parser',
37 """,37 'conf = openerpcommand.conf:init_parser',
38 'consume_cpu = openerpcommand.consume_cpu:init_parser',
39 'consume_memory = openerpcommand.consume_memory:init_parser',
40 'consume_nothing = openerpcommand.consume_nothing:init_parser',
41 'drop = openerpcommand.drop:init_parser',
42 'initialize = openerpcommand.initialize:init_parser',
43 'leak_memory = openerpcommand.leak_memory:init_parser',
44 'model = openerpcommand.model:init_parser',
45 'module = openerpcommand.module:init_parser',
46 'open = openerpcommand.open:init_parser',
47 'read = openerpcommand.read:init_parser',
48 'run_tests = openerpcommand.run_tests:init_parser',
49 'scaffold = openerpcommand.scaffold:init_parser',
50 'show = openerpcommand.show:init_parser',
51 'uninstall = openerpcommand.uninstall:init_parser',
52 'update = openerpcommand.update:init_parser'],
53 'openerpcommand.subcommands.benchmark': [ 'dummy = openerpcommand.benchmark.dummy:init_parser',
54 'fields_view_get = openerpcommand.benchmark.fields_view_get:init_parser',
55 'login = openerpcommand.benchmark.login:init_parser',
56 'read = openerpcommand.benchmark.read:init_parser',
57 'sale_mrp = openerpcommand.benchmark.sale_mrp:init_parser'],
58 },
38)59)

Subscribers

People subscribed via source and target branches