coveralls: 
[![Coverage Status](https://coveralls.io/builds/9818486/badge)](https://coveralls.io/builds/9818486)

Coverage decreased (-0.1%) to 83.091% when pulling **9d1e2b94ba2b130cd99f0993bf7a4fc37bf1ae19 on feature/activate_deactivate_spout** into **266004865f5c9db2b8fb96e1b4c0217f19aefc9a on master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/9818530/badge)](https://coveralls.io/builds/9818530)

Coverage decreased (-0.1%) to 83.091% when pulling **552fe17df9b072ac8721e4bad135651165afd0e5 on feature/activate_deactivate_spout** into **266004865f5c9db2b8fb96e1b4c0217f19aefc9a on master**.

diff --git a/pystorm/spout.py b/pystorm/spout.py
index 47cfd37..169fbd1 100644
--- a/pystorm/spout.py
+++ b/pystorm/spout.py
@@ -76,6 +76,23 @@ class Spout(Component):
                                        direct_task=direct_task,
                                        need_task_ids=need_task_ids)
 
+    def activate(self):
+        """Called when the Spout has been activated after being deactivated.
+
+        .. note::
+            This requires at least Storm 1.1.0.
+        """
+        pass
+
+
+    def deactivate(self):
+        """Called when the Spout has been deactivated.
+
+        .. note::
+            This requires at least Storm 1.1.0.
+        """
+        pass
+
     def _run(self):
         """The inside of ``run``'s infinite loop.
 
@@ -88,6 +105,10 @@ class Spout(Component):
             self.ack(cmd['id'])
         elif cmd['command'] == 'fail':
             self.fail(cmd['id'])
+        elif cmd['command'] == 'activate':
+            self.activate()
+        elif cmd['command'] == 'deactivate':
+            self.deactivate()
         else:
             self.logger.error('Received invalid command from Storm: %r', cmd)
         self.send_message({'command': 'sync'})

Support Spout activate/deactivate
_From @andrewkcarter on January 23, 2017 21:51_

Storm has recently exposed the activate and deactivate events via the `ShellSpout`. I would like to see these made available in streamparse for storm's next release.

https://github.com/apache/storm/pull/1096

_Copied from original issue: Parsely/streamparse#351_
diff --git a/test/pystorm/test_spout.py b/test/pystorm/test_spout.py
index ed84b16..25c762a 100644
--- a/test/pystorm/test_spout.py
+++ b/test/pystorm/test_spout.py
@@ -87,6 +87,22 @@ class SpoutTests(unittest.TestCase):
         read_command_mock.assert_called_with(self.spout)
         self.assertEqual(next_tuple_mock.call_count, 1)
 
+    @patch.object(Spout, 'read_command', autospec=True,
+                  return_value={'command': 'activate', 'id': 1234})
+    @patch.object(Spout, 'activate', autospec=True)
+    def test_activate(self, activate_mock, read_command_mock):
+        self.spout._run()
+        read_command_mock.assert_called_with(self.spout)
+        self.assertEqual(activate_mock.call_count, 1)
+
+    @patch.object(Spout, 'read_command', autospec=True,
+                  return_value={'command': 'deactivate', 'id': 1234})
+    @patch.object(Spout, 'deactivate', autospec=True)
+    def test_deactivate(self, deactivate_mock, read_command_mock):
+        self.spout._run()
+        read_command_mock.assert_called_with(self.spout)
+        self.assertEqual(deactivate_mock.call_count, 1)
+
 
 class ReliableSpoutTests(unittest.TestCase):
 

pip install -e .[all]
parse_log_pytest
requirements.txt
mock pytest unittest2
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup==1.2.2
iniconfig==2.1.0
linecache2==1.0.0
mock==5.2.0
msgpack-python==0.5.6
packaging==24.2
pluggy==1.5.0
-e git+https://github.com/pystorm/pystorm.git@266004865f5c9db2b8fb96e1b4c0217f19aefc9a#egg=pystorm
pytest==8.3.5
pytest-timeout==2.3.1
simplejson==3.20.1
six==1.17.0
tomli==2.2.1
traceback2==1.4.0
unittest2==1.1.0

name: pystorm
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - argparse==1.4.0
      - exceptiongroup==1.2.2
      - iniconfig==2.1.0
      - linecache2==1.0.0
      - mock==5.2.0
      - msgpack-python==0.5.6
      - packaging==24.2
      - pluggy==1.5.0
      - pytest==8.3.5
      - pytest-timeout==2.3.1
      - simplejson==3.20.1
      - six==1.17.0
      - tomli==2.2.1
      - traceback2==1.4.0
      - unittest2==1.1.0
prefix: /opt/conda/envs/pystorm

test/pystorm/test_spout.py::SpoutTests::test_activate test/pystorm/test_spout.py::SpoutTests::test_deactivate
test/pystorm/test_spout.py::SpoutTests::test_ack test/pystorm/test_spout.py::SpoutTests::test_emit test/pystorm/test_spout.py::SpoutTests::test_fail test/pystorm/test_spout.py::SpoutTests::test_next_tuple test/pystorm/test_spout.py::ReliableSpoutTests::test_ack test/pystorm/test_spout.py::ReliableSpoutTests::test_emit_reliable test/pystorm/test_spout.py::ReliableSpoutTests::test_emit_reliable_direct test/pystorm/test_spout.py::ReliableSpoutTests::test_emit_unreliable test/pystorm/test_spout.py::ReliableSpoutTests::test_fail_above_limit test/pystorm/test_spout.py::ReliableSpoutTests::test_fail_below_limit
pystorm/spout.py
pystorm/spout.py