diff --git a/.github/workflows/install-tests.yml b/.github/workflows/install-tests.yml index c8eee3da654eb75c249730aca93ed6f5bd910c18_LmdpdGh1Yi93b3JrZmxvd3MvaW5zdGFsbC10ZXN0cy55bWw=..02ad93304e140483efd2658b92851709112da348_LmdpdGh1Yi93b3JrZmxvd3MvaW5zdGFsbC10ZXN0cy55bWw= 100644 --- a/.github/workflows/install-tests.yml +++ b/.github/workflows/install-tests.yml @@ -3,7 +3,6 @@ push: branches: - master - - gh159-actions-unit-testing pull_request: jobs: diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index c8eee3da654eb75c249730aca93ed6f5bd910c18_LmdpdGh1Yi93b3JrZmxvd3MvdW5pdC10ZXN0cy55bWw=..02ad93304e140483efd2658b92851709112da348_LmdpdGh1Yi93b3JrZmxvd3MvdW5pdC10ZXN0cy55bWw= 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -3,7 +3,6 @@ push: branches: - master - - gh159-actions-unit-testing pull_request: jobs: @@ -17,7 +16,7 @@ # macos-latest: has some issues in SeyfSV/setup-mqclient@master action #environment: ['ubuntu-latest', 'macos-latest', 'windows-latest'] python-version: [2.7, 3.5, 3.6, 3.7, 3.8] - mq-client-version: [9.1.4.0] + mq-client-version: [9.1.5.0] services: mq: diff --git a/code/pymqi/__init__.py b/code/pymqi/__init__.py index c8eee3da654eb75c249730aca93ed6f5bd910c18_Y29kZS9weW1xaS9fX2luaXRfXy5weQ==..02ad93304e140483efd2658b92851709112da348_Y29kZS9weW1xaS9fX2luaXRfXy5weQ== 100644 --- a/code/pymqi/__init__.py +++ b/code/pymqi/__init__.py @@ -2283,6 +2283,34 @@ msg_desc.unpack(rv[0]) put_opts.unpack(rv[1]) + def pub_rfh2(self, msg, *opts): + # type: (bytes, *MQOpts) -> None + """pub_rfh2(msg[, mDesc ,putOpts, [rfh2_header, ]]) + Put a RFH2 message. opts[2] is a list of RFH2 headers. + MQMD and RFH2's must be correct. + """ + ensure_not_unicode(msg) # Python 3 bytes check + + rfh2_buff = b'' + if len(opts) >= 3: + if opts[2] is not None: + if not isinstance(opts[2], list): + raise TypeError('Third item of opts should be a list.') + encoding = CMQC.MQENC_NATIVE + if opts[0] is not None: + mqmd = opts[0] + encoding = mqmd['Encoding'] + + for rfh2_header in opts[2]: + if rfh2_header is not None: + rfh2_buff = rfh2_buff + rfh2_header.pack(encoding) + encoding = rfh2_header['Encoding'] + + msg = rfh2_buff + msg + self.pub(msg, *opts[0:2]) + else: + self.pub(msg, *opts) + def sub(self, *opts): """ Subscribe to the topic and return a Subscription object. A subscription to a topic can be made using an existing queue, either @@ -2350,6 +2378,12 @@ """ return self.sub_queue.get(max_length, *opts) + def get_rfh2(self, max_length=None, *opts): + # type: (int, *MQOpts) -> bytes + """ Get a publication from the Queue. + """ + return self.sub_queue.get_rfh2(max_length, *opts) + def sub(self, sub_desc=None, sub_queue=None, sub_name=None, sub_opts=None, topic_name=None, topic_string=None): """ Subscribe to a topic, alter or resume a subscription. diff --git a/code/tests/test_pubsub.py b/code/tests/test_pubsub.py index c8eee3da654eb75c249730aca93ed6f5bd910c18_Y29kZS90ZXN0cy90ZXN0X3B1YnN1Yi5weQ==..02ad93304e140483efd2658b92851709112da348_Y29kZS90ZXN0cy90ZXN0X3B1YnN1Yi5weQ== 100644 --- a/code/tests/test_pubsub.py +++ b/code/tests/test_pubsub.py @@ -106,6 +106,14 @@ topic.pub(msg, *opts) topic.close() + def pub_rfh2(self, msg, topic_string, *opts): + topic = pymqi.Topic(self.qmgr, topic_string=topic_string) + topic.open(open_opts=pymqi.CMQC.MQOO_OUTPUT) + if isinstance(msg, str) and not isinstance(msg, bytes): + raise AttributeError('msg must be bytes (not str) to publish to topic.') # py3 + topic.pub_rfh2(msg, *opts) + topic.close() + def create_api_subscription(self): return pymqi.Subscription(self.qmgr) @@ -208,6 +216,48 @@ sub.close(sub_close_options=0, close_sub_queue=True) self.assertEqual(data, msg) + def test_pubsub_api_managed_non_durable_rfh2(self): + topic_string = self.topic_string_template.format(type="API_RFH2", destination="MANAGED", durable="NON DURABLE") + subname = self.subname_template.format(type="Api_rfh2", destination="Managed", durable="Non Durable") + msg = self.msg_format(topic_string=topic_string) + sub_desc = self.get_subscription_descriptor(subname, topic_string, + pymqi.CMQC.MQSO_CREATE + pymqi.CMQC.MQSO_MANAGED) + # register Subscription + sub = self.create_api_subscription() + self.sub_desc_list = [(sub, sub_desc, None)] + sub.sub(sub_desc=sub_desc) + + # publish (put) + put_mqmd = pymqi.md( + Format=pymqi.CMQC.MQFMT_RF_HEADER_2, + Encoding=273, + CodedCharSetId=1208) + + put_opts = pymqi.pmo() + + put_rfh2 = pymqi.RFH2(StrucId=pymqi.CMQC.MQRFH_STRUC_ID, + Version=pymqi.CMQC.MQRFH_VERSION_2, + StrucLength=188, + Encoding=273, + CodedCharSetId=1208, + Format=pymqi.CMQC.MQFMT_STRING, + Flags=0, + NameValueCCSID=1208) + put_rfh2.add_folder(b"<psc><Command>RegSub</Command><Topic>$topictree/topiccat/topic</Topic><QMgrName>DebugQM</QMgrName><QName>PUBOUT</QName><RegOpt>PersAsPub</RegOpt></psc>") + put_rfh2.add_folder(b"<testFolder><testVar>testValue</testVar></testFolder>") + put_rfh2.add_folder(b"<mcd><Msd>xmlnsc</Msd></mcd>") + + self.pub_rfh2(msg, topic_string, put_mqmd, put_opts, [put_rfh2]) + get_opts = pymqi.GMO(Version=pymqi.CMQC.MQGMO_VERSION_4, + WaitInterval=15000, + Options=pymqi.CMQC.MQGMO_NO_SYNCPOINT + \ + pymqi.CMQC.MQGMO_FAIL_IF_QUIESCING + \ + pymqi.CMQC.MQGMO_WAIT) + get_rfh2_list = [] + data = sub.get_rfh2(None, pymqi.md(Version=pymqi.CMQC.MQMD_VERSION_2), get_opts, get_rfh2_list) + sub.close(sub_close_options=0, close_sub_queue=True) + self.assertEqual(data, msg) + def test_pubsub_admin_managed(self): topic_string = self.topic_string_template.format(type="ADMIN", destination="MANAGED", durable="DURABLE") subname = self.subname_template.format(type="Admin", destination="Managed", durable="Durable") @@ -275,7 +325,7 @@ data = sub.get(None, pymqi.md(), get_opts) sub.close(sub_close_options=0, close_sub_queue=True) self.assertEqual(data, msg) - + def test_pubsub_admin_provided(self): topic_string = self.topic_string_template.format(type="ADMIN", destination="PROVIDED", durable="DURABLE") subname = self.subname_template.format(type="Admin", destination="Provided", durable="Durable") @@ -290,7 +340,7 @@ # register Subscription self.create_admin_subscription(pymqi.CMQC.MQDC_PROVIDED, subname, queue_name, topic_string) sub = pymqi.Subscription(self.qmgr) - + sub.sub(sub_desc=sub_desc, sub_queue=sub_queue) self.sub_desc_list = [(sub, sub_desc, queue_name)] # publish (put) @@ -334,7 +384,7 @@ """ topic_string = self.topic_string_template.format(type="API", destination="MANAGED", durable="NON DURABLE") subname = self.subname_template.format(type="Api", destination="Managed", durable="Non Durable") - messages = ["ascii", unicode("Euro sign: �", "iso-8859-15"), unicode("Uml�ut", "iso-8859-15"), unicodedata.lookup("INFINITY")] + messages = ["ascii", unicode("Euro sign: �", "iso-8859-15"), unicode("Uml�ut", "iso-8859-15"), unicodedata.lookup("INFINITY")] md = pymqi.md() # setting this means the message is entirely character data