naeural-client 2.0.3__py3-none-any.whl → 2.1.0__py3-none-any.whl
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.
- naeural_client/__init__.py +2 -0
- naeural_client/_ver.py +1 -1
- naeural_client/base/generic_session.py +73 -3
- naeural_client/const/__init__.py +1 -0
- naeural_client/const/apps.py +11 -0
- naeural_client/const/environment.py +2 -0
- naeural_client/default/instance/__init__.py +12 -0
- naeural_client/default/instance/basic_telegram_bot_01_plugin.py +5 -0
- naeural_client/default/instance/chain_dist_custom_job_01_plugin.py +2 -1
- naeural_client/default/instance/custom_web_app_01_plugin.py +2 -2
- naeural_client/default/instance/net_mon_01_plugin.py +2 -2
- naeural_client/default/instance/view_scene_01_plugin.py +2 -2
- naeural_client/logging/base_logger.py +5 -4
- {naeural_client-2.0.3.dist-info → naeural_client-2.1.0.dist-info}/METADATA +1 -2
- {naeural_client-2.0.3.dist-info → naeural_client-2.1.0.dist-info}/RECORD +17 -15
- {naeural_client-2.0.3.dist-info → naeural_client-2.1.0.dist-info}/WHEEL +1 -1
- {naeural_client-2.0.3.dist-info → naeural_client-2.1.0.dist-info}/licenses/LICENSE +0 -0
naeural_client/__init__.py
CHANGED
@@ -11,3 +11,5 @@ from .base_decentra_object import BaseDecentrAIObject
|
|
11
11
|
from .plugins_manager_mixin import _PluginsManagerMixin
|
12
12
|
from .logging import Logger
|
13
13
|
from .code_cheker import BaseCodeChecker
|
14
|
+
from .const import PLUGIN_SIGNATURES
|
15
|
+
from .default.instance import PLUGIN_TYPES
|
naeural_client/_ver.py
CHANGED
@@ -9,7 +9,7 @@ from time import time as tm
|
|
9
9
|
|
10
10
|
from ..base_decentra_object import BaseDecentrAIObject
|
11
11
|
from ..bc import DefaultBlockEngine
|
12
|
-
from ..const import COMMANDS, ENVIRONMENT, HB, PAYLOAD_DATA, STATUS_TYPE
|
12
|
+
from ..const import COMMANDS, ENVIRONMENT, HB, PAYLOAD_DATA, STATUS_TYPE, PLUGIN_SIGNATURES
|
13
13
|
from ..const import comms as comm_ct
|
14
14
|
from ..io_formatter import IOFormatterWrapper
|
15
15
|
from ..logging import Logger
|
@@ -1396,7 +1396,7 @@ class GenericSession(BaseDecentrAIObject):
|
|
1396
1396
|
def create_or_attach_to_pipeline(self, *,
|
1397
1397
|
node,
|
1398
1398
|
name,
|
1399
|
-
data_source,
|
1399
|
+
data_source="Void",
|
1400
1400
|
config={},
|
1401
1401
|
plugins=[],
|
1402
1402
|
on_data=None,
|
@@ -1410,15 +1410,21 @@ class GenericSession(BaseDecentrAIObject):
|
|
1410
1410
|
----------
|
1411
1411
|
node : str
|
1412
1412
|
Address or Name of the Naeural Edge Protocol edge node that will handle this pipeline.
|
1413
|
+
|
1413
1414
|
name : str
|
1414
1415
|
Name of the pipeline. This is good to be kept unique, as it allows multiple parties to overwrite each others configurations.
|
1416
|
+
|
1415
1417
|
data_source : str
|
1416
1418
|
This is the name of the DCT plugin, which resembles the desired functionality of the acquisition.
|
1419
|
+
Defaults to "Void" - no actual data acquisition.
|
1420
|
+
|
1417
1421
|
config : dict, optional
|
1418
1422
|
This is the dictionary that contains the configuration of the acquisition source, by default {}
|
1423
|
+
|
1419
1424
|
plugins : list
|
1420
1425
|
List of dictionaries which contain the configurations of each plugin instance that is desired to run on the box.
|
1421
1426
|
Defaults to []. Should be left [], and instances should be created with the api.
|
1427
|
+
|
1422
1428
|
on_data : Callable[[Pipeline, str, str, dict], None], optional
|
1423
1429
|
Callback that handles messages received from any plugin instance.
|
1424
1430
|
As arguments, it has a reference to this Pipeline object, the signature and the instance of the plugin
|
@@ -1426,15 +1432,18 @@ class GenericSession(BaseDecentrAIObject):
|
|
1426
1432
|
This callback acts as a default payload processor and will be called even if for a given instance
|
1427
1433
|
the user has defined a specific callback.
|
1428
1434
|
Defaults to None.
|
1435
|
+
|
1429
1436
|
on_notification : Callable[[Pipeline, dict], None], optional
|
1430
1437
|
Callback that handles notifications received from any plugin instance.
|
1431
1438
|
As arguments, it has a reference to this Pipeline object, along with the payload itself.
|
1432
1439
|
This callback acts as a default payload processor and will be called even if for a given instance
|
1433
1440
|
the user has defined a specific callback.
|
1434
1441
|
Defaults to None.
|
1442
|
+
|
1435
1443
|
max_wait_time : int, optional
|
1436
1444
|
The maximum time to busy-wait, allowing the Session object to listen to node heartbeats
|
1437
1445
|
and to check if the desired node is online in the network, by default 0.
|
1446
|
+
|
1438
1447
|
**kwargs :
|
1439
1448
|
The user can provide the configuration of the acquisition source directly as kwargs.
|
1440
1449
|
|
@@ -1651,15 +1660,39 @@ class GenericSession(BaseDecentrAIObject):
|
|
1651
1660
|
*,
|
1652
1661
|
node,
|
1653
1662
|
name,
|
1654
|
-
signature=
|
1663
|
+
signature=PLUGIN_SIGNATURES.CUSTOM_WEB_APP_01,
|
1655
1664
|
endpoints=None,
|
1656
1665
|
use_ngrok=True,
|
1657
1666
|
**kwargs
|
1658
1667
|
):
|
1668
|
+
"""
|
1669
|
+
Create a new web app on a node.
|
1670
|
+
|
1671
|
+
Parameters
|
1672
|
+
----------
|
1673
|
+
|
1674
|
+
node : str
|
1675
|
+
Address or Name of the Naeural Edge Protocol edge node that will handle this web app.
|
1676
|
+
|
1677
|
+
name : str
|
1678
|
+
Name of the web app.
|
1679
|
+
|
1680
|
+
signature : str, optional
|
1681
|
+
The signature of the plugin that will be used. Defaults to PLUGIN_SIGNATURES.CUSTOM_WEB_APP_01.
|
1682
|
+
|
1683
|
+
endpoints : list[dict], optional
|
1684
|
+
A list of dictionaries defining the endpoint configuration. Defaults to None.
|
1685
|
+
|
1686
|
+
use_ngrok : bool, optional
|
1687
|
+
If True, will use ngrok to expose the web app. Defaults to True.
|
1688
|
+
|
1689
|
+
|
1690
|
+
"""
|
1659
1691
|
|
1660
1692
|
pipeline: Pipeline = self.create_pipeline(
|
1661
1693
|
node=node,
|
1662
1694
|
name=name,
|
1695
|
+
# default TYPE is "Void"
|
1663
1696
|
)
|
1664
1697
|
|
1665
1698
|
instance = pipeline.create_plugin_instance(
|
@@ -1677,6 +1710,43 @@ class GenericSession(BaseDecentrAIObject):
|
|
1677
1710
|
# end if we have endpoints defined in the call
|
1678
1711
|
|
1679
1712
|
return pipeline, instance
|
1713
|
+
|
1714
|
+
|
1715
|
+
def create_telegram_simple_bot(
|
1716
|
+
self,
|
1717
|
+
*,
|
1718
|
+
node,
|
1719
|
+
name,
|
1720
|
+
signature=PLUGIN_SIGNATURES.CUSTOM_WEB_APP_01,
|
1721
|
+
message_handler=None,
|
1722
|
+
telegram_bot_token=None,
|
1723
|
+
telegram_bot_token_env_key=ENVIRONMENT.TELEGRAM_BOT_TOKEN_ENV_KEY,
|
1724
|
+
**kwargs
|
1725
|
+
):
|
1726
|
+
|
1727
|
+
if telegram_bot_token is None:
|
1728
|
+
telegram_bot_token = os.getenv(telegram_bot_token_env_key)
|
1729
|
+
if telegram_bot_token is None:
|
1730
|
+
message = f"Warning! No Telegram bot token provided as via env {ENVIRONMENT.TELEGRAM_BOT_TOKEN_ENV_KEY} or explicitly as `telegram_bot_token` param."
|
1731
|
+
raise ValueError(message)
|
1732
|
+
|
1733
|
+
b64code = self._get_base64_code(message_handler)
|
1734
|
+
|
1735
|
+
pipeline: Pipeline = self.create_pipeline(
|
1736
|
+
node=node,
|
1737
|
+
name=name,
|
1738
|
+
# default TYPE is "Void"
|
1739
|
+
)
|
1740
|
+
|
1741
|
+
instance = pipeline.create_plugin_instance(
|
1742
|
+
signature=signature,
|
1743
|
+
instance_id=self.log.get_unique_id(),
|
1744
|
+
telegram_bot_token=telegram_bot_token,
|
1745
|
+
message_handler=b64code,
|
1746
|
+
**kwargs
|
1747
|
+
)
|
1748
|
+
return pipeline, instance
|
1749
|
+
|
1680
1750
|
|
1681
1751
|
def broadcast_instance_command_and_wait_for_response_payload(
|
1682
1752
|
self,
|
naeural_client/const/__init__.py
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
class PLUGIN_SIGNATURES:
|
2
|
+
"""
|
3
|
+
This class is used to store the plugin signatures for the different plugins.
|
4
|
+
It is complementary to the PLUGIN_TYPES class.
|
5
|
+
"""
|
6
|
+
NET_MON_01 = 'NET_MON_01'
|
7
|
+
VIEW_SCENE_01 = 'VIEW_SCENE_01'
|
8
|
+
CUSTOM_WEB_APP_01 = 'CUSTOM_CODE_FASTAPI_01'
|
9
|
+
CHAIN_DIST_CUSTOM_JOB_01 = 'PROCESS_REAL_TIME_COLLECTED_DATA_CUSTOM_EXEC_CHAIN_DIST'
|
10
|
+
BASIC_TELEGRAM_BOT_01 = 'BASIC_TELEGRAM_BOT_01'
|
11
|
+
# INSERT_NEW_PLUGIN_HERE
|
@@ -2,3 +2,15 @@ from .net_mon_01_plugin import NetMon01
|
|
2
2
|
from .view_scene_01_plugin import ViewScene01
|
3
3
|
from .custom_web_app_01_plugin import CustomWebApp01
|
4
4
|
from .chain_dist_custom_job_01_plugin import ChainDistCustomJob01
|
5
|
+
from .basic_telegram_bot_01_plugin import BasicTelegramBot01
|
6
|
+
|
7
|
+
|
8
|
+
class PLUGIN_TYPES:
|
9
|
+
"""
|
10
|
+
The plugin types that are available in the default instance
|
11
|
+
"""
|
12
|
+
NET_MON_01 = NetMon01
|
13
|
+
VIEW_SCENE_01 = ViewScene01
|
14
|
+
CUSTOM_WEB_APP_01 = CustomWebApp01
|
15
|
+
CHAIN_DIST_CUSTOM_JOB_01 = ChainDistCustomJob01
|
16
|
+
BASIC_TELEGRAM_BOT_01 = BasicTelegramBot01
|
@@ -1,8 +1,9 @@
|
|
1
1
|
from ...base import Instance
|
2
|
+
from ...const import PLUGIN_SIGNATURES
|
2
3
|
|
3
4
|
|
4
5
|
class ChainDistCustomJob01(Instance):
|
5
|
-
signature =
|
6
|
+
signature = PLUGIN_SIGNATURES.CHAIN_DIST_CUSTOM_JOB_01
|
6
7
|
|
7
8
|
def add_custom_code_callbacks(
|
8
9
|
self,
|
@@ -1,8 +1,8 @@
|
|
1
1
|
from ...base import Instance, Pipeline
|
2
|
-
|
2
|
+
from ...const import PLUGIN_SIGNATURES
|
3
3
|
|
4
4
|
class CustomWebApp01(Instance):
|
5
|
-
signature =
|
5
|
+
signature = PLUGIN_SIGNATURES.CUSTOM_WEB_APP_01
|
6
6
|
|
7
7
|
def get_proposed_endpoints(self):
|
8
8
|
from copy import deepcopy
|
@@ -1,8 +1,8 @@
|
|
1
1
|
from ...base import Instance
|
2
|
-
|
2
|
+
from ...const import PLUGIN_SIGNATURES
|
3
3
|
|
4
4
|
class NetMon01(Instance):
|
5
|
-
signature =
|
5
|
+
signature = PLUGIN_SIGNATURES.NET_MON_01
|
6
6
|
|
7
7
|
def get_node_history(self, node_id=None, node_addr=None, time_window_hours=1, steps=20):
|
8
8
|
"""
|
@@ -180,11 +180,12 @@ class BaseLogger(object):
|
|
180
180
|
if lib_ver == "":
|
181
181
|
lib_ver = __VER__
|
182
182
|
ver = "v{}".format(lib_ver) if lib_ver != "" else ""
|
183
|
-
self.
|
184
|
-
"
|
185
|
-
|
183
|
+
self.P(
|
184
|
+
"NSDK {} initialized on [{}][{}].".format(
|
185
|
+
ver, self.MACHINE_NAME, self.get_processor_platform(),
|
186
186
|
),
|
187
|
-
color='green'
|
187
|
+
color='green',
|
188
|
+
boxed=True,
|
188
189
|
)
|
189
190
|
self.verbose_log(" Timezone: {}.".format(self.timezone),color='green')
|
190
191
|
|
@@ -1,11 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: naeural_client
|
3
|
-
Version: 2.0
|
3
|
+
Version: 2.1.0
|
4
4
|
Summary: `naeural_client` is the Python SDK required for client app development for the Naeural Edge Protocol Edge Protocol framework
|
5
5
|
Project-URL: Homepage, https://github.com/Naeural Edge ProtocolEdgeProtocol/naeural_client
|
6
6
|
Project-URL: Bug Tracker, https://github.com/Naeural Edge ProtocolEdgeProtocol/naeural_client/issues
|
7
7
|
Author-email: Stefan Saraev <saraevstefan@gmail.com>, Andrei Ionut Damian <andrei.damian@me.com>, Cristan Bleotiu <cristibleotiu@gmail.com>
|
8
|
-
License-File: LICENSE
|
9
8
|
Classifier: License :: OSI Approved :: MIT License
|
10
9
|
Classifier: Operating System :: OS Independent
|
11
10
|
Classifier: Programming Language :: Python :: 3
|
@@ -1,10 +1,10 @@
|
|
1
|
-
naeural_client/__init__.py,sha256=
|
2
|
-
naeural_client/_ver.py,sha256=
|
1
|
+
naeural_client/__init__.py,sha256=UKEDGS0wFYyxwmhEAKJGecO2vYbIfRYUP4SQgnK10IE,578
|
2
|
+
naeural_client/_ver.py,sha256=PKIJgoKWB4wskSQA9KvdwJkGx2b-A3tKTo2Rq6DMhdw,330
|
3
3
|
naeural_client/base_decentra_object.py,sha256=qDBpitcyhr1eEXPD8cGFtcNPNf71fqNRsmOEcCpx4sM,4180
|
4
4
|
naeural_client/plugins_manager_mixin.py,sha256=X1JdGLDz0gN1rPnTN_5mJXR8JmqoBFQISJXmPR9yvCo,11106
|
5
5
|
naeural_client/base/__init__.py,sha256=hACh83_cIv7-PwYMM3bQm2IBmNqiHw-3PAfDfAEKz9A,259
|
6
6
|
naeural_client/base/distributed_custom_code_presets.py,sha256=cvz5R88P6Z5V61Ce1vHVVh8bOkgXd6gve_vdESDNAsg,2544
|
7
|
-
naeural_client/base/generic_session.py,sha256=
|
7
|
+
naeural_client/base/generic_session.py,sha256=azhJGCXstzBFQjWqW1z5OjwtSn2nkoPCNsSIcag5hIE,69231
|
8
8
|
naeural_client/base/instance.py,sha256=m6IKOWuT5GsZVSdFNdcR-ImJTpTdHqNoMe8KQlEK3Gc,19970
|
9
9
|
naeural_client/base/pipeline.py,sha256=fWwSNUvvrVvJYzxRBCKTt1f9_pci1hCBiG2LtoyOpMU,57512
|
10
10
|
naeural_client/base/plugin_template.py,sha256=qGaXByd_JZFpjvH9GXNbT7KaitRxIJB6-1IhbKrZjq4,138123
|
@@ -25,20 +25,22 @@ naeural_client/comm/__init__.py,sha256=za3B2HUKNXzYtjElMgGM9xbxNsdQfFY4JB_YzdyFk
|
|
25
25
|
naeural_client/comm/amqp_wrapper.py,sha256=hzj6ih07DnLQy2VSfA88giDIFHaCp9uSdGLTA-IFE4s,8535
|
26
26
|
naeural_client/comm/mqtt_wrapper.py,sha256=Ig3bFZkCbWd4y_Whn2PPa91Z3aLgNbNPau6Tn5yLPZ8,16167
|
27
27
|
naeural_client/const/README.md,sha256=6OHesr-f5NBuuJGryEoi_TCu2XdlhfQYlDKx_IJoXeg,177
|
28
|
-
naeural_client/const/__init__.py,sha256=
|
28
|
+
naeural_client/const/__init__.py,sha256=G7Fa50SpEhAPOnL8_mxgVmJ0Xq1qEncWd75pg2BkiG4,416
|
29
|
+
naeural_client/const/apps.py,sha256=i0MNCM1Wf7QUCB4OKO1vGNUonPs6EsnZV6-XZjknppw,439
|
29
30
|
naeural_client/const/base.py,sha256=V94oaT7xYrrTGxmLJlynxmbFujVX0G9wIfC8TilH5MU,2548
|
30
31
|
naeural_client/const/comms.py,sha256=La6JXWHexH8CfcBCKyT4fCIoeaoZlcm7KtZ57ab4ZgU,2201
|
31
|
-
naeural_client/const/environment.py,sha256=
|
32
|
+
naeural_client/const/environment.py,sha256=bq21Q7e5FXpTNpoek_CUOX5oOZpSJEtNHXiZ79ZHe18,753
|
32
33
|
naeural_client/const/formatter.py,sha256=AW3bWlqf39uaqV4BBUuW95qKYfF2OkkU4f9hy3kSVhM,200
|
33
34
|
naeural_client/const/heartbeat.py,sha256=jGHmKfeHTFOXJaKUT3o_ocnQyF-EpcLeunW-ifkYKfU,2534
|
34
35
|
naeural_client/const/misc.py,sha256=1ypROmZsOyp_8zG2LARwPeo-YfXuyYqZnml0elTP4kw,211
|
35
36
|
naeural_client/const/payload.py,sha256=k24vH9iJIBBPnCXx7HAEuli2fNAETK7h8ZuVKyKLgbk,5725
|
36
37
|
naeural_client/default/__init__.py,sha256=ozU6CMMuWl0LhG8Ae3LrZ65a6tLrptfscVYGf83zjxM,46
|
37
|
-
naeural_client/default/instance/__init__.py,sha256=
|
38
|
-
naeural_client/default/instance/
|
39
|
-
naeural_client/default/instance/
|
40
|
-
naeural_client/default/instance/
|
41
|
-
naeural_client/default/instance/
|
38
|
+
naeural_client/default/instance/__init__.py,sha256=pHR9_5t3xv9ug3nu-8202yW-rqq-KR3C_L5N2xaADTA,548
|
39
|
+
naeural_client/default/instance/basic_telegram_bot_01_plugin.py,sha256=STaIwtGCnEZdvxm7cF9NIQeZL5Zlru1c4cMSHKJc5pQ,159
|
40
|
+
naeural_client/default/instance/chain_dist_custom_job_01_plugin.py,sha256=QtHi3uXKsVs9eyMgbnvBVbMylErhV1Du4X2-7zDL7Y0,1915
|
41
|
+
naeural_client/default/instance/custom_web_app_01_plugin.py,sha256=JblmfDa8ICppHItzEqU2HBSgT0nzZy9NWzgUHQ2sffw,4854
|
42
|
+
naeural_client/default/instance/net_mon_01_plugin.py,sha256=u85i2AiYHkLJnam0wOx-m71hlp0EYyNtk3JwbkOrvHg,1208
|
43
|
+
naeural_client/default/instance/view_scene_01_plugin.py,sha256=5kMhd23kL5AYCdOJzrdCqi2ohoQNvmpv8oE6hWQtUWk,720
|
42
44
|
naeural_client/default/session/mqtt_session.py,sha256=dpQcBhhVZDo458v0IqJMZb1CsTn-TxXhYjNlyJp9Rp8,2414
|
43
45
|
naeural_client/io_formatter/__init__.py,sha256=_wy7c-Z9kgb26jN7uNTDq88G7xZ3wI_ObuQd3QWNPkQ,85
|
44
46
|
naeural_client/io_formatter/io_formatter_manager.py,sha256=MiZ70cGVD6hR99QiEk9wvJ_vADxpI-y2bTb0ITlMNI0,3451
|
@@ -49,7 +51,7 @@ naeural_client/io_formatter/default/a_dummy.py,sha256=qr9eUizQ-NN5jdXVzkaZKMaf9K
|
|
49
51
|
naeural_client/io_formatter/default/aixp1.py,sha256=MX0TeUR4APA-qN3vUC6uzcz8Pssz5lgrQWo7td5Ri1A,3052
|
50
52
|
naeural_client/io_formatter/default/default.py,sha256=gEy78cP2D5s0y8vQh4aHuxqz7D10gGfuiKF311QhrpE,494
|
51
53
|
naeural_client/logging/__init__.py,sha256=b79X45VC6c37u32flKB2GAK9f-RR0ocwP0JDCy0t7QQ,33
|
52
|
-
naeural_client/logging/base_logger.py,sha256=
|
54
|
+
naeural_client/logging/base_logger.py,sha256=tTxzCKOhcqGOtckHK8lQ1nUTNeaBNkeh0_SmDyzX6_Y,65146
|
53
55
|
naeural_client/logging/small_logger.py,sha256=6wljiHP1moCkgohRnr2EX095eM2RtdJ5B3cytbO_Ow4,2887
|
54
56
|
naeural_client/logging/logger_mixins/__init__.py,sha256=yQO7umlRvz63FeWpi-F9GRmC_MOHcNW6R6pwvZZBy3A,600
|
55
57
|
naeural_client/logging/logger_mixins/class_instance_mixin.py,sha256=xUXE2VZgmrlrSrvw0f6GF1jlTnVLeVkIiG0bhlBfq3o,2741
|
@@ -72,7 +74,7 @@ naeural_client/logging/tzlocal/windows_tz.py,sha256=Sv9okktjZJfRGGUOOppsvQuX_eXy
|
|
72
74
|
naeural_client/utils/__init__.py,sha256=mAnke3-MeRzz3nhQvhuHqLnpaaCSmDxicd7Ck9uwpmI,77
|
73
75
|
naeural_client/utils/comm_utils.py,sha256=4cS9llRr_pK_3rNgDcRMCQwYPO0kcNU7AdWy_LtMyCY,1072
|
74
76
|
naeural_client/utils/dotenv.py,sha256=_AgSo35n7EnQv5yDyu7C7i0kHragLJoCGydHjvOkrYY,2008
|
75
|
-
naeural_client-2.0.
|
76
|
-
naeural_client-2.0.
|
77
|
-
naeural_client-2.0.
|
78
|
-
naeural_client-2.0.
|
77
|
+
naeural_client-2.1.0.dist-info/METADATA,sha256=I71wSC0lZI0XDuh8j1mIcyHoxL8Y5SNcB0d_K31BTP0,14457
|
78
|
+
naeural_client-2.1.0.dist-info/WHEEL,sha256=wukiCwsxxsuzcQTdnC_ZWHZECE4wwOh3xCCrap6i6Ts,87
|
79
|
+
naeural_client-2.1.0.dist-info/licenses/LICENSE,sha256=cvOsJVslde4oIaTCadabXnPqZmzcBO2f2zwXZRmJEbE,11311
|
80
|
+
naeural_client-2.1.0.dist-info/RECORD,,
|
File without changes
|