vcon 0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
vcon-0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 vcon-dev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
vcon-0.1/PKG-INFO ADDED
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.1
2
+ Name: vcon
3
+ Version: 0.1
4
+ Summary: vCons are PDFs for human conversations, defining them so they can be shared, analyzed and secured.
5
+ Author-email: Daniel Petrie <dan.ietf@sipez.com>, Thomas McCarthy-Howe <thomas.howe@strolid.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2022 vcon-dev
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: repository, https://github.com/vcon-dev/vcon
29
+ Project-URL: documentation, https://www.vcon.dev/
30
+ Keywords: vcon,conversational ai,conversation
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Programming Language :: Python
33
+ Classifier: Programming Language :: Python :: 3
34
+ Requires-Python: >=3.8
35
+ Description-Content-Type: text/markdown
36
+ Provides-Extra: dev
37
+ License-File: LICENSE
38
+
39
+ # The Home Repo for vCons and the Conserver
40
+
41
+ ## Introduction
42
+ vCons are PDFs for human conversations, defining them so they can be shared, analyzed and secured. The Conserver is a domain specific data platform based on vCons, converting the raw materials of recorded conversations into self-serve data sources for any team. The Conserver represents the most modern set of tools for data engineers to responsibly and scalably use customer conversations in data pipelines.
43
+
44
+ The Vcon library consists of two primary components:
45
+
46
+ * The Python Vcon package for constructing and operating on Vcon objects
47
+ * The Conserver for storing, managing and manipulating Vcon objects and operation streams on Vcon objects
48
+
49
+ ## Table of Contents
50
+
51
+ + [Presentations, Whitepapers and Tutorials](#presentations-whitepapers-and-tutorials)
52
+ + [vCon Library Quick Start for Python](https://github.com/vcon-dev/vcon/wiki/Library-Quick-Start)
53
+ + [Testing the Vcon Package](#testing-the-vcon-package)
54
+ + [Testing the conserver](#testing-the-conserver)
55
+
56
+ ## Presentations, Whitepapers and Tutorials
57
+
58
+ See the [Birds of a Feather session at IETF 116, Yokohama](https://youtu.be/EF2OMbo6Qj4)
59
+
60
+ See the [presentation at TADSummit](https://youtu.be/ZBRJ6FcVblc)
61
+
62
+ See the [presentation at IETF](https://youtu.be/dJsPzZITr_g?t=243)
63
+
64
+ See the [presentation at IIT](https://youtu.be/s-pjgpBOQqc)
65
+
66
+ Read the [IETF draft proposal](https://datatracker.ietf.org/doc/html/draft-petrie-vcon-01)
67
+
68
+ Read the [white paper](https://docs.google.com/document/d/1TV8j29knVoOJcZvMHVFDaan0OVfraH_-nrS5gW4-DEA/edit?usp=sharing)
69
+
70
+ See the [key note proposal for vCons](https://blog.tadsummit.com/2021/12/08/strolid-keynote-vcons/).
71
+
72
+
73
+ ## Testing the Vcon Package
74
+ A suite of pytest unit tests exist for the Vcon package in: [tests](tests)
75
+
76
+ These can be run using the following command in the current directory:
77
+
78
+ pytest -v -rP tests
79
+
80
+
81
+ Please also run separately the following unit test as it will check for spurious stdout from the Vcon package that will likely cause the CLI to break:
82
+
83
+ pytest -v -rP tests/test_vcon_cli.py
84
+
85
+ Note: These errors may not show up when you run test_vcon_cli.py with the rest of the unit tests as some stdout may only occur when the Vcon package is first imported and may not get trapped/detected by other unit tests.
86
+
87
+
88
+ ## Testing the conserver
89
+ A suite of pytest unit tests exist for the conserver in: [server/tests](server/tests)
90
+
91
+ Running and testing the conserver requires a running instance of Redis.
92
+ Be sure to create and edit your server/.env file to reflect your redis server address and port.
93
+ It can be generated like the following command line:
94
+
95
+ cat <<EOF>.env
96
+ #!/usr/bin/sh
97
+ export AWS_BUCKET=vcon-storage
98
+ export AWS_KEY_ID=aaaaaaaaaaaaaaa
99
+ export AWS_SECRET_KEY=bbbbbbbbbbb
100
+ export DEEPGRAM_KEY=ccccccccccccc
101
+ export ENV=dev
102
+ export HOSTNAME=http://0.0.0.0:8000
103
+ export REDIS_URL=redis://172.17.0.4:6379
104
+ #export MONOREPO_DATABASE_URL=postgresql://password:userid@your.postgres.domain.com:5432/postgres
105
+ EOF
106
+
107
+ The unit tests for the conserver can be run using the following command in the server directory:
108
+
109
+ source .env
110
+ pytest -v -rP tests
111
+
vcon-0.1/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # The Home Repo for vCons and the Conserver
2
+
3
+ ## Introduction
4
+ vCons are PDFs for human conversations, defining them so they can be shared, analyzed and secured. The Conserver is a domain specific data platform based on vCons, converting the raw materials of recorded conversations into self-serve data sources for any team. The Conserver represents the most modern set of tools for data engineers to responsibly and scalably use customer conversations in data pipelines.
5
+
6
+ The Vcon library consists of two primary components:
7
+
8
+ * The Python Vcon package for constructing and operating on Vcon objects
9
+ * The Conserver for storing, managing and manipulating Vcon objects and operation streams on Vcon objects
10
+
11
+ ## Table of Contents
12
+
13
+ + [Presentations, Whitepapers and Tutorials](#presentations-whitepapers-and-tutorials)
14
+ + [vCon Library Quick Start for Python](https://github.com/vcon-dev/vcon/wiki/Library-Quick-Start)
15
+ + [Testing the Vcon Package](#testing-the-vcon-package)
16
+ + [Testing the conserver](#testing-the-conserver)
17
+
18
+ ## Presentations, Whitepapers and Tutorials
19
+
20
+ See the [Birds of a Feather session at IETF 116, Yokohama](https://youtu.be/EF2OMbo6Qj4)
21
+
22
+ See the [presentation at TADSummit](https://youtu.be/ZBRJ6FcVblc)
23
+
24
+ See the [presentation at IETF](https://youtu.be/dJsPzZITr_g?t=243)
25
+
26
+ See the [presentation at IIT](https://youtu.be/s-pjgpBOQqc)
27
+
28
+ Read the [IETF draft proposal](https://datatracker.ietf.org/doc/html/draft-petrie-vcon-01)
29
+
30
+ Read the [white paper](https://docs.google.com/document/d/1TV8j29knVoOJcZvMHVFDaan0OVfraH_-nrS5gW4-DEA/edit?usp=sharing)
31
+
32
+ See the [key note proposal for vCons](https://blog.tadsummit.com/2021/12/08/strolid-keynote-vcons/).
33
+
34
+
35
+ ## Testing the Vcon Package
36
+ A suite of pytest unit tests exist for the Vcon package in: [tests](tests)
37
+
38
+ These can be run using the following command in the current directory:
39
+
40
+ pytest -v -rP tests
41
+
42
+
43
+ Please also run separately the following unit test as it will check for spurious stdout from the Vcon package that will likely cause the CLI to break:
44
+
45
+ pytest -v -rP tests/test_vcon_cli.py
46
+
47
+ Note: These errors may not show up when you run test_vcon_cli.py with the rest of the unit tests as some stdout may only occur when the Vcon package is first imported and may not get trapped/detected by other unit tests.
48
+
49
+
50
+ ## Testing the conserver
51
+ A suite of pytest unit tests exist for the conserver in: [server/tests](server/tests)
52
+
53
+ Running and testing the conserver requires a running instance of Redis.
54
+ Be sure to create and edit your server/.env file to reflect your redis server address and port.
55
+ It can be generated like the following command line:
56
+
57
+ cat <<EOF>.env
58
+ #!/usr/bin/sh
59
+ export AWS_BUCKET=vcon-storage
60
+ export AWS_KEY_ID=aaaaaaaaaaaaaaa
61
+ export AWS_SECRET_KEY=bbbbbbbbbbb
62
+ export DEEPGRAM_KEY=ccccccccccccc
63
+ export ENV=dev
64
+ export HOSTNAME=http://0.0.0.0:8000
65
+ export REDIS_URL=redis://172.17.0.4:6379
66
+ #export MONOREPO_DATABASE_URL=postgresql://password:userid@your.postgres.domain.com:5432/postgres
67
+ EOF
68
+
69
+ The unit tests for the conserver can be run using the following command in the server directory:
70
+
71
+ source .env
72
+ pytest -v -rP tests
73
+
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "vcon"
7
+ version = "0.1"
8
+ description = "vCons are PDFs for human conversations, defining them so they can be shared, analyzed and secured."
9
+ readme = "README.md"
10
+ authors = [{ name = "Daniel Petrie", email = "dan.ietf@sipez.com" }, { name = "Thomas McCarthy-Howe", email = "thomas.howe@strolid.com" }]
11
+ license = { file = "LICENSE" }
12
+ classifiers = [
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python",
15
+ "Programming Language :: Python :: 3",
16
+ ]
17
+ keywords = ["vcon", "conversational ai", "conversation"]
18
+ dependencies = [
19
+ "cryptography >= 37",
20
+ "hsslms >= 0.1.2",
21
+ "python-jose[cryptography] >= 3.3.0",
22
+ "python-dateutil >= 2.8.2",
23
+ "uuid6 >= 2023.4.25",
24
+ "python-json-logger >= 2.0.7",
25
+ "sox >= 1.4.1",
26
+ ]
27
+ requires-python = ">=3.8"
28
+
29
+ [project.optional-dependencies]
30
+ dev = ["pytest"]
31
+
32
+ [project.urls]
33
+ repository = "https://github.com/vcon-dev/vcon"
34
+ documentation = "https://www.vcon.dev/"
35
+
36
+ [tool.setuptools]
37
+ packages = ["vcon", "vcon.filter_plugins","vcon.filter_plugins.impl"]
vcon-0.1/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,59 @@
1
+ """
2
+ Unit test for date conversions
3
+ """
4
+
5
+ import vcon.utils
6
+ import datetime
7
+ import dateutil.tz
8
+
9
+ date_int = 1652552179
10
+ date_float = 1652552179.0001
11
+ date_rfc2822 = "Wed, 14 May 2022 18:16:19 -0000"
12
+ date_rfc3339 = "2022-05-14T18:16:19.000+00:00"
13
+ date_rfc3339_EDT = "2022-05-14T14:16:19.000-04:00"
14
+
15
+
16
+ def test_created_at():
17
+ v = vcon.Vcon()
18
+ print("created_at: {}".format(v.created_at))
19
+ assert(len(v.created_at) > 10)
20
+
21
+ def test_cannonize_date():
22
+ cannonized = vcon.utils.cannonize_date(date_int)
23
+ #print(cannonized)
24
+ assert(cannonized == date_rfc3339)
25
+
26
+ cannonized = vcon.utils.cannonize_date(date_float)
27
+ # off by time zone
28
+ #print(cannonized)
29
+ assert(cannonized == date_rfc3339)
30
+
31
+ cannonized = vcon.utils.cannonize_date(date_rfc2822)
32
+ # off by time zone
33
+ #print(cannonized)
34
+ assert(cannonized == date_rfc3339)
35
+
36
+ cannonized = vcon.utils.cannonize_date(date_rfc3339)
37
+ # off by time zone
38
+ #print(cannonized)
39
+ assert(cannonized == date_rfc3339)
40
+
41
+ cannonized = vcon.utils.cannonize_date(date_rfc3339_EDT)
42
+ # off by time zone
43
+ #print(cannonized)
44
+ assert(cannonized == date_rfc3339)
45
+
46
+ try:
47
+ cannonized = vcon.utils.cannonize_date("10 June 2022 8:55PM")
48
+ raise Exception("Should have raised AttributeError exception for not valid date format")
49
+
50
+ except AttributeError as e:
51
+ # Expect to catch exception here
52
+ pass
53
+
54
+ datetime_val = datetime.datetime(2022, 9, 27, 14, 23, 38, 938223)
55
+ datetime_val = datetime_val.replace(tzinfo = dateutil.tz.gettz('US/Eastern'))
56
+ cannonized = vcon.utils.cannonize_date(datetime_val)
57
+ #print("{} dst: {}".format(cannonized, datetime_val.dst()))
58
+ assert(cannonized == "2022-09-27T18:23:38.938+00:00")
59
+
@@ -0,0 +1,231 @@
1
+ """
2
+ Unit tests for external content such as recording, attachments which are stored
3
+ as URLs with a signature for the content stored else where. Using
4
+ Leighton-Micali One Time Signature (RFC8554).
5
+ """
6
+
7
+ import os
8
+ import datetime
9
+ import pytest
10
+ import vcon
11
+ import vcon.security
12
+ import hsslms
13
+ import hashlib
14
+ import jose.utils
15
+
16
+ call_data = {
17
+ "epoch" : "1652552179",
18
+ "destination" : "2117",
19
+ "source" : "+19144345359",
20
+ "rfc2822" : "Sat, 14 May 2022 18:16:19 -0000",
21
+ "rfc3339" : "2022-05-14T18:16:19.000+00:00",
22
+ "file_extension" : "WAV",
23
+ "duration" : 94.84,
24
+ "channels" : 1
25
+ }
26
+
27
+ @pytest.fixture(scope="function")
28
+ def empty_vcon() -> vcon.Vcon:
29
+ """ construct vCon with no data """
30
+ vCon = vcon.Vcon()
31
+ return(vCon)
32
+
33
+ @pytest.fixture(scope="function")
34
+ def two_party_tel_vcon(empty_vcon : vcon.Vcon) -> vcon.Vcon:
35
+ """ construct vCon with two tel URL """
36
+ vCon = empty_vcon
37
+ first_party = vCon.set_party_parameter("tel", call_data['source'])
38
+ second_party = vCon.set_party_parameter("tel", call_data['destination'])
39
+ vCon.set_uuid("vcon.dev")
40
+ return(vCon)
41
+
42
+ def test_lm_ots_sign() -> None:
43
+ file_size = 2048
44
+ fake_file = os.urandom(file_size)
45
+
46
+ key, sig = vcon.security.lm_one_time_signature(fake_file)
47
+
48
+ vcon.security.verify_lm_one_time_signature(fake_file, sig, key)
49
+
50
+ try:
51
+ # cause signature to fail
52
+ vcon.security.verify_lm_one_time_signature(fake_file, sig.replace("D", "E", 1), key)
53
+ raise Exception("Should have raisee and INVALID signature error")
54
+
55
+ except hsslms.utils.INVALID as invalid_error:
56
+ # Expect this to be raised as we have modified signature
57
+ pass
58
+
59
+ try:
60
+ # cause key to fail
61
+ vcon.security.verify_lm_one_time_signature(fake_file, sig, key.replace("A", "Z", 1))
62
+ raise Exception("Should have raised and INVALID key error")
63
+
64
+ except hsslms.utils.INVALID as invalid_error:
65
+ # Expect this to be raised as we have modified signature
66
+ pass
67
+
68
+ def test_get_external_recording(two_party_tel_vcon : vcon.Vcon) -> None:
69
+ # Add external ref
70
+ file_path = "examples/agent_sample.wav"
71
+ url = "https://github.com/vcon-dev/vcon/blob/main/examples/agent_sample.wav?raw=true"
72
+ file_content = b""
73
+ with open(file_path, "rb") as file_handle:
74
+ file_content = file_handle.read()
75
+ print("body length: {}".format(len(file_content)))
76
+ assert(len(file_content) > 10000)
77
+
78
+ dialog_index = two_party_tel_vcon.add_dialog_external_recording(file_content,
79
+ datetime.datetime.utcnow(),
80
+ 0, # duration TODO
81
+ [0,1],
82
+ url,
83
+ vcon.Vcon.MIMETYPE_AUDIO_WAV,
84
+ os.path.basename(file_path))
85
+
86
+ assert(dialog_index == 0)
87
+
88
+ dialog_object = two_party_tel_vcon.dialog[0]
89
+ assert(dialog_object.get("originator", None) is None)
90
+ assert(dialog_object.get("duration", None) == 0)
91
+ assert(dialog_object.get("url", None) == url)
92
+
93
+ body_bytes = two_party_tel_vcon.get_dialog_external_recording(dialog_index)
94
+ assert(len(file_content) == len(body_bytes))
95
+ assert(file_content == body_bytes)
96
+
97
+ # This should be valid
98
+ two_party_tel_vcon.verify_dialog_external_recording(0, body_bytes)
99
+
100
+ body_byte_array = bytearray(body_bytes)
101
+ body_byte_array[0] = body_bytes[0] + 1
102
+ body_bytes = bytes(body_byte_array)
103
+ assert(file_content != body_bytes)
104
+
105
+ try:
106
+ #We modified the body_bytes so this should fail
107
+ two_party_tel_vcon.verify_dialog_external_recording(0, body_bytes)
108
+ raise Exception("Should have thrown invalid as body_bytes is not identical")
109
+
110
+ except vcon.InvalidVconHash as invalid_body_error:
111
+ # We expect this to occur
112
+ pass
113
+
114
+ def test_external_recording_lm_ots(two_party_tel_vcon : vcon.Vcon) -> None:
115
+ data_size = 4096
116
+ data = os.urandom(data_size)
117
+
118
+ url = "https://example.com?q=\"ddd\"&y=\'!\'"
119
+ #print("url: {}".format(url))
120
+
121
+ file_name = "my_rec.wav"
122
+
123
+ assert(vcon.Vcon.MIMETYPE_AUDIO_WAV == "audio/x-wav")
124
+
125
+ two_party_tel_vcon.add_dialog_external_recording(data,
126
+ call_data["rfc2822"],
127
+ call_data["duration"],
128
+ 0,
129
+ url,
130
+ vcon.Vcon.MIMETYPE_AUDIO_WAV,
131
+ file_name,
132
+ sign_type="LM-OTS")
133
+
134
+ vcon_json = two_party_tel_vcon.dumps()
135
+
136
+ new_vcon = vcon.Vcon()
137
+ new_vcon.loads(vcon_json)
138
+
139
+ assert(len(new_vcon.dialog) == 1)
140
+ assert(new_vcon.dialog[0]['type'] == "recording")
141
+ assert(new_vcon.dialog[0]['url'] == url)
142
+ assert(new_vcon.dialog[0]['parties'] == 0)
143
+ assert(new_vcon.dialog[0]['start'] == call_data["rfc3339"])
144
+ assert(new_vcon.dialog[0]['duration'] == call_data["duration"])
145
+ assert(new_vcon.dialog[0]['mimetype'] == "audio/x-wav")
146
+ assert(new_vcon.dialog[0]['filename'] == file_name)
147
+ assert(new_vcon.dialog[0]['alg'] == 'LMOTS_SHA256_N32_W8')
148
+ assert(len(new_vcon.dialog[0]['key']) > 1)
149
+ assert("body" not in new_vcon.dialog[0])
150
+
151
+ new_vcon.verify_dialog_external_recording(0, data)
152
+
153
+ try:
154
+ # Change the data so that validation should fail
155
+ new_vcon.verify_dialog_external_recording(0, data[1:])
156
+ raise Exception("Should have raised exception here as data is missin the first byte")
157
+
158
+ except hsslms.utils.INVALID as invalid_error:
159
+ # Expect to get this exception
160
+ pass
161
+
162
+ def test_sha512():
163
+ data1 = b"test some text stuff as binary"
164
+ data_size = 4096
165
+ data2 = os.urandom(data_size)
166
+
167
+ hasher = hashlib.sha512()
168
+
169
+ hasher.update(data1)
170
+ hasher.update(data2)
171
+
172
+ sig_hash = jose.utils.base64url_encode(hasher.digest())
173
+
174
+ validater = hashlib.sha512()
175
+
176
+ validater.update(data1 + data2)
177
+
178
+ validate_hash = jose.utils.base64url_encode(validater.digest())
179
+
180
+ assert(sig_hash == validate_hash)
181
+
182
+ def test_external_recording_sha_512(two_party_tel_vcon : vcon.Vcon) -> None:
183
+ data_size = 4096
184
+ data = os.urandom(data_size)
185
+
186
+ url = "https://example.com?q=\"ddd\"&y=\'!\'"
187
+ #print("url: {}".format(url))
188
+
189
+ file_name = "my_rec.wav"
190
+
191
+ assert(vcon.Vcon.MIMETYPE_AUDIO_WAV == "audio/x-wav")
192
+
193
+ two_party_tel_vcon.add_dialog_external_recording(data,
194
+ call_data["rfc2822"],
195
+ call_data["duration"],
196
+ 0,
197
+ url,
198
+ vcon.Vcon.MIMETYPE_AUDIO_WAV,
199
+ file_name,
200
+ originator=1)
201
+
202
+ vcon_json = two_party_tel_vcon.dumps()
203
+
204
+ print("original: {}".format(vcon_json))
205
+ new_vcon = vcon.Vcon()
206
+ new_vcon.loads(vcon_json)
207
+ print("deserialized: {}".format(new_vcon.dumps()))
208
+
209
+ assert(len(new_vcon.dialog) == 1)
210
+ assert(new_vcon.dialog[0]['type'] == "recording")
211
+ assert(new_vcon.dialog[0]['url'] == url)
212
+ assert(new_vcon.dialog[0]['parties'] == 0)
213
+ assert(new_vcon.dialog[0]['start'] == call_data["rfc3339"])
214
+ assert(new_vcon.dialog[0]['duration'] == call_data["duration"])
215
+ assert(new_vcon.dialog[0]['mimetype'] == "audio/x-wav")
216
+ assert(new_vcon.dialog[0]['filename'] == file_name)
217
+ assert(new_vcon.dialog[0]['alg'] == 'SHA-512')
218
+ assert(new_vcon.dialog[0]['originator'] == 1)
219
+ assert("body" not in new_vcon.dialog[0])
220
+ assert("key" not in new_vcon.dialog[0])
221
+
222
+ new_vcon.verify_dialog_external_recording(0, data)
223
+
224
+ try:
225
+ # Change the data so that validation should fail
226
+ new_vcon.verify_dialog_external_recording(0, data[1:])
227
+ raise Exception("Should have raised exception here as data is missin the first byte")
228
+
229
+ except vcon.InvalidVconHash as invalid_error:
230
+ # Expect to get this exception
231
+ pass
@@ -0,0 +1,95 @@
1
+ """ Unit test for filter plugin framework """
2
+
3
+ import pytest
4
+ import sys
5
+ import vcon
6
+ import vcon.filter_plugins
7
+
8
+ # test foo registration file
9
+ import tests.foo_reg
10
+
11
+ def test_registry():
12
+ plugin_names = vcon.filter_plugins.FilterPluginRegistry.get_names()
13
+
14
+ print("found {} plugins: {}".format(len(plugin_names), plugin_names))
15
+
16
+ # Test foo a test plugin, not fully implemented
17
+ plugin_foop = vcon.filter_plugins.FilterPluginRegistry.get("foop")
18
+ assert(plugin_foop is not None)
19
+ assert(plugin_foop.import_plugin() == True)
20
+ try:
21
+ plugin_foop.filter(None)
22
+ # SHould not get here
23
+ raise Exception("Should have thrown a PluginFilterNotImplemented exception")
24
+
25
+ except vcon.filter_plugins.PluginFilterNotImplemented as not_found_error:
26
+ # We are expecting this exception
27
+ print("got {}".format(not_found_error), file=sys.stderr)
28
+ #raise not_found_error
29
+
30
+ # this time test foop using its registered name as a method
31
+ try:
32
+ in_vcon = vcon.Vcon()
33
+ out_vcon = in_vcon.foop()
34
+ # SHould not get here
35
+ raise Exception("Should have thrown a PluginFilterNotImplemented exception")
36
+
37
+ except vcon.filter_plugins.PluginFilterNotImplemented as not_found_error:
38
+ # We are expecting this exception
39
+ print("got {}".format(not_found_error), file=sys.stderr)
40
+ #raise not_found_error
41
+
42
+ try:
43
+ plugin_barp = vcon.filter_plugins.FilterPluginRegistry.get("barp")
44
+ raise Exception("Expected not to fine barp and throw exception")
45
+
46
+ except vcon.filter_plugins.PluginFilterNotRegistered as not_reg_error:
47
+ print(not_reg_error, file=sys.stderr)
48
+
49
+ vcon.filter_plugins.FilterPluginRegistry.set_type_default_name("exclaim", "foop")
50
+ assert(vcon.filter_plugins.FilterPluginRegistry.get_type_default_name("exclaim") == "foop")
51
+ assert(vcon.filter_plugins.FilterPluginRegistry.get_type_default_name("bar") == None)
52
+ assert(vcon.filter_plugins.FilterPluginRegistry.get_type_default_plugin("exclaim") == plugin_foop)
53
+
54
+ # this time test foop using it set as default type exclaim name as a method
55
+ try:
56
+ in_vcon = vcon.Vcon()
57
+ out_vcon = in_vcon.exclaim()
58
+ # SHould not get here
59
+ raise Exception("Should have thrown a PluginFilterNotImplemented exception")
60
+
61
+ except vcon.filter_plugins.PluginFilterNotImplemented as not_found_error:
62
+ # We are expecting this exception
63
+ print("got {}".format(not_found_error), file=sys.stderr)
64
+ #raise not_found_error
65
+
66
+
67
+ # Test that real plugin was registered
68
+ plugin_whisper = vcon.filter_plugins.FilterPluginRegistry.get("whisper")
69
+ assert(plugin_whisper is not None)
70
+ assert(plugin_whisper.import_plugin() == True)
71
+
72
+ # Verify whisper is the default transcribe type filter plugin
73
+ assert(vcon.filter_plugins.FilterPluginRegistry.get_type_default_name("transcribe") == "whisper")
74
+
75
+ in_vcon = vcon.Vcon()
76
+ options = {}
77
+ try:
78
+ out_vcon = in_vcon.filter("doesnotexist", **options)
79
+ raise Exception("Expected not to find plugin and throw exception")
80
+
81
+ except vcon.filter_plugins.PluginFilterNotRegistered as not_reg_error:
82
+ print(not_reg_error, file=sys.stderr)
83
+
84
+ import tests.bar_reg
85
+
86
+ v2 = vcon.Vcon()
87
+
88
+ try:
89
+ v2.barp()
90
+ raise Exception("expect exception as filter plugin bar trys to import a non-existant package")
91
+
92
+ except vcon.filter_plugins.PluginModuleNotFound as fp_no_mod_error:
93
+ # should get here
94
+ print("got {}".format(fp_no_mod_error))
95
+