File: dbus-next-send.py

package info (click to toggle)
python-dbus-next 0.2.3-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 696 kB
  • sloc: python: 6,018; makefile: 45; xml: 29
file content (125 lines) | stat: -rwxr-xr-x 3,733 bytes parent folder | download | duplicates (3)
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
#!/usr/bin/env python3
import sys
import os

sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/..'))

from dbus_next.validators import (is_bus_name_valid, is_member_name_valid, is_object_path_valid,
                                  is_interface_name_valid)
from dbus_next.aio import MessageBus
from dbus_next import MessageType, BusType, Message, Variant
from argparse import ArgumentParser, OPTIONAL
import json

import asyncio

parser = ArgumentParser()

parser.add_argument('--system', help='Use the system bus', action='store_true')
parser.add_argument('--session', help='Use the session bus', action='store_true')
parser.add_argument('--dest', help='The destination address for the message', required=True)
parser.add_argument('--signature', help='The signature for the message body')
parser.add_argument('--type',
                    help='The type of message to send',
                    choices=[e.name for e in MessageType],
                    default=MessageType.METHOD_CALL.name,
                    nargs=OPTIONAL)
parser.add_argument('object_path', help='The object path for the message')
parser.add_argument('interface.member', help='The interface and member for the message')
parser.add_argument('body',
                    help='The JSON encoded body of the message. Must match the signature',
                    nargs=OPTIONAL)

args = parser.parse_args()


def exit_error(message):
    parser.print_usage()
    print()
    print(message)
    sys.exit(1)


interface_member = vars(args)['interface.member'].split('.')

if len(interface_member) < 2:
    exit_error(
        f'Expecting an interface and member separated by a dot: {vars(args)["interface.member"]}')

destination = args.dest
member = interface_member[-1]
interface = '.'.join(interface_member[:len(interface_member) - 1])
object_path = args.object_path
signature = args.signature
body = args.body
message_type = MessageType[args.type]
signature = args.signature

bus_type = BusType.SESSION

if args.system:
    bus_type = BusType.SYSTEM

if message_type is not MessageType.METHOD_CALL:
    exit_error('only message type METHOD_CALL is supported right now')

if not is_bus_name_valid(destination):
    exit_error(f'got invalid bus name: {destination}')

if not is_object_path_valid(object_path):
    exit_error(f'got invalid object path: {object_path}')

if not is_interface_name_valid(interface):
    exit_error(f'got invalid interface name: {interface}')

if not is_member_name_valid(member):
    exit_error(f'got invalid member name: {member}')

if body is None:
    body = []
    signature = ''
else:
    try:
        body = json.loads(body)
    except json.JSONDecodeError as e:
        exit_error(f'could not parse body as JSON: ({e})')

    if type(body) is not list:
        exit_error('body must be an array of arguments')

    if not signature:
        exit_error('--signature is a required argument when passing a message body')

loop = asyncio.get_event_loop()


async def main():
    bus = await MessageBus(bus_type=bus_type).connect()

    message = Message(destination=destination,
                      member=member,
                      interface=interface,
                      path=object_path,
                      signature=signature,
                      body=body)

    result = await bus.call(message)

    ret = 0

    if result.message_type is MessageType.ERROR:
        print(f'Error: {result.error_name}', file=sys.stderr)
        ret = 1

    def default(o):
        if type(o) is Variant:
            return [o.signature, o.value]
        else:
            raise json.JSONDecodeError()

    print(json.dumps(result.body, indent=2, default=default))

    sys.exit(ret)


loop.run_until_complete(main())