slenas: @capelastegui @bezes guys could you please check my reply above and comment? As I'm seeing it, for me "path" is not exactly an optional parameter...
codecov-io: # [Codecov](https://codecov.io/gh/sky-uk/anticipy/pull/71?src=pr&el=h1) Report
> Merging [#71](https://codecov.io/gh/sky-uk/anticipy/pull/71?src=pr&el=desc) into [master](https://codecov.io/gh/sky-uk/anticipy/commit/abf46202f20ef148073903593d2ec571ca8b0793?src=pr&el=desc) will **decrease** coverage by `0.24%`.
> The diff coverage is `37.5%`.

[![Impacted file tree graph](https://codecov.io/gh/sky-uk/anticipy/pull/71/graphs/tree.svg?width=650&token=QEpdZ0YcB4&height=150&src=pr)](https://codecov.io/gh/sky-uk/anticipy/pull/71?src=pr&el=tree)

```diff
@@            Coverage Diff            @@
##           master     #71      +/-   ##
=========================================
- Coverage   84.85%   84.6%   -0.25%     
=========================================
  Files           6       6              
  Lines        1373    1377       +4     
=========================================
  Hits         1165    1165              
- Misses        208     212       +4
```


| [Impacted Files](https://codecov.io/gh/sky-uk/anticipy/pull/71?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [anticipy/app.py](https://codecov.io/gh/sky-uk/anticipy/pull/71/diff?src=pr&el=tree#diff-YW50aWNpcHkvYXBwLnB5) | `0% <0%> (ø)` | :arrow_up: |
| [anticipy/forecast\_plot.py](https://codecov.io/gh/sky-uk/anticipy/pull/71/diff?src=pr&el=tree#diff-YW50aWNpcHkvZm9yZWNhc3RfcGxvdC5weQ==) | `85.33% <42.85%> (-2.17%)` | :arrow_down: |
| [anticipy/forecast\_models.py](https://codecov.io/gh/sky-uk/anticipy/pull/71/diff?src=pr&el=tree#diff-YW50aWNpcHkvZm9yZWNhc3RfbW9kZWxzLnB5) | `86.84% <0%> (-0.05%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/sky-uk/anticipy/pull/71?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/sky-uk/anticipy/pull/71?src=pr&el=footer). Last update [abf4620...2782ecd](https://codecov.io/gh/sky-uk/anticipy/pull/71?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/anticipy/app.py b/anticipy/app.py
index 91ab7ff..05511cc 100644
--- a/anticipy/app.py
+++ b/anticipy/app.py
@@ -95,9 +95,8 @@ def run_forecast_app(path_in, path_out=None, forecast_years=2.0,
     df_metadata.to_csv(path_metadata, index=False)
 
     try:
-        forecast_plot.plot_forecast(
-            df_result, path_plot, output=output_format, width=1920,
-            height=1080)
+        forecast_plot.plot_forecast(df_result, output_format, path_plot,
+                                    width=1920, height=1080)
     except AssertionError:
         logger.info("Couldn't generate plot - The required plotting library "
                     "is not installed")
diff --git a/anticipy/forecast_plot.py b/anticipy/forecast_plot.py
index 7427ccc..889a667 100644
--- a/anticipy/forecast_plot.py
+++ b/anticipy/forecast_plot.py
@@ -322,9 +322,8 @@ def _plotly_forecast_create(df_fcast, subplots, sources, nrows, ncols,
     return fig
 
 
-def plot_forecast(df_fcast, path, output='html', width=None,
-                  height=None, title=None, dpi=70, show_legend=True,
-                  auto_open=False):
+def plot_forecast(df_fcast, output, path=None, width=None, height=None,
+                  title=None, dpi=70, show_legend=True, auto_open=False):
     """
     Generates matplotlib or plotly plot and saves it respectively as png or
     html
@@ -334,12 +333,13 @@ def plot_forecast(df_fcast, path, output='html', width=None,
         | - date (timestamp)
         | - model (str) : ID for the forecast model
         | - y (float) : Value of the time series in that sample
-        | - is_actuals (bool) : True for actuals samples, False for forecasted samples # noqa
+        | - is_actuals (bool) : True for actuals samples, False for
+        |                       forecasted samples # noqa
     :type df_fcast: pandas.DataFrame
+    :param output: Indicates the output type (html=Default, png or jupyter)
+    :type output: basestring
     :param path: File path for output
     :type path: basestring
-    :param output: ...
-    :type output: ...
     :param width: Image width, in pixels
     :type width: int
     :param height: Image height, in pixels
@@ -353,10 +353,17 @@ def plot_forecast(df_fcast, path, output='html', width=None,
     :param auto_open: Indicates whether the output will be displayed
                       automatically
     :type auto_open: bool
+
+    :return: Success or failure code.
+    :rtype: int
     """
 
     assert isinstance(df_fcast, pd.DataFrame)
 
+    if not path and (output == 'html' or output == 'png'):
+        logger.error('No export path provided.')
+        return 1
+
     if 'source' in df_fcast.columns:
         subplots = True
         sources = df_fcast.loc[df_fcast['is_actuals'], 'source'].unique()
@@ -375,6 +382,7 @@ def plot_forecast(df_fcast, path, output='html', width=None,
             fig = _matplotlib_forecast_create(df_fcast, subplots, sources,
                                               nrows, ncols, width, height,
                                               title, dpi, show_legend)
+
             path = '{}.png'.format(path)
             dirname, fname = os.path.split(path)
             if not os.path.exists(dirname):
@@ -412,5 +420,6 @@ def plot_forecast(df_fcast, path, output='html', width=None,
     else:
         logger.error('Wrong exporting format provided. Either png, html or '
                      'jupyter formats are supported at the moment.')
-        return 0
+        return 1
 
+    return 0
diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst
index df92fa1..5278592 100755
--- a/docs/source/tutorial.rst
+++ b/docs/source/tutorial.rst
@@ -41,19 +41,20 @@ The tool automatically selects the best model from a list of defaults - in this
 users can instead provide their preferred model or lists of candidate models, as explained in :ref:`models`.
 
 You can plot the forecast output using the functions in :py:mod:`forecast_plot`.
-:py:func:`anticipy.forecast_plot.plot_forecast_save` saves the plot as a file. If you use
-nsa.forecast in a Jupyter notebook, :py:func:`anticipy.forecast_plot.plot_forecast` shows the plot as the output of
-a notebook cell. The plot looks as follows:
+:py:func:`anticipy.forecast_plot.plot_forecast` saves the plot as a file or
+exports it to a jupyter notebook. The plot looks as follows:
 
 .. image:: resources/tutorial-forecast1.png
 
 The code to generate the plot is::
 
-    path_tutorial_plot = 'plot-tutorial.png'
+    path_tutorial_plot = 'plot-tutorial'
     # Save plot as a file
-    forecast_plot.plot_forecast_save(df_forecast, path_tutorial_plot,width=350, height=240, title='Tutorial Forecast')
+    forecast_plot.plot_forecast(df_forecast, output='html',
+    path=path_tutorial_plot, width=350, height=240, title='Tutorial Forecast')
     # Show plot in a jupyter notebook
-    forecast_plot.plot_forecast(df_forecast, width=350, height=240, title='Tutorial Forecast')
+    forecast_plot.plot_forecast(df_forecast, output='jupyter', width=350,
+    height=240, title='Tutorial Forecast')
 
 
 

Make path an optional input variable in forecast_plot.plot_forecast()
When using `output='jupyter'`, no path is needed.
When `output='png'` or `output='html'` we need to verify path is not empty.
diff --git a/tests/test_forecast_plot.py b/tests/test_forecast_plot.py
index cc97abb..c50a2cf 100644
--- a/tests/test_forecast_plot.py
+++ b/tests/test_forecast_plot.py
@@ -96,59 +96,85 @@ class TestForecastPlot(PandasTest):
         if not forecast_plot._matplotlib_imported:
             self.skipTest('Test skipped as Matplotlib is not installed...')
         path = get_file_path(base_folder, 'test_mpl')
-        forecast_plot.plot_forecast(df_forecast, path, 'png', 900, 600,
+        forecast_plot.plot_forecast(df_forecast, 'png', path, 900, 600,
                                     'Test Plot', show_legend=False,
                                     auto_open=False)
         self.assertTrue(os.path.isfile('{}.png'.format(path)))
 
         path = get_file_path(base_folder, 'test_facet_mpl')
-        forecast_plot.plot_forecast(df_forecast_facet, path, 'png', 1200, 900,
+        forecast_plot.plot_forecast(df_forecast_facet, 'png', path, 1200, 900,
                                     'Test Plot', show_legend=True,
                                     auto_open=False)
         self.assertTrue(os.path.isfile('{}.png'.format(path)))
 
         # Repeat test with prediction intervals
         path = get_file_path(base_folder, 'test_pi_mpl')
-        forecast_plot.plot_forecast(df_forecast_pi, path, 'png', 900, 600,
+        forecast_plot.plot_forecast(df_forecast_pi, 'png', path, 900, 600,
                                     'Test Plot', show_legend=True,
                                     auto_open=False)
         self.assertTrue(os.path.isfile('{}.png'.format(path)))
 
         path = get_file_path(base_folder, 'test_pi_facet_mpl')
-        forecast_plot.plot_forecast(df_forecast_pi_facet, path, 'png', 1200,
+        forecast_plot.plot_forecast(df_forecast_pi_facet, 'png', path, 1200,
                                     900, 'Test Plot', show_legend=True,
                                     auto_open=False)
         self.assertTrue(os.path.isfile('{}.png'.format(path)))
 
+        # Test the case where a 'None' or an empty path is provided
+        self.assertTrue(forecast_plot.plot_forecast(df_forecast_pi_facet,
+                                                    'png', None, 1200, 900,
+                                                    'Test Plot',
+                                                    show_legend=True,
+                                                    auto_open=False))
+
+        self.assertTrue(forecast_plot.plot_forecast(df_forecast_pi_facet,
+                                                    'png', '', 1200, 900,
+                                                    'Test Plot',
+                                                    show_legend=True,
+                                                    auto_open=False))
+
     def test_plot_forecast_html(self):
         if not forecast_plot._plotly_imported:
             self.skipTest('Test skipped as Plotly is not installed...')
 
         path = get_file_path(base_folder, 'test_plotly')
-        forecast_plot.plot_forecast(df_forecast, path, 'html', 900, 600,
+        forecast_plot.plot_forecast(df_forecast, 'html', path, 900, 600,
                                     'Test Plot', show_legend=False,
                                     auto_open=False)
         self.assertTrue(os.path.isfile('{}.html'.format(path)))
 
         path = get_file_path(base_folder, 'test_facet_plotly')
-        forecast_plot.plot_forecast(df_forecast_facet, path, 'html', 1900,
+        forecast_plot.plot_forecast(df_forecast_facet, 'html', path, 1900,
                                     1200, 'Test Plot', show_legend=False,
                                     auto_open=False)
         self.assertTrue(os.path.isfile('{}.html'.format(path)))
 
         # Repeat test with prediction intervals
         path = get_file_path(base_folder, 'test_pi_plotly')
-        forecast_plot.plot_forecast(df_forecast_pi, path, 'html', 900, 600,
+        forecast_plot.plot_forecast(df_forecast_pi, 'html', path, 900, 600,
                                     'Test Plot', show_legend=False,
                                     auto_open=False)
         self.assertTrue(os.path.isfile('{}.html'.format(path)))
 
         path = get_file_path(base_folder, 'test_pi_facet_plotly')
-        forecast_plot.plot_forecast(df_forecast_pi_facet, path, 'html', 1900,
+        forecast_plot.plot_forecast(df_forecast_pi_facet, 'html', path, 1900,
                                     1200, 'Test Plot', show_legend=False,
                                     auto_open=False)
         self.assertTrue(os.path.isfile('{}.html'.format(path)))
 
+        # Test the case where a 'None' or an empty path is provided
+        self.assertTrue(forecast_plot.plot_forecast(df_forecast_pi_facet,
+                                                    'html', None, 1900, 1200,
+                                                    'Test Plot',
+                                                    show_legend=False,
+                                                    auto_open=False))
+
+        self.assertTrue(forecast_plot.plot_forecast(df_forecast_pi_facet,
+                                                    'html', '', 1900, 1200,
+                                                    'Test Plot',
+                                                    show_legend=False,
+                                                    auto_open=False))
+
     def test_plot_forecast_jupyter(self):
         if (not forecast_plot._plotly_imported) or \
                 (not forecast_plot._ipython_imported):
@@ -156,7 +182,6 @@ class TestForecastPlot(PandasTest):
                           'not installed...')
 
         forecast_plot.plot_forecast(df_forecast_pi_facet,
-                                    path=None,
                                     output='jupyter',
                                     width=1900,
                                     height=1200,

pip install -e .[extras]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.6
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/sky-uk/anticipy.git@abf46202f20ef148073903593d2ec571ca8b0793#egg=anticipy
attrs==22.2.0
backcall==0.2.0
certifi==2021.5.30
cycler==0.11.0
decorator==5.1.1
importlib-metadata==4.8.3
iniconfig==1.1.1
ipython==7.16.3
ipython-genutils==0.2.0
jedi==0.17.2
kiwisolver==1.3.1
matplotlib==3.3.4
numpy==1.19.5
packaging==21.3
pandas==1.1.5
parso==0.7.1
pexpect==4.9.0
pickleshare==0.7.5
Pillow==8.4.0
plotly==5.18.0
pluggy==1.0.0
prompt-toolkit==3.0.36
ptyprocess==0.7.0
py==1.11.0
Pygments==2.14.0
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
scipy==1.5.4
six==1.17.0
tenacity==8.2.2
tomli==1.2.3
traitlets==4.3.3
typing_extensions==4.1.1
wcwidth==0.2.13
zipp==3.6.0

name: anticipy
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
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - 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=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - backcall==0.2.0
      - cycler==0.11.0
      - decorator==5.1.1
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - ipython==7.16.3
      - ipython-genutils==0.2.0
      - jedi==0.17.2
      - kiwisolver==1.3.1
      - matplotlib==3.3.4
      - numpy==1.19.5
      - packaging==21.3
      - pandas==1.1.5
      - parso==0.7.1
      - pexpect==4.9.0
      - pickleshare==0.7.5
      - pillow==8.4.0
      - plotly==5.18.0
      - pluggy==1.0.0
      - prompt-toolkit==3.0.36
      - ptyprocess==0.7.0
      - py==1.11.0
      - pygments==2.14.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - scipy==1.5.4
      - six==1.17.0
      - tenacity==8.2.2
      - tomli==1.2.3
      - traitlets==4.3.3
      - typing-extensions==4.1.1
      - wcwidth==0.2.13
      - zipp==3.6.0
prefix: /opt/conda/envs/anticipy

tests/test_forecast_plot.py::TestForecastPlot::test_plot_forecast_html tests/test_forecast_plot.py::TestForecastPlot::test_plot_forecast_png
tests/test_forecast_plot.py::TestForecastPlot::test_plot_forecast_jupyter
anticipy/app.py anticipy/forecast_plot.py docs/source/tutorial.rst
anticipy/app.py anticipy/forecast_plot.py docs/source/tutorial.rst