highcharts-for-python / highcharts-stock

Python wrapper for the Highcharts Stock data visualization library.
https://stock-docs.highchartspython.com
Other
26 stars 3 forks source link

BUG Bug in generated JS with global options #57

Closed RobertHana closed 7 months ago

RobertHana commented 8 months ago

Describe the bug chart.display(global_options=global_options) causes Javascript Error: missing ) after argument list output

To Reproduce Steps to reproduce the behavior:

  1. When I attempt 'to set up global options' using the following code: 'chart.display(global_options=global_options) '
  2. I receive 2 'Javascript Error: missing ) after argument list' errors

Expected behavior I expect it to render proper JS with 2 calls -- one to set the global options, and the other to create the chart.

Your Environment:

Additional context Bug may be at: highcharts_core/utility_functions.py:525 where it does not extract the function body correctly, cutting out too much at the end, and thus not closing off properly.

... my stupid work-around (i just added 3 dumb characters xxx to be lopped off by the function call):

class RBHChart(Chart):

    @classmethod
    def from_array(cls,
                   value,
                   series_type='line',
               series_kwargs=None,
                   options_kwargs=None,
                   chart_kwargs=None,
                   is_stock_chart=False):

        series_type = validators.string(series_type, allow_empty = False)
        series_type = series_type.lower()
        if series_type not in SERIES_CLASSES:
            raise errors.HighchartsValueError(f'series_type expects a valid Highcharts '
                                              f'series type. Received: {series_type}')

        series_kwargs = validators.dict(series_kwargs, allow_empty = True) or {}
        options_kwargs = validators.dict(options_kwargs, allow_empty = True) or {}
        chart_kwargs = validators.dict(chart_kwargs, allow_empty = True) or {}

        series_cls = SERIES_CLASSES.get(series_type, None)

        series = series_cls.from_array(value, series_kwargs = series_kwargs)

        options_kwargs['series'] = [series]
        chart_kwargs['is_stock_chart'] = is_stock_chart

        if is_stock_chart:
            options = HighchartsStockOptions(**options_kwargs)
        else:
            options = HighchartsOptions(**options_kwargs)

        instance = cls(**chart_kwargs)
        instance.options = options

        return instance

    def _jupyter_javascript(self,
                            global_options = None,
                            container = None,
                            random_slug = None,
                            retries = 3,
                            interval = 1000):
        original_container = self.container
        new_container = container or self.container or 'highcharts_target_div'
        if not random_slug:
            self.container = new_container
        else:
            self.container = f'{new_container}_{random_slug}'

        if global_options is not None:
            global_options = validate_types(global_options,
                                            types = (SharedStockOptions, SharedOptions))

        js_str = ''
        js_str += utility_functions.get_retryHighcharts()

        if global_options:
            js_str += '\n' + utility_functions.prep_js_for_jupyter(global_options.to_js_literal()+'xxx') + '\n'  # extra 3 chars

        js_str += utility_functions.prep_js_for_jupyter(self.to_js_literal(),
                                                        container=self.container,
                                                        random_slug=random_slug,
                                                        retries=retries,
                                                        interval=interval)

        self.container = original_container

        return js_str
lovepocky commented 8 months ago

same problem. deleting extra ';' character in 'to_js_literal' function in class will generate correct js code.

hcpchris commented 7 months ago

Sorry you're running into this issue! It turns out this is an upstream issue in Highcharts Core for Python that is causing this. It'll be resolved in the Highcharts Core for Python v.1.6.0 release, which I expect to release within the next day or so. I've created an issue there referencing it (highcharts-for-python/highcharts-core#159).

Thanks for reporting this, and thanks for the detailed write-up and explanation of your workaround - it's much appreciated!

hcpchris commented 7 months ago

This was technically resolved in the Highcharts Core for Python v.1.6 release which went out today, however the fix is now enforced through the Highcharts Stock for Python v.1.6 release which bumps the dependency on Highcharts Core for Python.