Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on adding word goal in outline #561

Closed
DarkRedman opened this issue Apr 22, 2019 · 6 comments
Closed

Crash on adding word goal in outline #561

DarkRedman opened this issue Apr 22, 2019 · 6 comments
Labels
Milestone

Comments

@DarkRedman
Copy link
Contributor

Each time I'm on the plan tab and edit the goal of one of the act and press enter to valid, Manuskript crash, but alternatively, when I'm on redaction mode and edit the goal on the sidebar and press enter, it doesn't crash.

@worstje
Copy link
Contributor

worstje commented Apr 22, 2019

Try disabling auto-saving. I suspect that feature is the culprit of most of the crash bugs while editing things on the outline screen.

@gedakc
Copy link
Collaborator

gedakc commented May 19, 2019

@DarkRedman what version of Manusrkipt are you using, and on which operating system?

Manuskript renamed the Redaction pane to Editor since at least version 0.5.0.

@DarkRedman
Copy link
Contributor Author

Sorry that I didn't replied that fast.
I used the 0.9 version on Windows, now I exclusively use it on GNU/Linux and I don't have this problem of saving even with the option to automatically change if any modification occurred within 5 seconds and it works fine.

@gedakc
Copy link
Collaborator

gedakc commented Jul 21, 2019

After much testing and investigation I finally reproduced this crash.

Steps to Reproduce:

  1. Start manuskript and create new project (no template).

  2. Select Outline pane.

  3. Click "Text Plus" icon to create a text (default name "New")

  4. Select Editor pane.

  5. Click on New to display empty text.

  6. Select Outline pane.

  7. Double-click the empty area on New line under title Goal, type in "300", and press Enter.

    Notice manuskript crash on segmentation fault with following console log:

$ bin/manuskript 
Debug: Web rendering engine used: QWebView
Running manuskript version 0.9.0.
Found translation in settings: 
Note: No translator found or loaded from system locale for locale en_CA.
Last accessed directory "/home/gedakc/tmp" loaded.
Project issue561.msk saved.
Project issue561.msk saved.
Traceback (most recent call last):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 354, in modelDataChanged
    self.updateStatusBar()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 389, in updateStatusBar
    mw.mainEditor.tabChanged()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 138, in tabChanged
    self.updateStats()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 317, in updateStats
    drawProgress(p, rect, progress, 2)
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/functions/__init__.py", line 60, in drawProgress
    r2.setWidth(r2.width() * min(progress, 1))
TypeError: unorderable types: int() < str()
QPaintDevice: Cannot destroy paint device that is being painted
Fatal Python error: Segmentation fault

Current thread 0x00007f59d23f0700 (most recent call first):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/abstractItem.py", line 85 in emitDataChanged
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/abstractItem.py", line 254 in setData
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/outlineItem.py", line 151 in setData
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/outlineItem.py", line 194 in updateWordCount
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/outlineItem.py", line 169 in setData
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/abstractModel.py", line 167 in setData
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/main.py", line 145 in launch
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/main.py", line 158 in run
  File "bin/manuskript", line 13 in <module>
Segmentation fault (core dumped)

I am working on a patch to address this crash.

@gedakc gedakc changed the title Crash on goal edition in planning Crash on adding word goal in outline planning Jul 21, 2019
@gedakc gedakc changed the title Crash on adding word goal in outline planning Crash on adding word goal in outline Jul 21, 2019
@gedakc
Copy link
Collaborator

gedakc commented Jul 22, 2019

Continuing the investigation from the above post I searched for the error and found:

Stackoverflow.com: “Unorderable types: int() < str()”

Fix Attempt 1

This led me to try the following code change:

$ git diff
diff --git a/manuskript/functions/__init__.py b/manuskript/functions/__init__.py
index 94cb371..bfe9a7d 100644
--- a/manuskript/functions/__init__.py
+++ b/manuskript/functions/__init__.py
@@ -57,7 +57,8 @@ def drawProgress(painter, rect, progress, radius=0):
     painter.setBrush(QBrush(colorFromProgress(progress)))
 
     r2 = QRect(rect)
-    r2.setWidth(r2.width() * min(progress, 1))
+    r2.setWidth(r2.width() * min(int(progress), 1))
+    #                            ^^^ Avoid crash - issue #561
     painter.drawRoundedRect(r2, radius, radius)
 

To test I started manuskript, loaded recent project "issue561.msk", cleared the goal in outline on lower portion of window, and stopped manuskript.

Then I started manuskript, loaded recent project "issue561.msk". Selected the Outline pane and double-clicked the Goal, typed in "333", pressed Enter and Manuskript crashed with the following console log:

$ bin/manuskript 
Debug: Web rendering engine used: QWebView
Running manuskript version 0.9.0.
Found translation in settings: 
Note: No translator found or loaded from system locale for locale en_CA.
Loading: /home/gedakc/tmp/issue561.msk
Detected file format version: 1. Zip: True.
Project /home/gedakc/tmp/issue561.msk loaded.
Project issue561.msk saved.
gedakc@kaby:~/workspace/manuskript.gedakc$ bin/manuskript 
Debug: Web rendering engine used: QWebView
Running manuskript version 0.9.0.
Found translation in settings: 
Note: No translator found or loaded from system locale for locale en_CA.
Loading: /home/gedakc/tmp/issue561.msk
Detected file format version: 1. Zip: True.
Project /home/gedakc/tmp/issue561.msk loaded.
Traceback (most recent call last):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 354, in modelDataChanged
    self.updateStatusBar()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 389, in updateStatusBar
    mw.mainEditor.tabChanged()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 138, in tabChanged
    self.updateStats()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 317, in updateStats
    drawProgress(p, rect, progress, 2)
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/functions/__init__.py", line 60, in drawProgress
    r2.setWidth(r2.width() * min(int(progress), 1))
ValueError: invalid literal for int() with base 10: ''
QPaintDevice: Cannot destroy paint device that is being painted
Fatal Python error: Segmentation fault

Current thread 0x00007f7359edb700 (most recent call first):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/abstractItem.py", line 85 in emitDataChanged
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/abstractItem.py", line 254 in setData
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/outlineItem.py", line 151 in setData
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/outlineItem.py", line 194 in updateWordCount
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/outlineItem.py", line 169 in setData
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/models/abstractModel.py", line 167 in setData
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/main.py", line 145 in launch
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/main.py", line 158 in run
  File "bin/manuskript", line 13 in <module>
Segmentation fault (core dumped)

Searching the Internet for this new problem I came across the following post:

Stackoverflow.com: How to make “int” parse blank strings?

Fix Attempt 2

Based on the advice of the above link I discovered that Manuskript already had a toInt() function and led me to try the following code change:

$ git diff
diff --git a/manuskript/functions/__init__.py b/manuskript/functions/__init__.py
index 94cb371..8b4006e 100644
--- a/manuskript/functions/__init__.py
+++ b/manuskript/functions/__init__.py
@@ -57,7 +57,8 @@ def drawProgress(painter, rect, progress, radius=0):
     painter.setBrush(QBrush(colorFromProgress(progress)))
 
     r2 = QRect(rect)
-    r2.setWidth(r2.width() * min(progress, 1))
+    r2.setWidth(r2.width() * min(toInt(progress), 1))
+    #                            ^^^^^ Avoid crash - issue #561
     painter.drawRoundedRect(r2, radius, radius)
 

To test I started manuskript, loaded recent project "issue561.msk", cleared the goal in outline on lower portion of window, and stopped manuskript.

Then I started manuskript, loaded recent project "issue561.msk". Selected the Outline pane and double-clicked the Goal, typed in "333", pressed Enter and Manuskript crashed with the following console log:

$ bin/manuskript 
Debug: Web rendering engine used: QWebView
Running manuskript version 0.9.0.
Found translation in settings: 
Note: No translator found or loaded from system locale for locale en_CA.
Loading: /home/gedakc/tmp/issue561.msk
Detected file format version: 1. Zip: True.
Project /home/gedakc/tmp/issue561.msk loaded.
Traceback (most recent call last):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 354, in modelDataChanged
    self.updateStatusBar()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 389, in updateStatusBar
    mw.mainEditor.tabChanged()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 138, in tabChanged
    self.updateStats()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 322, in updateStats
    locale.format_string("%d", goal, grouping=True)))
  File "/usr/lib/python3.5/locale.py", line 248, in format_string
    *val[i+1:i+1+starcount]))
  File "/usr/lib/python3.5/locale.py", line 200, in _format
    formatted = percent % value
TypeError: %d format: a number is required, not str
Traceback (most recent call last):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 354, in modelDataChanged
    self.updateStatusBar()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 389, in updateStatusBar
    mw.mainEditor.tabChanged()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 138, in tabChanged
    self.updateStats()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 322, in updateStats
    locale.format_string("%d", goal, grouping=True)))
  File "/usr/lib/python3.5/locale.py", line 248, in format_string
    *val[i+1:i+1+starcount]))
  File "/usr/lib/python3.5/locale.py", line 200, in _format
    formatted = percent % value
TypeError: %d format: a number is required, not str
Traceback (most recent call last):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 354, in modelDataChanged
    self.updateStatusBar()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 389, in updateStatusBar
    mw.mainEditor.tabChanged()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 138, in tabChanged
    self.updateStats()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 322, in updateStats
    locale.format_string("%d", goal, grouping=True)))
  File "/usr/lib/python3.5/locale.py", line 248, in format_string
    *val[i+1:i+1+starcount]))
  File "/usr/lib/python3.5/locale.py", line 200, in _format
    formatted = percent % value
TypeError: %d format: a number is required, not str
Traceback (most recent call last):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 354, in modelDataChanged
    self.updateStatusBar()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 389, in updateStatusBar
    mw.mainEditor.tabChanged()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 138, in tabChanged
    self.updateStats()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 322, in updateStats
    locale.format_string("%d", goal, grouping=True)))
  File "/usr/lib/python3.5/locale.py", line 248, in format_string
    *val[i+1:i+1+starcount]))
  File "/usr/lib/python3.5/locale.py", line 200, in _format
    formatted = percent % value
TypeError: %d format: a number is required, not str
Traceback (most recent call last):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 354, in modelDataChanged
    self.updateStatusBar()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 389, in updateStatusBar
    mw.mainEditor.tabChanged()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 138, in tabChanged
    self.updateStats()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 322, in updateStats
    locale.format_string("%d", goal, grouping=True)))
  File "/usr/lib/python3.5/locale.py", line 248, in format_string
    *val[i+1:i+1+starcount]))
  File "/usr/lib/python3.5/locale.py", line 200, in _format
    formatted = percent % value
TypeError: %d format: a number is required, not str
Traceback (most recent call last):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 354, in modelDataChanged
    self.updateStatusBar()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 389, in updateStatusBar
    mw.mainEditor.tabChanged()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 138, in tabChanged
    self.updateStats()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 322, in updateStats
    locale.format_string("%d", goal, grouping=True)))
  File "/usr/lib/python3.5/locale.py", line 248, in format_string
    *val[i+1:i+1+starcount]))
  File "/usr/lib/python3.5/locale.py", line 200, in _format
    formatted = percent % value
TypeError: %d format: a number is required, not str
Traceback (most recent call last):
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 354, in modelDataChanged
    self.updateStatusBar()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/editorWidget.py", line 389, in updateStatusBar
    mw.mainEditor.tabChanged()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 138, in tabChanged
    self.updateStats()
  File "/home/gedakc/workspace/manuskript.gedakc/bin/../manuskript/ui/editors/mainEditor.py", line 322, in updateStats
    locale.format_string("%d", goal, grouping=True)))
  File "/usr/lib/python3.5/locale.py", line 248, in format_string
    *val[i+1:i+1+starcount]))
  File "/usr/lib/python3.5/locale.py", line 200, in _format
    formatted = percent % value
TypeError: %d format: a number is required, not str

Fix Attempt 3

In an attempt to fix this latest problem I made this additional code change:

$ git diff
diff --git a/manuskript/ui/editors/mainEditor.py b/manuskript/ui/editors/mainEditor.py
index 35a9274..26ac637 100644
--- a/manuskript/ui/editors/mainEditor.py
+++ b/manuskript/ui/editors/mainEditor.py
@@ -9,7 +9,7 @@ from PyQt5.QtWidgets import QWidget, qApp
 
 from manuskript import settings
 from manuskript.enums import Outline
-from manuskript.functions import AUC, mainWindow, drawProgress, appPath
+from manuskript.functions import AUC, mainWindow, drawProgress, appPath, toInt
 from manuskript.ui import style
 from manuskript.ui.editors.editorWidget import editorWidget
 from manuskript.ui.editors.fullScreenEditor import fullScreenEditor
@@ -319,7 +319,8 @@ class mainEditor(QWidget, Ui_mainEditor):
             self.lblRedacProgress.setPixmap(self.px)
             self.lblRedacWC.setText(self.tr("{} words / {} ").format(
                     locale.format_string("%d", wc, grouping=True),
-                    locale.format_string("%d", goal, grouping=True)))
+                    locale.format_string("%d", toInt(goal), grouping=True)))
+                    #                          ^^^^^ Avoid crash - issue #561
         else:
             self.lblRedacProgress.hide()
             self.lblRedacWC.setText(self.tr("{} words ").format(

To test I started manuskript, loaded recent project "issue561.msk", cleared the goal in outline on lower portion of window, and stopped manuskript.

Then I started manuskript, loaded recent project "issue561.msk". Selected the Outline pane and double-clicked the Goal, typed in "333", pressed Enter and wow! No crash!

Success?

I will perform more tests on this potential solution to see if any other issues crop up.

gedakc added a commit to gedakc/manuskript that referenced this issue Jul 23, 2019
See issue olivierkes#561

The problem appears to be a due to a combination of factors, such as:

- Python does not automatically convert an empty/blank variable to the
  integer zero (0)
- Default goal value is empty/blank for a new Text (scene)
- Asynchronous events can occur such that the change in the Outline
  pane of a new Text (scene) goal from empty/blank to a value is not
  saved to the data model prior to the update event in the Editor pane
  accessing the model value for the word count progress display.

Steps to Reproduce:

1. Start manuskript and create new project (no template).

2. Select **Outline** pane.

3. Click "Text Plus" icon to create a text (default name "New")

4. Select **Editor** pane.

5. Click on **New** to display empty text.

6. Select **Outline** pane.

7. Double-click the empty area on **New** line under title **Goal**, type in "300", and press **Enter**.

   Note that manuskript crashes with a segmentation fault.

Work around the crash by using the already existing manuskript
function toInt() which handles conversion of empty/blank values to
integer value zero (0).
gedakc added a commit to gedakc/manuskript that referenced this issue Jul 23, 2019
See issue olivierkes#561.

The problem appears to be a due to a combination of factors, such as:

- Python does not automatically convert an empty/blank variable to the
  integer zero (0)
- Default goal value is empty/blank for a new Text (scene)
- Asynchronous events can occur such that the change in the Outline
  pane of a new Text (scene) goal from empty/blank to a value is not
  saved to the data model prior to the update event in the Editor pane
  accessing the model value for the word count progress display.

Steps to Reproduce:

1. Start manuskript and create new project (no template).

2. Select **Outline** pane.

3. Click "Text Plus" icon to create a text (default name "New")

4. Select **Editor** pane.

5. Click on **New** to display empty text.

6. Select **Outline** pane.

7. Double-click the empty area on **New** line under title **Goal**, type in "300", and press **Enter**.

   Note that manuskript crashes with a segmentation fault.

Work around the crash by using the already existing manuskript
function toInt() which handles conversion of empty/blank values to
integer value zero (0).
gedakc added a commit to gedakc/manuskript that referenced this issue Jul 23, 2019
See issue olivierkes#561.

The problem appears to be a due to a combination of factors, such as:

- Python does not automatically convert an empty/blank variable to the
  integer zero (0)
- Default goal value is empty/blank for a new Text (scene)
- Asynchronous events can occur such that the change in the Outline
  pane of a new Text (scene) goal from empty/blank to a value is not
  saved to the data model prior to the update event in the Editor pane
  accessing the model value for the word count progress display.

Steps to Reproduce:

1. Start manuskript and create new project (no template).

2. Select **Outline** pane.

3. Click "Text Plus" icon to create a text (default name "New")

4. Select **Editor** pane.

5. Click on **New** to display empty text.

6. Select **Outline** pane.

7. Double-click the empty area on **New** line under title **Goal**,
  type in "300", and press **Enter**.

   Note that manuskript crashes with a segmentation fault.

Work around the crash by using the already existing manuskript
function toInt() which handles conversion of empty/blank values to
integer value zero (0).
@gedakc gedakc added the bug label Jul 23, 2019
@gedakc gedakc added this to the 0.10.0 milestone Jul 23, 2019
gedakc added a commit that referenced this issue Jul 31, 2019
See issue #561.

The problem appears to be a due to a combination of factors, such as:

- Python does not automatically convert an empty/blank variable to the
  integer zero (0)
- Default goal value is empty/blank for a new Text (scene)
- Asynchronous events can occur such that the change in the Outline
  pane of a new Text (scene) goal from empty/blank to a value is not
  saved to the data model prior to the update event in the Editor pane
  accessing the model value for the word count progress display.

Steps to Reproduce:

1. Start manuskript and create new project (no template).

2. Select **Outline** pane.

3. Click "Text Plus" icon to create a text (default name "New")

4. Select **Editor** pane.

5. Click on **New** to display empty text.

6. Select **Outline** pane.

7. Double-click the empty area on **New** line under title **Goal**,
  type in "300", and press **Enter**.

   Note that manuskript crashes with a segmentation fault.

Work around the crash by using the already existing manuskript
function toInt() which handles conversion of empty/blank values to
integer value zero (0).
@gedakc
Copy link
Collaborator

gedakc commented Jul 31, 2019

Closing this issue as PR #609 has been merged with the develop branch.

@gedakc gedakc closed this as completed Jul 31, 2019
worstje added a commit to worstje/manuskript that referenced this issue Sep 22, 2019
A previous fix (5f9ea3) inadvertently broke the progress bar by
converting to the wrong data type. (See issue olivierkes#561 / PR olivierkes#609).

While checking the code I realized the problem occurred primarily
because we weren't checking the validity of the values closer to the
source. Doing so alleviates the need to check elsewhere.

In the hope of inspiring a more systematic approach, a new uiParse()
utility function has been added to curb the further growth of toXxx()
functions that exist solely to validate user input.

There is no doubt room for improvement, both on the end of the new
uiParse() function as well as the spot where it is used. Ideally, the
data that comes out of the model should already be 'safe', but since
this is a bugfix for a bugfix I want to keep waves to a minimum.

This commit fixes issue olivierkes#652.
gedakc pushed a commit that referenced this issue Sep 23, 2019
A previous fix (5f9ea3) inadvertently broke the progress bar by
converting to the wrong data type. (See issue #561 / PR #609).

While checking the code I realized the problem occurred primarily
because we weren't checking the validity of the values closer to the
source. Doing so alleviates the need to check elsewhere.

In the hope of inspiring a more systematic approach, a new uiParse()
utility function has been added to curb the further growth of toXxx()
functions that exist solely to validate user input.

There is no doubt room for improvement, both on the end of the new
uiParse() function as well as the spot where it is used. Ideally, the
data that comes out of the model should already be 'safe', but since
this is a bugfix for a bugfix I want to keep waves to a minimum.

This commit fixes issue #652.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants