We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Deprecate ignite.contrib.handlers.custom_events.CustomPeriodicEvent
## 🚀 Feature

Custom events `CustomPeriodicEvent` from contrib seem heavy and unusable. 

Idea is to 

- [ ] raise a warning about deprecation since v0.4.0 and removing since v0.5.0 and suggest to use filtered events.
- [ ] remove all docs about them 


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ignite/contrib/handlers/custom_events.py`
Content:
```
1 from ignite.engine import Events, State, EventEnum
2 
3 
4 class CustomPeriodicEvent:
5     """Handler to define a custom periodic events as a number of elapsed iterations/epochs for an engine.
6 
7     When custom periodic event is created and attached to an engine, the following events are fired:
8     1) K iterations is specified:
9     - `Events.ITERATIONS_<K>_STARTED`
10     - `Events.ITERATIONS_<K>_COMPLETED`
11 
12     1) K epochs is specified:
13     - `Events.EPOCHS_<K>_STARTED`
14     - `Events.EPOCHS_<K>_COMPLETED`
15 
16 
17     Examples:
18 
19     .. code-block:: python
20 
21         from ignite.engine import Engine, Events
22         from ignite.contrib.handlers import CustomPeriodicEvent
23 
24         # Let's define an event every 1000 iterations
25         cpe1 = CustomPeriodicEvent(n_iterations=1000)
26         cpe1.attach(trainer)
27 
28         # Let's define an event every 10 epochs
29         cpe2 = CustomPeriodicEvent(n_epochs=10)
30         cpe2.attach(trainer)
31 
32         @trainer.on(cpe1.Events.ITERATIONS_1000_COMPLETED)
33         def on_every_1000_iterations(engine):
34             # run a computation after 1000 iterations
35             # ...
36             print(engine.state.iterations_1000)
37 
38         @trainer.on(cpe2.Events.EPOCHS_10_STARTED)
39         def on_every_10_epochs(engine):
40             # run a computation every 10 epochs
41             # ...
42             print(engine.state.epochs_10)
43 
44 
45     Args:
46         n_iterations (int, optional): number iterations of the custom periodic event
47         n_epochs (int, optional): number iterations of the custom periodic event. Argument is optional, but only one,
48             either n_iterations or n_epochs should defined.
49 
50     """
51 
52     def __init__(self, n_iterations=None, n_epochs=None):
53 
54         if n_iterations is not None and (not isinstance(n_iterations, int) or n_iterations < 1):
55             raise ValueError("Argument n_iterations should be positive integer number")
56 
57         if n_epochs is not None and (not isinstance(n_epochs, int) or n_epochs < 1):
58             raise ValueError("Argument n_epochs should be positive integer number")
59 
60         if (n_iterations is None and n_epochs is None) or (n_iterations and n_epochs):
61             raise ValueError("Either n_iterations or n_epochs should defined")
62 
63         if n_iterations:
64             prefix = "iterations"
65             self.state_attr = "iteration"
66             self.period = n_iterations
67 
68         if n_epochs:
69             prefix = "epochs"
70             self.state_attr = "epoch"
71             self.period = n_epochs
72 
73         self.custom_state_attr = "{}_{}".format(prefix, self.period)
74         event_name = "{}_{}".format(prefix.upper(), self.period)
75         setattr(
76             self,
77             "Events",
78             EventEnum("Events", " ".join(["{}_STARTED".format(event_name), "{}_COMPLETED".format(event_name)])),
79         )
80 
81         # Update State.event_to_attr
82         for e in self.Events:
83             State.event_to_attr[e] = self.custom_state_attr
84 
85         # Create aliases
86         self._periodic_event_started = getattr(self.Events, "{}_STARTED".format(event_name))
87         self._periodic_event_completed = getattr(self.Events, "{}_COMPLETED".format(event_name))
88 
89     def _on_started(self, engine):
90         setattr(engine.state, self.custom_state_attr, 0)
91 
92     def _on_periodic_event_started(self, engine):
93         if getattr(engine.state, self.state_attr) % self.period == 1:
94             setattr(engine.state, self.custom_state_attr, getattr(engine.state, self.custom_state_attr) + 1)
95             engine.fire_event(self._periodic_event_started)
96 
97     def _on_periodic_event_completed(self, engine):
98         if getattr(engine.state, self.state_attr) % self.period == 0:
99             engine.fire_event(self._periodic_event_completed)
100 
101     def attach(self, engine):
102         engine.register_events(*self.Events)
103 
104         engine.add_event_handler(Events.STARTED, self._on_started)
105         engine.add_event_handler(
106             getattr(Events, "{}_STARTED".format(self.state_attr.upper())), self._on_periodic_event_started
107         )
108         engine.add_event_handler(
109             getattr(Events, "{}_COMPLETED".format(self.state_attr.upper())), self._on_periodic_event_completed
110         )
111
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ignite/contrib/handlers/custom_events.py b/ignite/contrib/handlers/custom_events.py
--- a/ignite/contrib/handlers/custom_events.py
+++ b/ignite/contrib/handlers/custom_events.py
@@ -1,8 +1,11 @@
 from ignite.engine import Events, State, EventEnum
+import warnings
 
 
 class CustomPeriodicEvent:
-    """Handler to define a custom periodic events as a number of elapsed iterations/epochs for an engine.
+    """DEPRECATED. Use filtered events instead.
+    Handler to define a custom periodic events as a number of elapsed iterations/epochs
+    for an engine.
 
     When custom periodic event is created and attached to an engine, the following events are fired:
     1) K iterations is specified:
@@ -51,6 +54,11 @@
 
     def __init__(self, n_iterations=None, n_epochs=None):
 
+        warnings.warn(
+            "CustomPeriodicEvent is deprecated since 0.4.0 and will be removed in 0.5.0. Use filtered events instead.",
+            DeprecationWarning,
+        )
+
         if n_iterations is not None and (not isinstance(n_iterations, int) or n_iterations < 1):
             raise ValueError("Argument n_iterations should be positive integer number")

{"golden_diff": "diff --git a/ignite/contrib/handlers/custom_events.py b/ignite/contrib/handlers/custom_events.py\n--- a/ignite/contrib/handlers/custom_events.py\n+++ b/ignite/contrib/handlers/custom_events.py\n@@ -1,8 +1,11 @@\n from ignite.engine import Events, State, EventEnum\n+import warnings\n \n \n class CustomPeriodicEvent:\n-    \"\"\"Handler to define a custom periodic events as a number of elapsed iterations/epochs for an engine.\n+    \"\"\"DEPRECATED. Use filtered events instead.\n+    Handler to define a custom periodic events as a number of elapsed iterations/epochs\n+    for an engine.\n \n     When custom periodic event is created and attached to an engine, the following events are fired:\n     1) K iterations is specified:\n@@ -51,6 +54,11 @@\n \n     def __init__(self, n_iterations=None, n_epochs=None):\n \n+        warnings.warn(\n+            \"CustomPeriodicEvent is deprecated since 0.4.0 and will be removed in 0.5.0. Use filtered events instead.\",\n+            DeprecationWarning,\n+        )\n+\n         if n_iterations is not None and (not isinstance(n_iterations, int) or n_iterations < 1):\n             raise ValueError(\"Argument n_iterations should be positive integer number\")\n", "issue": "Deprecate ignite.contrib.handlers.custom_events.CustomPeriodicEvent\n## \ud83d\ude80 Feature\r\n\r\nCustom events `CustomPeriodicEvent` from contrib seem heavy and unusable. \r\n\r\nIdea is to \r\n\r\n- [ ] raise a warning about deprecation since v0.4.0 and removing since v0.5.0 and suggest to use filtered events.\r\n- [ ] remove all docs about them \r\n\n", "before_files": [{"content": "from ignite.engine import Events, State, EventEnum\n\n\nclass CustomPeriodicEvent:\n    \"\"\"Handler to define a custom periodic events as a number of elapsed iterations/epochs for an engine.\n\n    When custom periodic event is created and attached to an engine, the following events are fired:\n    1) K iterations is specified:\n    - `Events.ITERATIONS_<K>_STARTED`\n    - `Events.ITERATIONS_<K>_COMPLETED`\n\n    1) K epochs is specified:\n    - `Events.EPOCHS_<K>_STARTED`\n    - `Events.EPOCHS_<K>_COMPLETED`\n\n\n    Examples:\n\n    .. code-block:: python\n\n        from ignite.engine import Engine, Events\n        from ignite.contrib.handlers import CustomPeriodicEvent\n\n        # Let's define an event every 1000 iterations\n        cpe1 = CustomPeriodicEvent(n_iterations=1000)\n        cpe1.attach(trainer)\n\n        # Let's define an event every 10 epochs\n        cpe2 = CustomPeriodicEvent(n_epochs=10)\n        cpe2.attach(trainer)\n\n        @trainer.on(cpe1.Events.ITERATIONS_1000_COMPLETED)\n        def on_every_1000_iterations(engine):\n            # run a computation after 1000 iterations\n            # ...\n            print(engine.state.iterations_1000)\n\n        @trainer.on(cpe2.Events.EPOCHS_10_STARTED)\n        def on_every_10_epochs(engine):\n            # run a computation every 10 epochs\n            # ...\n            print(engine.state.epochs_10)\n\n\n    Args:\n        n_iterations (int, optional): number iterations of the custom periodic event\n        n_epochs (int, optional): number iterations of the custom periodic event. Argument is optional, but only one,\n            either n_iterations or n_epochs should defined.\n\n    \"\"\"\n\n    def __init__(self, n_iterations=None, n_epochs=None):\n\n        if n_iterations is not None and (not isinstance(n_iterations, int) or n_iterations < 1):\n            raise ValueError(\"Argument n_iterations should be positive integer number\")\n\n        if n_epochs is not None and (not isinstance(n_epochs, int) or n_epochs < 1):\n            raise ValueError(\"Argument n_epochs should be positive integer number\")\n\n        if (n_iterations is None and n_epochs is None) or (n_iterations and n_epochs):\n            raise ValueError(\"Either n_iterations or n_epochs should defined\")\n\n        if n_iterations:\n            prefix = \"iterations\"\n            self.state_attr = \"iteration\"\n            self.period = n_iterations\n\n        if n_epochs:\n            prefix = \"epochs\"\n            self.state_attr = \"epoch\"\n            self.period = n_epochs\n\n        self.custom_state_attr = \"{}_{}\".format(prefix, self.period)\n        event_name = \"{}_{}\".format(prefix.upper(), self.period)\n        setattr(\n            self,\n            \"Events\",\n            EventEnum(\"Events\", \" \".join([\"{}_STARTED\".format(event_name), \"{}_COMPLETED\".format(event_name)])),\n        )\n\n        # Update State.event_to_attr\n        for e in self.Events:\n            State.event_to_attr[e] = self.custom_state_attr\n\n        # Create aliases\n        self._periodic_event_started = getattr(self.Events, \"{}_STARTED\".format(event_name))\n        self._periodic_event_completed = getattr(self.Events, \"{}_COMPLETED\".format(event_name))\n\n    def _on_started(self, engine):\n        setattr(engine.state, self.custom_state_attr, 0)\n\n    def _on_periodic_event_started(self, engine):\n        if getattr(engine.state, self.state_attr) % self.period == 1:\n            setattr(engine.state, self.custom_state_attr, getattr(engine.state, self.custom_state_attr) + 1)\n            engine.fire_event(self._periodic_event_started)\n\n    def _on_periodic_event_completed(self, engine):\n        if getattr(engine.state, self.state_attr) % self.period == 0:\n            engine.fire_event(self._periodic_event_completed)\n\n    def attach(self, engine):\n        engine.register_events(*self.Events)\n\n        engine.add_event_handler(Events.STARTED, self._on_started)\n        engine.add_event_handler(\n            getattr(Events, \"{}_STARTED\".format(self.state_attr.upper())), self._on_periodic_event_started\n        )\n        engine.add_event_handler(\n            getattr(Events, \"{}_COMPLETED\".format(self.state_attr.upper())), self._on_periodic_event_completed\n        )\n", "path": "ignite/contrib/handlers/custom_events.py"}], "after_files": [{"content": "from ignite.engine import Events, State, EventEnum\nimport warnings\n\n\nclass CustomPeriodicEvent:\n    \"\"\"DEPRECATED. Use filtered events instead.\n    Handler to define a custom periodic events as a number of elapsed iterations/epochs\n    for an engine.\n\n    When custom periodic event is created and attached to an engine, the following events are fired:\n    1) K iterations is specified:\n    - `Events.ITERATIONS_<K>_STARTED`\n    - `Events.ITERATIONS_<K>_COMPLETED`\n\n    1) K epochs is specified:\n    - `Events.EPOCHS_<K>_STARTED`\n    - `Events.EPOCHS_<K>_COMPLETED`\n\n\n    Examples:\n\n    .. code-block:: python\n\n        from ignite.engine import Engine, Events\n        from ignite.contrib.handlers import CustomPeriodicEvent\n\n        # Let's define an event every 1000 iterations\n        cpe1 = CustomPeriodicEvent(n_iterations=1000)\n        cpe1.attach(trainer)\n\n        # Let's define an event every 10 epochs\n        cpe2 = CustomPeriodicEvent(n_epochs=10)\n        cpe2.attach(trainer)\n\n        @trainer.on(cpe1.Events.ITERATIONS_1000_COMPLETED)\n        def on_every_1000_iterations(engine):\n            # run a computation after 1000 iterations\n            # ...\n            print(engine.state.iterations_1000)\n\n        @trainer.on(cpe2.Events.EPOCHS_10_STARTED)\n        def on_every_10_epochs(engine):\n            # run a computation every 10 epochs\n            # ...\n            print(engine.state.epochs_10)\n\n\n    Args:\n        n_iterations (int, optional): number iterations of the custom periodic event\n        n_epochs (int, optional): number iterations of the custom periodic event. Argument is optional, but only one,\n            either n_iterations or n_epochs should defined.\n\n    \"\"\"\n\n    def __init__(self, n_iterations=None, n_epochs=None):\n\n        warnings.warn(\n            \"CustomPeriodicEvent is deprecated since 0.4.0 and will be removed in 0.5.0. Use filtered events instead.\",\n            DeprecationWarning,\n        )\n\n        if n_iterations is not None and (not isinstance(n_iterations, int) or n_iterations < 1):\n            raise ValueError(\"Argument n_iterations should be positive integer number\")\n\n        if n_epochs is not None and (not isinstance(n_epochs, int) or n_epochs < 1):\n            raise ValueError(\"Argument n_epochs should be positive integer number\")\n\n        if (n_iterations is None and n_epochs is None) or (n_iterations and n_epochs):\n            raise ValueError(\"Either n_iterations or n_epochs should defined\")\n\n        if n_iterations:\n            prefix = \"iterations\"\n            self.state_attr = \"iteration\"\n            self.period = n_iterations\n\n        if n_epochs:\n            prefix = \"epochs\"\n            self.state_attr = \"epoch\"\n            self.period = n_epochs\n\n        self.custom_state_attr = \"{}_{}\".format(prefix, self.period)\n        event_name = \"{}_{}\".format(prefix.upper(), self.period)\n        setattr(\n            self,\n            \"Events\",\n            EventEnum(\"Events\", \" \".join([\"{}_STARTED\".format(event_name), \"{}_COMPLETED\".format(event_name)])),\n        )\n\n        # Update State.event_to_attr\n        for e in self.Events:\n            State.event_to_attr[e] = self.custom_state_attr\n\n        # Create aliases\n        self._periodic_event_started = getattr(self.Events, \"{}_STARTED\".format(event_name))\n        self._periodic_event_completed = getattr(self.Events, \"{}_COMPLETED\".format(event_name))\n\n    def _on_started(self, engine):\n        setattr(engine.state, self.custom_state_attr, 0)\n\n    def _on_periodic_event_started(self, engine):\n        if getattr(engine.state, self.state_attr) % self.period == 1:\n            setattr(engine.state, self.custom_state_attr, getattr(engine.state, self.custom_state_attr) + 1)\n            engine.fire_event(self._periodic_event_started)\n\n    def _on_periodic_event_completed(self, engine):\n        if getattr(engine.state, self.state_attr) % self.period == 0:\n            engine.fire_event(self._periodic_event_completed)\n\n    def attach(self, engine):\n        engine.register_events(*self.Events)\n\n        engine.add_event_handler(Events.STARTED, self._on_started)\n        engine.add_event_handler(\n            getattr(Events, \"{}_STARTED\".format(self.state_attr.upper())), self._on_periodic_event_started\n        )\n        engine.add_event_handler(\n            getattr(Events, \"{}_COMPLETED\".format(self.state_attr.upper())), self._on_periodic_event_completed\n        )\n", "path": "ignite/contrib/handlers/custom_events.py"}]}