Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,25 +35,12 @@ jobs:
paths:
- "venv"

- run:
name: Run lint
command: |
. venv/bin/activate
pylint dash setup.py --rcfile=$PYLINTRC
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109
flake8 dash setup.py
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest tests.development.test_base_component
python -m unittest tests.development.test_component_loader
python -m unittest tests.test_integration
python -m unittest tests.test_resources
python -m unittest tests.test_configs
./test.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


"python-3.6":
<<: *test-template
Expand All@@ -80,4 +67,4 @@ workflows:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
- "python-3.7"
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements-py37.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components==0.12.0rc3
dash-flow-example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components>=0.12.0rc3
dash_flow_example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
## Unreleased
## Removed
- Removed support for `Event` system. Use event properties instead, for example the `n_clicks` property instead of the `click` event, see [#531](https://github.com/plotly/dash/issues/531) for details. `dash_renderer` MUST be upgraded to >=0.17.0 together with this, and it is recommended to update `dash_core_components` to >=0.43.0 and `dash_html_components` to >=0.14.0. [#550](https://github.com/plotly/dash/pull/550)

## [0.35.3] - 2019-01-23
## Fixed
- Asset blueprint takes routes prefix into it's static path. [#547](https://github.com/plotly/dash/pull/547)
Expand Down
51 changes: 17 additions & 34 deletions dash/dash.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,13 +15,14 @@

from functools import wraps

import plotly
import dash_renderer
import flask
from flask import Flask, Response
from flask_compress import Compress

from .dependencies import Event, Input, Output, State
import plotly
import dash_renderer

from .dependencies import Input, Output, State
from .resources import Scripts, Css
from .development.base_component import Component
from . import exceptions
Expand DownExpand Up@@ -622,7 +623,6 @@ def dependencies(self):
},
'inputs': v['inputs'],
'state': v['state'],
'events': v['events']
} for k, v in self.callback_map.items()
])

Expand All@@ -633,7 +633,7 @@ def react(self, *args, **kwargs):
'Use `callback` instead. `callback` has a new syntax too, '
'so make sure to call `help(app.callback)` to learn more.')

def _validate_callback(self, output, inputs, state, events):
def _validate_callback(self, output, inputs, state):
# pylint: disable=too-many-branches
layout = self._cached_layout or self._layout_value()

Expand All@@ -652,8 +652,7 @@ def _validate_callback(self, output, inputs, state, events):

for args, obj, name in [([output], Output, 'Output'),
(inputs, Input, 'Input'),
(state, State, 'State'),
(events, Event, 'Event')]:
(state, State, 'State')]:

if not isinstance(args, list):
raise exceptions.IncorrectTypeException(
Expand DownExpand Up@@ -721,32 +720,20 @@ def _validate_callback(self, output, inputs, state, events):
component.available_properties).replace(
' ', ''))

if (hasattr(arg, 'component_event') and
arg.component_event not in
component.available_events):
if hasattr(arg, 'component_event'):
raise exceptions.NonExistentEventException('''
Attempting to assign a callback with
the event "{}" but the component
"{}" doesn't have "{}" as an event.\n
Here is a list of the available events in "{}":
{}
'''.format(
arg.component_event,
arg.component_id,
arg.component_event,
arg.component_id,
component.available_events).replace(' ', ''))
Events have been removed.
Use the associated property instead.
''')

if state and not events and not inputs:
raise exceptions.MissingEventsException('''
if state and not inputs:
raise exceptions.MissingInputsException('''
This callback has {} `State` {}
but no `Input` elements or `Event` elements.\n
Without `Input` or `Event` elements, this callback
but no `Input` elements.\n
Without `Input` elements, this callback
will never get called.\n
(Subscribing to input components will cause the
callback to be called whenever their values
change and subscribing to an event will cause the
callback to be called whenever the event is fired.)
callback to be called whenever their values change.)
'''.format(
len(state),
'elements' if len(state) > 1 else 'element'
Expand DownExpand Up@@ -888,8 +875,8 @@ def _validate_value(val, index=None):
# TODO - Check this map for recursive or other ill-defined non-tree
# relationships
# pylint: disable=dangerous-default-value
def callback(self, output, inputs=[], state=[], events=[]):
self._validate_callback(output, inputs, state, events)
def callback(self, output, inputs=[], state=[]):
self._validate_callback(output, inputs, state)

callback_id = '{}.{}'.format(
output.component_id, output.component_property
Expand All@@ -902,10 +889,6 @@ def callback(self, output, inputs=[], state=[], events=[]):
'state': [
{'id': c.component_id, 'property': c.component_property}
for c in state
],
'events': [
{'id': c.component_id, 'event': c.component_event}
for c in events
]
}

Expand Down
7 changes: 0 additions & 7 deletions dash/dependencies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,10 +17,3 @@ class State:
def __init__(self, component_id, component_property):
self.component_id = component_id
self.component_property = component_property


# pylint: disable=old-style-class, too-few-public-methods
class Event:
def __init__(self, component_id, component_event):
self.component_id = component_id
self.component_event = component_event
50 changes: 18 additions & 32 deletions dash/development/_py_components_generation.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@
import os

from dash.development.base_component import _explicitize_args
from dash.exceptions import NonExistentEventException
from ._all_keywords import python_keywords
from .base_component import Component

Expand All@@ -27,8 +28,7 @@ def generate_class_string(typename, props, description, namespace):
string

"""
# TODO _prop_names, _type, _namespace, available_events,
# and available_properties
# TODO _prop_names, _type, _namespace, and available_properties
# can be modified by a Dash JS developer via setattr
# TODO - Tab out the repr for the repr of these components to make it
# look more like a hierarchical tree
Expand All@@ -52,7 +52,6 @@ def __init__(self, {default_argtext}):
self._namespace = '{namespace}'
self._valid_wildcard_attributes =\
{list_of_valid_wildcard_attr_prefixes}
self.available_events = {events}
self.available_properties = {list_of_valid_keys}
self.available_wildcard_properties =\
{list_of_valid_wildcard_attr_prefixes}
Expand DownExpand Up@@ -101,11 +100,11 @@ def __repr__(self):
docstring = create_docstring(
component_name=typename,
props=filtered_props,
events=parse_events(props),
description=description).replace('\r\n', '\n')

prohibit_events(props)

# pylint: disable=unused-variable
events = '[' + ', '.join(parse_events(props)) + ']'
prop_keys = list(props.keys())
if 'children' in props:
prop_keys.remove('children')
Expand All@@ -122,7 +121,7 @@ def __repr__(self):
for p in prop_keys
if not p.endswith("-*") and
p not in python_keywords and
p not in ['dashEvents', 'fireEvent', 'setProps']] + ['**kwargs']
p != 'setProps'] + ['**kwargs']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that was intentional but still present for the R generation

@rpkylerpkyleJan 21, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have modified my code to match.

)

required_args = required_props(props)
Expand DownExpand Up@@ -233,7 +232,7 @@ def required_props(props):
if prop['required']]


def create_docstring(component_name, props, events, description):
def create_docstring(component_name, props, description):
"""
Create the Dash component docstring

Expand All@@ -243,8 +242,6 @@ def create_docstring(component_name, props, events, description):
Component name
props: dict
Dictionary with {propName: propMetadata} structure
events: list
List of Dash events
description: str
Component description

Expand All@@ -259,9 +256,7 @@ def create_docstring(component_name, props, events, description):
return (
"""A {name} component.\n{description}

Keyword arguments:\n{args}

Available events: {events}"""
Keyword arguments:\n{args}"""
).format(
name=component_name,
description=description,
Expand All@@ -274,30 +269,26 @@ def create_docstring(component_name, props, events, description):
description=prop['description'],
indent_num=0,
is_flow_type='flowType' in prop and 'type' not in prop)
for p, prop in list(filter_props(props).items())),
events=', '.join(events))
for p, prop in list(filter_props(props).items())))


def parse_events(props):
def prohibit_events(props):
"""
Pull out the dashEvents from the Component props
Events have been removed. Raise an error if we see dashEvents or fireEvents

Parameters
----------
props: dict
Dictionary with {propName: propMetadata} structure

Returns
Raises
-------
list
List of Dash event strings
?
"""
if 'dashEvents' in props and props['dashEvents']['type']['name'] == 'enum':
events = [v['value'] for v in props['dashEvents']['type']['value']]
else:
events = []

return events
if 'dashEvents' in props or 'fireEvents' in props:
raise NonExistentEventException(
'Events are no longer supported by dash. Use properties instead, '
'eg `n_clicks` instead of a `click` event.')


def parse_wildcards(props):
Expand DownExpand Up@@ -349,7 +340,6 @@ def filter_props(props):
Filter props from the Component arguments to exclude:
- Those without a "type" or a "flowType" field
- Those with arg.type.name in {'func', 'symbol', 'instanceOf'}
- dashEvents as a name

Parameters
----------
Expand DownExpand Up@@ -415,10 +405,6 @@ def filter_props(props):
else:
raise ValueError

# dashEvents are a special oneOf property that is used for subscribing
# to events but it's never set as a property
if arg_name in ['dashEvents']:
filtered_props.pop(arg_name)
return filtered_props


Expand DownExpand Up@@ -518,7 +504,7 @@ def map_js_to_py_types_prop_types(type_object):
', '.join(
"'{}'".format(t)
for t in list(type_object['value'].keys())),
'Those keys have the following types:\n{}'.format(
'Those keys have the following types:\n{}'.format(
'\n'.join(create_prop_docstring(
prop_name=prop_name,
type_object=prop,
Expand DownExpand Up@@ -561,7 +547,7 @@ def map_js_to_py_types_flow_types(type_object):
signature=lambda indent_num: 'dict containing keys {}.\n{}'.format(
', '.join("'{}'".format(d['key'])
for d in type_object['signature']['properties']),
'{}Those keys have the following types:\n{}'.format(
'{}Those keys have the following types:\n{}'.format(
' ' * indent_num,
'\n'.join(
create_prop_docstring(
Expand Down
2 changes: 1 addition & 1 deletion dash/exceptions.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@ class IncorrectTypeException(CallbackException):
pass


class MissingEventsException(CallbackException):
class MissingInputsException(CallbackException):
pass


Expand Down
2 changes: 1 addition & 1 deletion dash/extract-meta.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ const componentPaths = process.argv.slice(3);
const ignorePattern = new RegExp(process.argv[2]);

const excludedDocProps = [
'setProps', 'id', 'className', 'style', 'dashEvents', 'fireEvent'
'setProps', 'id', 'className', 'style'
];

if (!componentPaths.length) {
Expand Down
20 changes: 20 additions & 0 deletions test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
EXIT_STATE=0

python -m unittest tests.development.test_base_component || EXIT_STATE=$?
python -m unittest tests.development.test_component_loader || EXIT_STATE=$?
python -m unittest tests.test_integration || EXIT_STATE=$?
python -m unittest tests.test_resources || EXIT_STATE=$?
python -m unittest tests.test_configs || EXIT_STATE=$?

pylint dash setup.py --rcfile=$PYLINTRC || EXIT_STATE=$?
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109 || EXIT_STATE=$?
flake8 dash setup.py || EXIT_STATE=$?
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests || EXIT_STATE=$?

if [ $EXIT_STATE -ne 0 ]; then
Comment thread
alexcjohnson marked this conversation as resolved.
echo "One or more tests failed"
else
echo "All tests passed!"
fi

exit $EXIT_STATE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include the linting also ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'll move linting in here too.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting into test.sh -> 2c9a3c8

10 changes: 0 additions & 10 deletions tests/development/TestReactComponent.react.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,19 +91,9 @@ ReactComponent.propTypes = {
}
}),

// special dash events

children: React.PropTypes.node,

id: React.PropTypes.string,


// dashEvents is a special prop that is used to events validation
dashEvents: React.PropTypes.oneOf([
'restyle',
'relayout',
'click'
])
};

ReactComponent.defaultProps = {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,25 +35,12 @@ jobs:
paths:
- "venv"

- run:
name: Run lint
command: |
. venv/bin/activate
pylint dash setup.py --rcfile=$PYLINTRC
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109
flake8 dash setup.py
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest tests.development.test_base_component
python -m unittest tests.development.test_component_loader
python -m unittest tests.test_integration
python -m unittest tests.test_resources
python -m unittest tests.test_configs
./test.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


"python-3.6":
<<: *test-template
Expand All@@ -80,4 +67,4 @@ workflows:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
- "python-3.7"
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements-py37.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components==0.12.0rc3
dash-flow-example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components>=0.12.0rc3
dash_flow_example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
## Unreleased
## Removed
- Removed support for `Event` system. Use event properties instead, for example the `n_clicks` property instead of the `click` event, see [#531](https://github.com/plotly/dash/issues/531) for details. `dash_renderer` MUST be upgraded to >=0.17.0 together with this, and it is recommended to update `dash_core_components` to >=0.43.0 and `dash_html_components` to >=0.14.0. [#550](https://github.com/plotly/dash/pull/550)

## [0.35.3] - 2019-01-23
## Fixed
- Asset blueprint takes routes prefix into it's static path. [#547](https://github.com/plotly/dash/pull/547)
Expand Down
51 changes: 17 additions & 34 deletions dash/dash.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,13 +15,14 @@

from functools import wraps

import plotly
import dash_renderer
import flask
from flask import Flask, Response
from flask_compress import Compress

from .dependencies import Event, Input, Output, State
import plotly
import dash_renderer

from .dependencies import Input, Output, State
from .resources import Scripts, Css
from .development.base_component import Component
from . import exceptions
Expand DownExpand Up@@ -622,7 +623,6 @@ def dependencies(self):
},
'inputs': v['inputs'],
'state': v['state'],
'events': v['events']
} for k, v in self.callback_map.items()
])

Expand All@@ -633,7 +633,7 @@ def react(self, *args, **kwargs):
'Use `callback` instead. `callback` has a new syntax too, '
'so make sure to call `help(app.callback)` to learn more.')

def _validate_callback(self, output, inputs, state, events):
def _validate_callback(self, output, inputs, state):
# pylint: disable=too-many-branches
layout = self._cached_layout or self._layout_value()

Expand All@@ -652,8 +652,7 @@ def _validate_callback(self, output, inputs, state, events):

for args, obj, name in [([output], Output, 'Output'),
(inputs, Input, 'Input'),
(state, State, 'State'),
(events, Event, 'Event')]:
(state, State, 'State')]:

if not isinstance(args, list):
raise exceptions.IncorrectTypeException(
Expand DownExpand Up@@ -721,32 +720,20 @@ def _validate_callback(self, output, inputs, state, events):
component.available_properties).replace(
' ', ''))

if (hasattr(arg, 'component_event') and
arg.component_event not in
component.available_events):
if hasattr(arg, 'component_event'):
raise exceptions.NonExistentEventException('''
Attempting to assign a callback with
the event "{}" but the component
"{}" doesn't have "{}" as an event.\n
Here is a list of the available events in "{}":
{}
'''.format(
arg.component_event,
arg.component_id,
arg.component_event,
arg.component_id,
component.available_events).replace(' ', ''))
Events have been removed.
Use the associated property instead.
''')

if state and not events and not inputs:
raise exceptions.MissingEventsException('''
if state and not inputs:
raise exceptions.MissingInputsException('''
This callback has {} `State` {}
but no `Input` elements or `Event` elements.\n
Without `Input` or `Event` elements, this callback
but no `Input` elements.\n
Without `Input` elements, this callback
will never get called.\n
(Subscribing to input components will cause the
callback to be called whenever their values
change and subscribing to an event will cause the
callback to be called whenever the event is fired.)
callback to be called whenever their values change.)
'''.format(
len(state),
'elements' if len(state) > 1 else 'element'
Expand DownExpand Up@@ -888,8 +875,8 @@ def _validate_value(val, index=None):
# TODO - Check this map for recursive or other ill-defined non-tree
# relationships
# pylint: disable=dangerous-default-value
def callback(self, output, inputs=[], state=[], events=[]):
self._validate_callback(output, inputs, state, events)
def callback(self, output, inputs=[], state=[]):
self._validate_callback(output, inputs, state)

callback_id = '{}.{}'.format(
output.component_id, output.component_property
Expand All@@ -902,10 +889,6 @@ def callback(self, output, inputs=[], state=[], events=[]):
'state': [
{'id': c.component_id, 'property': c.component_property}
for c in state
],
'events': [
{'id': c.component_id, 'event': c.component_event}
for c in events
]
}

Expand Down
7 changes: 0 additions & 7 deletions dash/dependencies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,10 +17,3 @@ class State:
def __init__(self, component_id, component_property):
self.component_id = component_id
self.component_property = component_property


# pylint: disable=old-style-class, too-few-public-methods
class Event:
def __init__(self, component_id, component_event):
self.component_id = component_id
self.component_event = component_event
50 changes: 18 additions & 32 deletions dash/development/_py_components_generation.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@
import os

from dash.development.base_component import _explicitize_args
from dash.exceptions import NonExistentEventException
from ._all_keywords import python_keywords
from .base_component import Component

Expand All@@ -27,8 +28,7 @@ def generate_class_string(typename, props, description, namespace):
string

"""
# TODO _prop_names, _type, _namespace, available_events,
# and available_properties
# TODO _prop_names, _type, _namespace, and available_properties
# can be modified by a Dash JS developer via setattr
# TODO - Tab out the repr for the repr of these components to make it
# look more like a hierarchical tree
Expand All@@ -52,7 +52,6 @@ def __init__(self, {default_argtext}):
self._namespace = '{namespace}'
self._valid_wildcard_attributes =\
{list_of_valid_wildcard_attr_prefixes}
self.available_events = {events}
self.available_properties = {list_of_valid_keys}
self.available_wildcard_properties =\
{list_of_valid_wildcard_attr_prefixes}
Expand DownExpand Up@@ -101,11 +100,11 @@ def __repr__(self):
docstring = create_docstring(
component_name=typename,
props=filtered_props,
events=parse_events(props),
description=description).replace('\r\n', '\n')

prohibit_events(props)

# pylint: disable=unused-variable
events = '[' + ', '.join(parse_events(props)) + ']'
prop_keys = list(props.keys())
if 'children' in props:
prop_keys.remove('children')
Expand All@@ -122,7 +121,7 @@ def __repr__(self):
for p in prop_keys
if not p.endswith("-*") and
p not in python_keywords and
p not in ['dashEvents', 'fireEvent', 'setProps']] + ['**kwargs']
p != 'setProps'] + ['**kwargs']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that was intentional but still present for the R generation

@rpkylerpkyleJan 21, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have modified my code to match.

)

required_args = required_props(props)
Expand DownExpand Up@@ -233,7 +232,7 @@ def required_props(props):
if prop['required']]


def create_docstring(component_name, props, events, description):
def create_docstring(component_name, props, description):
"""
Create the Dash component docstring

Expand All@@ -243,8 +242,6 @@ def create_docstring(component_name, props, events, description):
Component name
props: dict
Dictionary with {propName: propMetadata} structure
events: list
List of Dash events
description: str
Component description

Expand All@@ -259,9 +256,7 @@ def create_docstring(component_name, props, events, description):
return (
"""A {name} component.\n{description}

Keyword arguments:\n{args}

Available events: {events}"""
Keyword arguments:\n{args}"""
).format(
name=component_name,
description=description,
Expand All@@ -274,30 +269,26 @@ def create_docstring(component_name, props, events, description):
description=prop['description'],
indent_num=0,
is_flow_type='flowType' in prop and 'type' not in prop)
for p, prop in list(filter_props(props).items())),
events=', '.join(events))
for p, prop in list(filter_props(props).items())))


def parse_events(props):
def prohibit_events(props):
"""
Pull out the dashEvents from the Component props
Events have been removed. Raise an error if we see dashEvents or fireEvents

Parameters
----------
props: dict
Dictionary with {propName: propMetadata} structure

Returns
Raises
-------
list
List of Dash event strings
?
"""
if 'dashEvents' in props and props['dashEvents']['type']['name'] == 'enum':
events = [v['value'] for v in props['dashEvents']['type']['value']]
else:
events = []

return events
if 'dashEvents' in props or 'fireEvents' in props:
raise NonExistentEventException(
'Events are no longer supported by dash. Use properties instead, '
'eg `n_clicks` instead of a `click` event.')


def parse_wildcards(props):
Expand DownExpand Up@@ -349,7 +340,6 @@ def filter_props(props):
Filter props from the Component arguments to exclude:
- Those without a "type" or a "flowType" field
- Those with arg.type.name in {'func', 'symbol', 'instanceOf'}
- dashEvents as a name

Parameters
----------
Expand DownExpand Up@@ -415,10 +405,6 @@ def filter_props(props):
else:
raise ValueError

# dashEvents are a special oneOf property that is used for subscribing
# to events but it's never set as a property
if arg_name in ['dashEvents']:
filtered_props.pop(arg_name)
return filtered_props


Expand DownExpand Up@@ -518,7 +504,7 @@ def map_js_to_py_types_prop_types(type_object):
', '.join(
"'{}'".format(t)
for t in list(type_object['value'].keys())),
'Those keys have the following types:\n{}'.format(
'Those keys have the following types:\n{}'.format(
'\n'.join(create_prop_docstring(
prop_name=prop_name,
type_object=prop,
Expand DownExpand Up@@ -561,7 +547,7 @@ def map_js_to_py_types_flow_types(type_object):
signature=lambda indent_num: 'dict containing keys {}.\n{}'.format(
', '.join("'{}'".format(d['key'])
for d in type_object['signature']['properties']),
'{}Those keys have the following types:\n{}'.format(
'{}Those keys have the following types:\n{}'.format(
' ' * indent_num,
'\n'.join(
create_prop_docstring(
Expand Down
2 changes: 1 addition & 1 deletion dash/exceptions.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@ class IncorrectTypeException(CallbackException):
pass


class MissingEventsException(CallbackException):
class MissingInputsException(CallbackException):
pass


Expand Down
2 changes: 1 addition & 1 deletion dash/extract-meta.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ const componentPaths = process.argv.slice(3);
const ignorePattern = new RegExp(process.argv[2]);

const excludedDocProps = [
'setProps', 'id', 'className', 'style', 'dashEvents', 'fireEvent'
'setProps', 'id', 'className', 'style'
];

if (!componentPaths.length) {
Expand Down
20 changes: 20 additions & 0 deletions test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
EXIT_STATE=0

python -m unittest tests.development.test_base_component || EXIT_STATE=$?
python -m unittest tests.development.test_component_loader || EXIT_STATE=$?
python -m unittest tests.test_integration || EXIT_STATE=$?
python -m unittest tests.test_resources || EXIT_STATE=$?
python -m unittest tests.test_configs || EXIT_STATE=$?

pylint dash setup.py --rcfile=$PYLINTRC || EXIT_STATE=$?
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109 || EXIT_STATE=$?
flake8 dash setup.py || EXIT_STATE=$?
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests || EXIT_STATE=$?

if [ $EXIT_STATE -ne 0 ]; then
Comment thread
alexcjohnson marked this conversation as resolved.
echo "One or more tests failed"
else
echo "All tests passed!"
fi

exit $EXIT_STATE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include the linting also ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'll move linting in here too.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting into test.sh -> 2c9a3c8

10 changes: 0 additions & 10 deletions tests/development/TestReactComponent.react.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,19 +91,9 @@ ReactComponent.propTypes = {
}
}),

// special dash events

children: React.PropTypes.node,

id: React.PropTypes.string,


// dashEvents is a special prop that is used to events validation
dashEvents: React.PropTypes.oneOf([
'restyle',
'relayout',
'click'
])
};

ReactComponent.defaultProps = {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,25 +35,12 @@ jobs:
paths:
- "venv"

- run:
name: Run lint
command: |
. venv/bin/activate
pylint dash setup.py --rcfile=$PYLINTRC
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109
flake8 dash setup.py
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest tests.development.test_base_component
python -m unittest tests.development.test_component_loader
python -m unittest tests.test_integration
python -m unittest tests.test_resources
python -m unittest tests.test_configs
./test.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


"python-3.6":
<<: *test-template
Expand All@@ -80,4 +67,4 @@ workflows:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
- "python-3.7"
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements-py37.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components==0.12.0rc3
dash-flow-example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components>=0.12.0rc3
dash_flow_example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
## Unreleased
## Removed
- Removed support for `Event` system. Use event properties instead, for example the `n_clicks` property instead of the `click` event, see [#531](https://github.com/plotly/dash/issues/531) for details. `dash_renderer` MUST be upgraded to >=0.17.0 together with this, and it is recommended to update `dash_core_components` to >=0.43.0 and `dash_html_components` to >=0.14.0. [#550](https://github.com/plotly/dash/pull/550)

## [0.35.3] - 2019-01-23
## Fixed
- Asset blueprint takes routes prefix into it's static path. [#547](https://github.com/plotly/dash/pull/547)
Expand Down
51 changes: 17 additions & 34 deletions dash/dash.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,13 +15,14 @@

from functools import wraps

import plotly
import dash_renderer
import flask
from flask import Flask, Response
from flask_compress import Compress

from .dependencies import Event, Input, Output, State
import plotly
import dash_renderer

from .dependencies import Input, Output, State
from .resources import Scripts, Css
from .development.base_component import Component
from . import exceptions
Expand DownExpand Up@@ -622,7 +623,6 @@ def dependencies(self):
},
'inputs': v['inputs'],
'state': v['state'],
'events': v['events']
} for k, v in self.callback_map.items()
])

Expand All@@ -633,7 +633,7 @@ def react(self, *args, **kwargs):
'Use `callback` instead. `callback` has a new syntax too, '
'so make sure to call `help(app.callback)` to learn more.')

def _validate_callback(self, output, inputs, state, events):
def _validate_callback(self, output, inputs, state):
# pylint: disable=too-many-branches
layout = self._cached_layout or self._layout_value()

Expand All@@ -652,8 +652,7 @@ def _validate_callback(self, output, inputs, state, events):

for args, obj, name in [([output], Output, 'Output'),
(inputs, Input, 'Input'),
(state, State, 'State'),
(events, Event, 'Event')]:
(state, State, 'State')]:

if not isinstance(args, list):
raise exceptions.IncorrectTypeException(
Expand DownExpand Up@@ -721,32 +720,20 @@ def _validate_callback(self, output, inputs, state, events):
component.available_properties).replace(
' ', ''))

if (hasattr(arg, 'component_event') and
arg.component_event not in
component.available_events):
if hasattr(arg, 'component_event'):
raise exceptions.NonExistentEventException('''
Attempting to assign a callback with
the event "{}" but the component
"{}" doesn't have "{}" as an event.\n
Here is a list of the available events in "{}":
{}
'''.format(
arg.component_event,
arg.component_id,
arg.component_event,
arg.component_id,
component.available_events).replace(' ', ''))
Events have been removed.
Use the associated property instead.
''')

if state and not events and not inputs:
raise exceptions.MissingEventsException('''
if state and not inputs:
raise exceptions.MissingInputsException('''
This callback has {} `State` {}
but no `Input` elements or `Event` elements.\n
Without `Input` or `Event` elements, this callback
but no `Input` elements.\n
Without `Input` elements, this callback
will never get called.\n
(Subscribing to input components will cause the
callback to be called whenever their values
change and subscribing to an event will cause the
callback to be called whenever the event is fired.)
callback to be called whenever their values change.)
'''.format(
len(state),
'elements' if len(state) > 1 else 'element'
Expand DownExpand Up@@ -888,8 +875,8 @@ def _validate_value(val, index=None):
# TODO - Check this map for recursive or other ill-defined non-tree
# relationships
# pylint: disable=dangerous-default-value
def callback(self, output, inputs=[], state=[], events=[]):
self._validate_callback(output, inputs, state, events)
def callback(self, output, inputs=[], state=[]):
self._validate_callback(output, inputs, state)

callback_id = '{}.{}'.format(
output.component_id, output.component_property
Expand All@@ -902,10 +889,6 @@ def callback(self, output, inputs=[], state=[], events=[]):
'state': [
{'id': c.component_id, 'property': c.component_property}
for c in state
],
'events': [
{'id': c.component_id, 'event': c.component_event}
for c in events
]
}

Expand Down
7 changes: 0 additions & 7 deletions dash/dependencies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,10 +17,3 @@ class State:
def __init__(self, component_id, component_property):
self.component_id = component_id
self.component_property = component_property


# pylint: disable=old-style-class, too-few-public-methods
class Event:
def __init__(self, component_id, component_event):
self.component_id = component_id
self.component_event = component_event
50 changes: 18 additions & 32 deletions dash/development/_py_components_generation.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@
import os

from dash.development.base_component import _explicitize_args
from dash.exceptions import NonExistentEventException
from ._all_keywords import python_keywords
from .base_component import Component

Expand All@@ -27,8 +28,7 @@ def generate_class_string(typename, props, description, namespace):
string

"""
# TODO _prop_names, _type, _namespace, available_events,
# and available_properties
# TODO _prop_names, _type, _namespace, and available_properties
# can be modified by a Dash JS developer via setattr
# TODO - Tab out the repr for the repr of these components to make it
# look more like a hierarchical tree
Expand All@@ -52,7 +52,6 @@ def __init__(self, {default_argtext}):
self._namespace = '{namespace}'
self._valid_wildcard_attributes =\
{list_of_valid_wildcard_attr_prefixes}
self.available_events = {events}
self.available_properties = {list_of_valid_keys}
self.available_wildcard_properties =\
{list_of_valid_wildcard_attr_prefixes}
Expand DownExpand Up@@ -101,11 +100,11 @@ def __repr__(self):
docstring = create_docstring(
component_name=typename,
props=filtered_props,
events=parse_events(props),
description=description).replace('\r\n', '\n')

prohibit_events(props)

# pylint: disable=unused-variable
events = '[' + ', '.join(parse_events(props)) + ']'
prop_keys = list(props.keys())
if 'children' in props:
prop_keys.remove('children')
Expand All@@ -122,7 +121,7 @@ def __repr__(self):
for p in prop_keys
if not p.endswith("-*") and
p not in python_keywords and
p not in ['dashEvents', 'fireEvent', 'setProps']] + ['**kwargs']
p != 'setProps'] + ['**kwargs']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that was intentional but still present for the R generation

@rpkylerpkyleJan 21, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have modified my code to match.

)

required_args = required_props(props)
Expand DownExpand Up@@ -233,7 +232,7 @@ def required_props(props):
if prop['required']]


def create_docstring(component_name, props, events, description):
def create_docstring(component_name, props, description):
"""
Create the Dash component docstring

Expand All@@ -243,8 +242,6 @@ def create_docstring(component_name, props, events, description):
Component name
props: dict
Dictionary with {propName: propMetadata} structure
events: list
List of Dash events
description: str
Component description

Expand All@@ -259,9 +256,7 @@ def create_docstring(component_name, props, events, description):
return (
"""A {name} component.\n{description}

Keyword arguments:\n{args}

Available events: {events}"""
Keyword arguments:\n{args}"""
).format(
name=component_name,
description=description,
Expand All@@ -274,30 +269,26 @@ def create_docstring(component_name, props, events, description):
description=prop['description'],
indent_num=0,
is_flow_type='flowType' in prop and 'type' not in prop)
for p, prop in list(filter_props(props).items())),
events=', '.join(events))
for p, prop in list(filter_props(props).items())))


def parse_events(props):
def prohibit_events(props):
"""
Pull out the dashEvents from the Component props
Events have been removed. Raise an error if we see dashEvents or fireEvents

Parameters
----------
props: dict
Dictionary with {propName: propMetadata} structure

Returns
Raises
-------
list
List of Dash event strings
?
"""
if 'dashEvents' in props and props['dashEvents']['type']['name'] == 'enum':
events = [v['value'] for v in props['dashEvents']['type']['value']]
else:
events = []

return events
if 'dashEvents' in props or 'fireEvents' in props:
raise NonExistentEventException(
'Events are no longer supported by dash. Use properties instead, '
'eg `n_clicks` instead of a `click` event.')


def parse_wildcards(props):
Expand DownExpand Up@@ -349,7 +340,6 @@ def filter_props(props):
Filter props from the Component arguments to exclude:
- Those without a "type" or a "flowType" field
- Those with arg.type.name in {'func', 'symbol', 'instanceOf'}
- dashEvents as a name

Parameters
----------
Expand DownExpand Up@@ -415,10 +405,6 @@ def filter_props(props):
else:
raise ValueError

# dashEvents are a special oneOf property that is used for subscribing
# to events but it's never set as a property
if arg_name in ['dashEvents']:
filtered_props.pop(arg_name)
return filtered_props


Expand DownExpand Up@@ -518,7 +504,7 @@ def map_js_to_py_types_prop_types(type_object):
', '.join(
"'{}'".format(t)
for t in list(type_object['value'].keys())),
'Those keys have the following types:\n{}'.format(
'Those keys have the following types:\n{}'.format(
'\n'.join(create_prop_docstring(
prop_name=prop_name,
type_object=prop,
Expand DownExpand Up@@ -561,7 +547,7 @@ def map_js_to_py_types_flow_types(type_object):
signature=lambda indent_num: 'dict containing keys {}.\n{}'.format(
', '.join("'{}'".format(d['key'])
for d in type_object['signature']['properties']),
'{}Those keys have the following types:\n{}'.format(
'{}Those keys have the following types:\n{}'.format(
' ' * indent_num,
'\n'.join(
create_prop_docstring(
Expand Down
2 changes: 1 addition & 1 deletion dash/exceptions.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@ class IncorrectTypeException(CallbackException):
pass


class MissingEventsException(CallbackException):
class MissingInputsException(CallbackException):
pass


Expand Down
2 changes: 1 addition & 1 deletion dash/extract-meta.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ const componentPaths = process.argv.slice(3);
const ignorePattern = new RegExp(process.argv[2]);

const excludedDocProps = [
'setProps', 'id', 'className', 'style', 'dashEvents', 'fireEvent'
'setProps', 'id', 'className', 'style'
];

if (!componentPaths.length) {
Expand Down
20 changes: 20 additions & 0 deletions test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
EXIT_STATE=0

python -m unittest tests.development.test_base_component || EXIT_STATE=$?
python -m unittest tests.development.test_component_loader || EXIT_STATE=$?
python -m unittest tests.test_integration || EXIT_STATE=$?
python -m unittest tests.test_resources || EXIT_STATE=$?
python -m unittest tests.test_configs || EXIT_STATE=$?

pylint dash setup.py --rcfile=$PYLINTRC || EXIT_STATE=$?
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109 || EXIT_STATE=$?
flake8 dash setup.py || EXIT_STATE=$?
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests || EXIT_STATE=$?

if [ $EXIT_STATE -ne 0 ]; then
Comment thread
alexcjohnson marked this conversation as resolved.
echo "One or more tests failed"
else
echo "All tests passed!"
fi

exit $EXIT_STATE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include the linting also ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'll move linting in here too.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting into test.sh -> 2c9a3c8

10 changes: 0 additions & 10 deletions tests/development/TestReactComponent.react.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,19 +91,9 @@ ReactComponent.propTypes = {
}
}),

// special dash events

children: React.PropTypes.node,

id: React.PropTypes.string,


// dashEvents is a special prop that is used to events validation
dashEvents: React.PropTypes.oneOf([
'restyle',
'relayout',
'click'
])
};

ReactComponent.defaultProps = {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,25 +35,12 @@ jobs:
paths:
- "venv"

- run:
name: Run lint
command: |
. venv/bin/activate
pylint dash setup.py --rcfile=$PYLINTRC
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109
flake8 dash setup.py
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest tests.development.test_base_component
python -m unittest tests.development.test_component_loader
python -m unittest tests.test_integration
python -m unittest tests.test_resources
python -m unittest tests.test_configs
./test.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


"python-3.6":
<<: *test-template
Expand All@@ -80,4 +67,4 @@ workflows:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
- "python-3.7"
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements-py37.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components==0.12.0rc3
dash-flow-example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components>=0.12.0rc3
dash_flow_example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
## Unreleased
## Removed
- Removed support for `Event` system. Use event properties instead, for example the `n_clicks` property instead of the `click` event, see [#531](https://github.com/plotly/dash/issues/531) for details. `dash_renderer` MUST be upgraded to >=0.17.0 together with this, and it is recommended to update `dash_core_components` to >=0.43.0 and `dash_html_components` to >=0.14.0. [#550](https://github.com/plotly/dash/pull/550)

## [0.35.3] - 2019-01-23
## Fixed
- Asset blueprint takes routes prefix into it's static path. [#547](https://github.com/plotly/dash/pull/547)
Expand Down
51 changes: 17 additions & 34 deletions dash/dash.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,13 +15,14 @@

from functools import wraps

import plotly
import dash_renderer
import flask
from flask import Flask, Response
from flask_compress import Compress

from .dependencies import Event, Input, Output, State
import plotly
import dash_renderer

from .dependencies import Input, Output, State
from .resources import Scripts, Css
from .development.base_component import Component
from . import exceptions
Expand DownExpand Up@@ -622,7 +623,6 @@ def dependencies(self):
},
'inputs': v['inputs'],
'state': v['state'],
'events': v['events']
} for k, v in self.callback_map.items()
])

Expand All@@ -633,7 +633,7 @@ def react(self, *args, **kwargs):
'Use `callback` instead. `callback` has a new syntax too, '
'so make sure to call `help(app.callback)` to learn more.')

def _validate_callback(self, output, inputs, state, events):
def _validate_callback(self, output, inputs, state):
# pylint: disable=too-many-branches
layout = self._cached_layout or self._layout_value()

Expand All@@ -652,8 +652,7 @@ def _validate_callback(self, output, inputs, state, events):

for args, obj, name in [([output], Output, 'Output'),
(inputs, Input, 'Input'),
(state, State, 'State'),
(events, Event, 'Event')]:
(state, State, 'State')]:

if not isinstance(args, list):
raise exceptions.IncorrectTypeException(
Expand DownExpand Up@@ -721,32 +720,20 @@ def _validate_callback(self, output, inputs, state, events):
component.available_properties).replace(
' ', ''))

if (hasattr(arg, 'component_event') and
arg.component_event not in
component.available_events):
if hasattr(arg, 'component_event'):
raise exceptions.NonExistentEventException('''
Attempting to assign a callback with
the event "{}" but the component
"{}" doesn't have "{}" as an event.\n
Here is a list of the available events in "{}":
{}
'''.format(
arg.component_event,
arg.component_id,
arg.component_event,
arg.component_id,
component.available_events).replace(' ', ''))
Events have been removed.
Use the associated property instead.
''')

if state and not events and not inputs:
raise exceptions.MissingEventsException('''
if state and not inputs:
raise exceptions.MissingInputsException('''
This callback has {} `State` {}
but no `Input` elements or `Event` elements.\n
Without `Input` or `Event` elements, this callback
but no `Input` elements.\n
Without `Input` elements, this callback
will never get called.\n
(Subscribing to input components will cause the
callback to be called whenever their values
change and subscribing to an event will cause the
callback to be called whenever the event is fired.)
callback to be called whenever their values change.)
'''.format(
len(state),
'elements' if len(state) > 1 else 'element'
Expand DownExpand Up@@ -888,8 +875,8 @@ def _validate_value(val, index=None):
# TODO - Check this map for recursive or other ill-defined non-tree
# relationships
# pylint: disable=dangerous-default-value
def callback(self, output, inputs=[], state=[], events=[]):
self._validate_callback(output, inputs, state, events)
def callback(self, output, inputs=[], state=[]):
self._validate_callback(output, inputs, state)

callback_id = '{}.{}'.format(
output.component_id, output.component_property
Expand All@@ -902,10 +889,6 @@ def callback(self, output, inputs=[], state=[], events=[]):
'state': [
{'id': c.component_id, 'property': c.component_property}
for c in state
],
'events': [
{'id': c.component_id, 'event': c.component_event}
for c in events
]
}

Expand Down
7 changes: 0 additions & 7 deletions dash/dependencies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,10 +17,3 @@ class State:
def __init__(self, component_id, component_property):
self.component_id = component_id
self.component_property = component_property


# pylint: disable=old-style-class, too-few-public-methods
class Event:
def __init__(self, component_id, component_event):
self.component_id = component_id
self.component_event = component_event
50 changes: 18 additions & 32 deletions dash/development/_py_components_generation.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@
import os

from dash.development.base_component import _explicitize_args
from dash.exceptions import NonExistentEventException
from ._all_keywords import python_keywords
from .base_component import Component

Expand All@@ -27,8 +28,7 @@ def generate_class_string(typename, props, description, namespace):
string

"""
# TODO _prop_names, _type, _namespace, available_events,
# and available_properties
# TODO _prop_names, _type, _namespace, and available_properties
# can be modified by a Dash JS developer via setattr
# TODO - Tab out the repr for the repr of these components to make it
# look more like a hierarchical tree
Expand All@@ -52,7 +52,6 @@ def __init__(self, {default_argtext}):
self._namespace = '{namespace}'
self._valid_wildcard_attributes =\
{list_of_valid_wildcard_attr_prefixes}
self.available_events = {events}
self.available_properties = {list_of_valid_keys}
self.available_wildcard_properties =\
{list_of_valid_wildcard_attr_prefixes}
Expand DownExpand Up@@ -101,11 +100,11 @@ def __repr__(self):
docstring = create_docstring(
component_name=typename,
props=filtered_props,
events=parse_events(props),
description=description).replace('\r\n', '\n')

prohibit_events(props)

# pylint: disable=unused-variable
events = '[' + ', '.join(parse_events(props)) + ']'
prop_keys = list(props.keys())
if 'children' in props:
prop_keys.remove('children')
Expand All@@ -122,7 +121,7 @@ def __repr__(self):
for p in prop_keys
if not p.endswith("-*") and
p not in python_keywords and
p not in ['dashEvents', 'fireEvent', 'setProps']] + ['**kwargs']
p != 'setProps'] + ['**kwargs']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that was intentional but still present for the R generation

@rpkylerpkyleJan 21, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have modified my code to match.

)

required_args = required_props(props)
Expand DownExpand Up@@ -233,7 +232,7 @@ def required_props(props):
if prop['required']]


def create_docstring(component_name, props, events, description):
def create_docstring(component_name, props, description):
"""
Create the Dash component docstring

Expand All@@ -243,8 +242,6 @@ def create_docstring(component_name, props, events, description):
Component name
props: dict
Dictionary with {propName: propMetadata} structure
events: list
List of Dash events
description: str
Component description

Expand All@@ -259,9 +256,7 @@ def create_docstring(component_name, props, events, description):
return (
"""A {name} component.\n{description}

Keyword arguments:\n{args}

Available events: {events}"""
Keyword arguments:\n{args}"""
).format(
name=component_name,
description=description,
Expand All@@ -274,30 +269,26 @@ def create_docstring(component_name, props, events, description):
description=prop['description'],
indent_num=0,
is_flow_type='flowType' in prop and 'type' not in prop)
for p, prop in list(filter_props(props).items())),
events=', '.join(events))
for p, prop in list(filter_props(props).items())))


def parse_events(props):
def prohibit_events(props):
"""
Pull out the dashEvents from the Component props
Events have been removed. Raise an error if we see dashEvents or fireEvents

Parameters
----------
props: dict
Dictionary with {propName: propMetadata} structure

Returns
Raises
-------
list
List of Dash event strings
?
"""
if 'dashEvents' in props and props['dashEvents']['type']['name'] == 'enum':
events = [v['value'] for v in props['dashEvents']['type']['value']]
else:
events = []

return events
if 'dashEvents' in props or 'fireEvents' in props:
raise NonExistentEventException(
'Events are no longer supported by dash. Use properties instead, '
'eg `n_clicks` instead of a `click` event.')


def parse_wildcards(props):
Expand DownExpand Up@@ -349,7 +340,6 @@ def filter_props(props):
Filter props from the Component arguments to exclude:
- Those without a "type" or a "flowType" field
- Those with arg.type.name in {'func', 'symbol', 'instanceOf'}
- dashEvents as a name

Parameters
----------
Expand DownExpand Up@@ -415,10 +405,6 @@ def filter_props(props):
else:
raise ValueError

# dashEvents are a special oneOf property that is used for subscribing
# to events but it's never set as a property
if arg_name in ['dashEvents']:
filtered_props.pop(arg_name)
return filtered_props


Expand DownExpand Up@@ -518,7 +504,7 @@ def map_js_to_py_types_prop_types(type_object):
', '.join(
"'{}'".format(t)
for t in list(type_object['value'].keys())),
'Those keys have the following types:\n{}'.format(
'Those keys have the following types:\n{}'.format(
'\n'.join(create_prop_docstring(
prop_name=prop_name,
type_object=prop,
Expand DownExpand Up@@ -561,7 +547,7 @@ def map_js_to_py_types_flow_types(type_object):
signature=lambda indent_num: 'dict containing keys {}.\n{}'.format(
', '.join("'{}'".format(d['key'])
for d in type_object['signature']['properties']),
'{}Those keys have the following types:\n{}'.format(
'{}Those keys have the following types:\n{}'.format(
' ' * indent_num,
'\n'.join(
create_prop_docstring(
Expand Down
2 changes: 1 addition & 1 deletion dash/exceptions.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@ class IncorrectTypeException(CallbackException):
pass


class MissingEventsException(CallbackException):
class MissingInputsException(CallbackException):
pass


Expand Down
2 changes: 1 addition & 1 deletion dash/extract-meta.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ const componentPaths = process.argv.slice(3);
const ignorePattern = new RegExp(process.argv[2]);

const excludedDocProps = [
'setProps', 'id', 'className', 'style', 'dashEvents', 'fireEvent'
'setProps', 'id', 'className', 'style'
];

if (!componentPaths.length) {
Expand Down
20 changes: 20 additions & 0 deletions test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
EXIT_STATE=0

python -m unittest tests.development.test_base_component || EXIT_STATE=$?
python -m unittest tests.development.test_component_loader || EXIT_STATE=$?
python -m unittest tests.test_integration || EXIT_STATE=$?
python -m unittest tests.test_resources || EXIT_STATE=$?
python -m unittest tests.test_configs || EXIT_STATE=$?

pylint dash setup.py --rcfile=$PYLINTRC || EXIT_STATE=$?
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109 || EXIT_STATE=$?
flake8 dash setup.py || EXIT_STATE=$?
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests || EXIT_STATE=$?

if [ $EXIT_STATE -ne 0 ]; then
Comment thread
alexcjohnson marked this conversation as resolved.
echo "One or more tests failed"
else
echo "All tests passed!"
fi

exit $EXIT_STATE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include the linting also ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'll move linting in here too.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting into test.sh -> 2c9a3c8

10 changes: 0 additions & 10 deletions tests/development/TestReactComponent.react.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,19 +91,9 @@ ReactComponent.propTypes = {
}
}),

// special dash events

children: React.PropTypes.node,

id: React.PropTypes.string,


// dashEvents is a special prop that is used to events validation
dashEvents: React.PropTypes.oneOf([
'restyle',
'relayout',
'click'
])
};

ReactComponent.defaultProps = {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,25 +35,12 @@ jobs:
paths:
- "venv"

- run:
name: Run lint
command: |
. venv/bin/activate
pylint dash setup.py --rcfile=$PYLINTRC
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109
flake8 dash setup.py
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest tests.development.test_base_component
python -m unittest tests.development.test_component_loader
python -m unittest tests.test_integration
python -m unittest tests.test_resources
python -m unittest tests.test_configs
./test.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


"python-3.6":
<<: *test-template
Expand All@@ -80,4 +67,4 @@ workflows:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
- "python-3.7"
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements-py37.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components==0.12.0rc3
dash-flow-example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components>=0.12.0rc3
dash_flow_example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
## Unreleased
## Removed
- Removed support for `Event` system. Use event properties instead, for example the `n_clicks` property instead of the `click` event, see [#531](https://github.com/plotly/dash/issues/531) for details. `dash_renderer` MUST be upgraded to >=0.17.0 together with this, and it is recommended to update `dash_core_components` to >=0.43.0 and `dash_html_components` to >=0.14.0. [#550](https://github.com/plotly/dash/pull/550)

## [0.35.3] - 2019-01-23
## Fixed
- Asset blueprint takes routes prefix into it's static path. [#547](https://github.com/plotly/dash/pull/547)
Expand Down
51 changes: 17 additions & 34 deletions dash/dash.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,13 +15,14 @@

from functools import wraps

import plotly
import dash_renderer
import flask
from flask import Flask, Response
from flask_compress import Compress

from .dependencies import Event, Input, Output, State
import plotly
import dash_renderer

from .dependencies import Input, Output, State
from .resources import Scripts, Css
from .development.base_component import Component
from . import exceptions
Expand DownExpand Up@@ -622,7 +623,6 @@ def dependencies(self):
},
'inputs': v['inputs'],
'state': v['state'],
'events': v['events']
} for k, v in self.callback_map.items()
])

Expand All@@ -633,7 +633,7 @@ def react(self, *args, **kwargs):
'Use `callback` instead. `callback` has a new syntax too, '
'so make sure to call `help(app.callback)` to learn more.')

def _validate_callback(self, output, inputs, state, events):
def _validate_callback(self, output, inputs, state):
# pylint: disable=too-many-branches
layout = self._cached_layout or self._layout_value()

Expand All@@ -652,8 +652,7 @@ def _validate_callback(self, output, inputs, state, events):

for args, obj, name in [([output], Output, 'Output'),
(inputs, Input, 'Input'),
(state, State, 'State'),
(events, Event, 'Event')]:
(state, State, 'State')]:

if not isinstance(args, list):
raise exceptions.IncorrectTypeException(
Expand DownExpand Up@@ -721,32 +720,20 @@ def _validate_callback(self, output, inputs, state, events):
component.available_properties).replace(
' ', ''))

if (hasattr(arg, 'component_event') and
arg.component_event not in
component.available_events):
if hasattr(arg, 'component_event'):
raise exceptions.NonExistentEventException('''
Attempting to assign a callback with
the event "{}" but the component
"{}" doesn't have "{}" as an event.\n
Here is a list of the available events in "{}":
{}
'''.format(
arg.component_event,
arg.component_id,
arg.component_event,
arg.component_id,
component.available_events).replace(' ', ''))
Events have been removed.
Use the associated property instead.
''')

if state and not events and not inputs:
raise exceptions.MissingEventsException('''
if state and not inputs:
raise exceptions.MissingInputsException('''
This callback has {} `State` {}
but no `Input` elements or `Event` elements.\n
Without `Input` or `Event` elements, this callback
but no `Input` elements.\n
Without `Input` elements, this callback
will never get called.\n
(Subscribing to input components will cause the
callback to be called whenever their values
change and subscribing to an event will cause the
callback to be called whenever the event is fired.)
callback to be called whenever their values change.)
'''.format(
len(state),
'elements' if len(state) > 1 else 'element'
Expand DownExpand Up@@ -888,8 +875,8 @@ def _validate_value(val, index=None):
# TODO - Check this map for recursive or other ill-defined non-tree
# relationships
# pylint: disable=dangerous-default-value
def callback(self, output, inputs=[], state=[], events=[]):
self._validate_callback(output, inputs, state, events)
def callback(self, output, inputs=[], state=[]):
self._validate_callback(output, inputs, state)

callback_id = '{}.{}'.format(
output.component_id, output.component_property
Expand All@@ -902,10 +889,6 @@ def callback(self, output, inputs=[], state=[], events=[]):
'state': [
{'id': c.component_id, 'property': c.component_property}
for c in state
],
'events': [
{'id': c.component_id, 'event': c.component_event}
for c in events
]
}

Expand Down
7 changes: 0 additions & 7 deletions dash/dependencies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,10 +17,3 @@ class State:
def __init__(self, component_id, component_property):
self.component_id = component_id
self.component_property = component_property


# pylint: disable=old-style-class, too-few-public-methods
class Event:
def __init__(self, component_id, component_event):
self.component_id = component_id
self.component_event = component_event
50 changes: 18 additions & 32 deletions dash/development/_py_components_generation.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@
import os

from dash.development.base_component import _explicitize_args
from dash.exceptions import NonExistentEventException
from ._all_keywords import python_keywords
from .base_component import Component

Expand All@@ -27,8 +28,7 @@ def generate_class_string(typename, props, description, namespace):
string

"""
# TODO _prop_names, _type, _namespace, available_events,
# and available_properties
# TODO _prop_names, _type, _namespace, and available_properties
# can be modified by a Dash JS developer via setattr
# TODO - Tab out the repr for the repr of these components to make it
# look more like a hierarchical tree
Expand All@@ -52,7 +52,6 @@ def __init__(self, {default_argtext}):
self._namespace = '{namespace}'
self._valid_wildcard_attributes =\
{list_of_valid_wildcard_attr_prefixes}
self.available_events = {events}
self.available_properties = {list_of_valid_keys}
self.available_wildcard_properties =\
{list_of_valid_wildcard_attr_prefixes}
Expand DownExpand Up@@ -101,11 +100,11 @@ def __repr__(self):
docstring = create_docstring(
component_name=typename,
props=filtered_props,
events=parse_events(props),
description=description).replace('\r\n', '\n')

prohibit_events(props)

# pylint: disable=unused-variable
events = '[' + ', '.join(parse_events(props)) + ']'
prop_keys = list(props.keys())
if 'children' in props:
prop_keys.remove('children')
Expand All@@ -122,7 +121,7 @@ def __repr__(self):
for p in prop_keys
if not p.endswith("-*") and
p not in python_keywords and
p not in ['dashEvents', 'fireEvent', 'setProps']] + ['**kwargs']
p != 'setProps'] + ['**kwargs']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that was intentional but still present for the R generation

@rpkylerpkyleJan 21, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have modified my code to match.

)

required_args = required_props(props)
Expand DownExpand Up@@ -233,7 +232,7 @@ def required_props(props):
if prop['required']]


def create_docstring(component_name, props, events, description):
def create_docstring(component_name, props, description):
"""
Create the Dash component docstring

Expand All@@ -243,8 +242,6 @@ def create_docstring(component_name, props, events, description):
Component name
props: dict
Dictionary with {propName: propMetadata} structure
events: list
List of Dash events
description: str
Component description

Expand All@@ -259,9 +256,7 @@ def create_docstring(component_name, props, events, description):
return (
"""A {name} component.\n{description}

Keyword arguments:\n{args}

Available events: {events}"""
Keyword arguments:\n{args}"""
).format(
name=component_name,
description=description,
Expand All@@ -274,30 +269,26 @@ def create_docstring(component_name, props, events, description):
description=prop['description'],
indent_num=0,
is_flow_type='flowType' in prop and 'type' not in prop)
for p, prop in list(filter_props(props).items())),
events=', '.join(events))
for p, prop in list(filter_props(props).items())))


def parse_events(props):
def prohibit_events(props):
"""
Pull out the dashEvents from the Component props
Events have been removed. Raise an error if we see dashEvents or fireEvents

Parameters
----------
props: dict
Dictionary with {propName: propMetadata} structure

Returns
Raises
-------
list
List of Dash event strings
?
"""
if 'dashEvents' in props and props['dashEvents']['type']['name'] == 'enum':
events = [v['value'] for v in props['dashEvents']['type']['value']]
else:
events = []

return events
if 'dashEvents' in props or 'fireEvents' in props:
raise NonExistentEventException(
'Events are no longer supported by dash. Use properties instead, '
'eg `n_clicks` instead of a `click` event.')


def parse_wildcards(props):
Expand DownExpand Up@@ -349,7 +340,6 @@ def filter_props(props):
Filter props from the Component arguments to exclude:
- Those without a "type" or a "flowType" field
- Those with arg.type.name in {'func', 'symbol', 'instanceOf'}
- dashEvents as a name

Parameters
----------
Expand DownExpand Up@@ -415,10 +405,6 @@ def filter_props(props):
else:
raise ValueError

# dashEvents are a special oneOf property that is used for subscribing
# to events but it's never set as a property
if arg_name in ['dashEvents']:
filtered_props.pop(arg_name)
return filtered_props


Expand DownExpand Up@@ -518,7 +504,7 @@ def map_js_to_py_types_prop_types(type_object):
', '.join(
"'{}'".format(t)
for t in list(type_object['value'].keys())),
'Those keys have the following types:\n{}'.format(
'Those keys have the following types:\n{}'.format(
'\n'.join(create_prop_docstring(
prop_name=prop_name,
type_object=prop,
Expand DownExpand Up@@ -561,7 +547,7 @@ def map_js_to_py_types_flow_types(type_object):
signature=lambda indent_num: 'dict containing keys {}.\n{}'.format(
', '.join("'{}'".format(d['key'])
for d in type_object['signature']['properties']),
'{}Those keys have the following types:\n{}'.format(
'{}Those keys have the following types:\n{}'.format(
' ' * indent_num,
'\n'.join(
create_prop_docstring(
Expand Down
2 changes: 1 addition & 1 deletion dash/exceptions.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@ class IncorrectTypeException(CallbackException):
pass


class MissingEventsException(CallbackException):
class MissingInputsException(CallbackException):
pass


Expand Down
2 changes: 1 addition & 1 deletion dash/extract-meta.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ const componentPaths = process.argv.slice(3);
const ignorePattern = new RegExp(process.argv[2]);

const excludedDocProps = [
'setProps', 'id', 'className', 'style', 'dashEvents', 'fireEvent'
'setProps', 'id', 'className', 'style'
];

if (!componentPaths.length) {
Expand Down
20 changes: 20 additions & 0 deletions test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
EXIT_STATE=0

python -m unittest tests.development.test_base_component || EXIT_STATE=$?
python -m unittest tests.development.test_component_loader || EXIT_STATE=$?
python -m unittest tests.test_integration || EXIT_STATE=$?
python -m unittest tests.test_resources || EXIT_STATE=$?
python -m unittest tests.test_configs || EXIT_STATE=$?

pylint dash setup.py --rcfile=$PYLINTRC || EXIT_STATE=$?
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109 || EXIT_STATE=$?
flake8 dash setup.py || EXIT_STATE=$?
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests || EXIT_STATE=$?

if [ $EXIT_STATE -ne 0 ]; then
Comment thread
alexcjohnson marked this conversation as resolved.
echo "One or more tests failed"
else
echo "All tests passed!"
fi

exit $EXIT_STATE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include the linting also ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'll move linting in here too.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting into test.sh -> 2c9a3c8

10 changes: 0 additions & 10 deletions tests/development/TestReactComponent.react.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,19 +91,9 @@ ReactComponent.propTypes = {
}
}),

// special dash events

children: React.PropTypes.node,

id: React.PropTypes.string,


// dashEvents is a special prop that is used to events validation
dashEvents: React.PropTypes.oneOf([
'restyle',
'relayout',
'click'
])
};

ReactComponent.defaultProps = {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,25 +35,12 @@ jobs:
paths:
- "venv"

- run:
name: Run lint
command: |
. venv/bin/activate
pylint dash setup.py --rcfile=$PYLINTRC
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109
flake8 dash setup.py
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest tests.development.test_base_component
python -m unittest tests.development.test_component_loader
python -m unittest tests.test_integration
python -m unittest tests.test_resources
python -m unittest tests.test_configs
./test.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


"python-3.6":
<<: *test-template
Expand All@@ -80,4 +67,4 @@ workflows:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
- "python-3.7"
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements-py37.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components==0.12.0rc3
dash-flow-example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components>=0.12.0rc3
dash_flow_example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
## Unreleased
## Removed
- Removed support for `Event` system. Use event properties instead, for example the `n_clicks` property instead of the `click` event, see [#531](https://github.com/plotly/dash/issues/531) for details. `dash_renderer` MUST be upgraded to >=0.17.0 together with this, and it is recommended to update `dash_core_components` to >=0.43.0 and `dash_html_components` to >=0.14.0. [#550](https://github.com/plotly/dash/pull/550)

## [0.35.3] - 2019-01-23
## Fixed
- Asset blueprint takes routes prefix into it's static path. [#547](https://github.com/plotly/dash/pull/547)
Expand Down
51 changes: 17 additions & 34 deletions dash/dash.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,13 +15,14 @@

from functools import wraps

import plotly
import dash_renderer
import flask
from flask import Flask, Response
from flask_compress import Compress

from .dependencies import Event, Input, Output, State
import plotly
import dash_renderer

from .dependencies import Input, Output, State
from .resources import Scripts, Css
from .development.base_component import Component
from . import exceptions
Expand DownExpand Up@@ -622,7 +623,6 @@ def dependencies(self):
},
'inputs': v['inputs'],
'state': v['state'],
'events': v['events']
} for k, v in self.callback_map.items()
])

Expand All@@ -633,7 +633,7 @@ def react(self, *args, **kwargs):
'Use `callback` instead. `callback` has a new syntax too, '
'so make sure to call `help(app.callback)` to learn more.')

def _validate_callback(self, output, inputs, state, events):
def _validate_callback(self, output, inputs, state):
# pylint: disable=too-many-branches
layout = self._cached_layout or self._layout_value()

Expand All@@ -652,8 +652,7 @@ def _validate_callback(self, output, inputs, state, events):

for args, obj, name in [([output], Output, 'Output'),
(inputs, Input, 'Input'),
(state, State, 'State'),
(events, Event, 'Event')]:
(state, State, 'State')]:

if not isinstance(args, list):
raise exceptions.IncorrectTypeException(
Expand DownExpand Up@@ -721,32 +720,20 @@ def _validate_callback(self, output, inputs, state, events):
component.available_properties).replace(
' ', ''))

if (hasattr(arg, 'component_event') and
arg.component_event not in
component.available_events):
if hasattr(arg, 'component_event'):
raise exceptions.NonExistentEventException('''
Attempting to assign a callback with
the event "{}" but the component
"{}" doesn't have "{}" as an event.\n
Here is a list of the available events in "{}":
{}
'''.format(
arg.component_event,
arg.component_id,
arg.component_event,
arg.component_id,
component.available_events).replace(' ', ''))
Events have been removed.
Use the associated property instead.
''')

if state and not events and not inputs:
raise exceptions.MissingEventsException('''
if state and not inputs:
raise exceptions.MissingInputsException('''
This callback has {} `State` {}
but no `Input` elements or `Event` elements.\n
Without `Input` or `Event` elements, this callback
but no `Input` elements.\n
Without `Input` elements, this callback
will never get called.\n
(Subscribing to input components will cause the
callback to be called whenever their values
change and subscribing to an event will cause the
callback to be called whenever the event is fired.)
callback to be called whenever their values change.)
'''.format(
len(state),
'elements' if len(state) > 1 else 'element'
Expand DownExpand Up@@ -888,8 +875,8 @@ def _validate_value(val, index=None):
# TODO - Check this map for recursive or other ill-defined non-tree
# relationships
# pylint: disable=dangerous-default-value
def callback(self, output, inputs=[], state=[], events=[]):
self._validate_callback(output, inputs, state, events)
def callback(self, output, inputs=[], state=[]):
self._validate_callback(output, inputs, state)

callback_id = '{}.{}'.format(
output.component_id, output.component_property
Expand All@@ -902,10 +889,6 @@ def callback(self, output, inputs=[], state=[], events=[]):
'state': [
{'id': c.component_id, 'property': c.component_property}
for c in state
],
'events': [
{'id': c.component_id, 'event': c.component_event}
for c in events
]
}

Expand Down
7 changes: 0 additions & 7 deletions dash/dependencies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,10 +17,3 @@ class State:
def __init__(self, component_id, component_property):
self.component_id = component_id
self.component_property = component_property


# pylint: disable=old-style-class, too-few-public-methods
class Event:
def __init__(self, component_id, component_event):
self.component_id = component_id
self.component_event = component_event
50 changes: 18 additions & 32 deletions dash/development/_py_components_generation.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@
import os

from dash.development.base_component import _explicitize_args
from dash.exceptions import NonExistentEventException
from ._all_keywords import python_keywords
from .base_component import Component

Expand All@@ -27,8 +28,7 @@ def generate_class_string(typename, props, description, namespace):
string

"""
# TODO _prop_names, _type, _namespace, available_events,
# and available_properties
# TODO _prop_names, _type, _namespace, and available_properties
# can be modified by a Dash JS developer via setattr
# TODO - Tab out the repr for the repr of these components to make it
# look more like a hierarchical tree
Expand All@@ -52,7 +52,6 @@ def __init__(self, {default_argtext}):
self._namespace = '{namespace}'
self._valid_wildcard_attributes =\
{list_of_valid_wildcard_attr_prefixes}
self.available_events = {events}
self.available_properties = {list_of_valid_keys}
self.available_wildcard_properties =\
{list_of_valid_wildcard_attr_prefixes}
Expand DownExpand Up@@ -101,11 +100,11 @@ def __repr__(self):
docstring = create_docstring(
component_name=typename,
props=filtered_props,
events=parse_events(props),
description=description).replace('\r\n', '\n')

prohibit_events(props)

# pylint: disable=unused-variable
events = '[' + ', '.join(parse_events(props)) + ']'
prop_keys = list(props.keys())
if 'children' in props:
prop_keys.remove('children')
Expand All@@ -122,7 +121,7 @@ def __repr__(self):
for p in prop_keys
if not p.endswith("-*") and
p not in python_keywords and
p not in ['dashEvents', 'fireEvent', 'setProps']] + ['**kwargs']
p != 'setProps'] + ['**kwargs']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that was intentional but still present for the R generation

@rpkylerpkyleJan 21, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have modified my code to match.

)

required_args = required_props(props)
Expand DownExpand Up@@ -233,7 +232,7 @@ def required_props(props):
if prop['required']]


def create_docstring(component_name, props, events, description):
def create_docstring(component_name, props, description):
"""
Create the Dash component docstring

Expand All@@ -243,8 +242,6 @@ def create_docstring(component_name, props, events, description):
Component name
props: dict
Dictionary with {propName: propMetadata} structure
events: list
List of Dash events
description: str
Component description

Expand All@@ -259,9 +256,7 @@ def create_docstring(component_name, props, events, description):
return (
"""A {name} component.\n{description}

Keyword arguments:\n{args}

Available events: {events}"""
Keyword arguments:\n{args}"""
).format(
name=component_name,
description=description,
Expand All@@ -274,30 +269,26 @@ def create_docstring(component_name, props, events, description):
description=prop['description'],
indent_num=0,
is_flow_type='flowType' in prop and 'type' not in prop)
for p, prop in list(filter_props(props).items())),
events=', '.join(events))
for p, prop in list(filter_props(props).items())))


def parse_events(props):
def prohibit_events(props):
"""
Pull out the dashEvents from the Component props
Events have been removed. Raise an error if we see dashEvents or fireEvents

Parameters
----------
props: dict
Dictionary with {propName: propMetadata} structure

Returns
Raises
-------
list
List of Dash event strings
?
"""
if 'dashEvents' in props and props['dashEvents']['type']['name'] == 'enum':
events = [v['value'] for v in props['dashEvents']['type']['value']]
else:
events = []

return events
if 'dashEvents' in props or 'fireEvents' in props:
raise NonExistentEventException(
'Events are no longer supported by dash. Use properties instead, '
'eg `n_clicks` instead of a `click` event.')


def parse_wildcards(props):
Expand DownExpand Up@@ -349,7 +340,6 @@ def filter_props(props):
Filter props from the Component arguments to exclude:
- Those without a "type" or a "flowType" field
- Those with arg.type.name in {'func', 'symbol', 'instanceOf'}
- dashEvents as a name

Parameters
----------
Expand DownExpand Up@@ -415,10 +405,6 @@ def filter_props(props):
else:
raise ValueError

# dashEvents are a special oneOf property that is used for subscribing
# to events but it's never set as a property
if arg_name in ['dashEvents']:
filtered_props.pop(arg_name)
return filtered_props


Expand DownExpand Up@@ -518,7 +504,7 @@ def map_js_to_py_types_prop_types(type_object):
', '.join(
"'{}'".format(t)
for t in list(type_object['value'].keys())),
'Those keys have the following types:\n{}'.format(
'Those keys have the following types:\n{}'.format(
'\n'.join(create_prop_docstring(
prop_name=prop_name,
type_object=prop,
Expand DownExpand Up@@ -561,7 +547,7 @@ def map_js_to_py_types_flow_types(type_object):
signature=lambda indent_num: 'dict containing keys {}.\n{}'.format(
', '.join("'{}'".format(d['key'])
for d in type_object['signature']['properties']),
'{}Those keys have the following types:\n{}'.format(
'{}Those keys have the following types:\n{}'.format(
' ' * indent_num,
'\n'.join(
create_prop_docstring(
Expand Down
2 changes: 1 addition & 1 deletion dash/exceptions.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@ class IncorrectTypeException(CallbackException):
pass


class MissingEventsException(CallbackException):
class MissingInputsException(CallbackException):
pass


Expand Down
2 changes: 1 addition & 1 deletion dash/extract-meta.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ const componentPaths = process.argv.slice(3);
const ignorePattern = new RegExp(process.argv[2]);

const excludedDocProps = [
'setProps', 'id', 'className', 'style', 'dashEvents', 'fireEvent'
'setProps', 'id', 'className', 'style'
];

if (!componentPaths.length) {
Expand Down
20 changes: 20 additions & 0 deletions test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
EXIT_STATE=0

python -m unittest tests.development.test_base_component || EXIT_STATE=$?
python -m unittest tests.development.test_component_loader || EXIT_STATE=$?
python -m unittest tests.test_integration || EXIT_STATE=$?
python -m unittest tests.test_resources || EXIT_STATE=$?
python -m unittest tests.test_configs || EXIT_STATE=$?

pylint dash setup.py --rcfile=$PYLINTRC || EXIT_STATE=$?
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109 || EXIT_STATE=$?
flake8 dash setup.py || EXIT_STATE=$?
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests || EXIT_STATE=$?

if [ $EXIT_STATE -ne 0 ]; then
Comment thread
alexcjohnson marked this conversation as resolved.
echo "One or more tests failed"
else
echo "All tests passed!"
fi

exit $EXIT_STATE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include the linting also ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'll move linting in here too.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting into test.sh -> 2c9a3c8

10 changes: 0 additions & 10 deletions tests/development/TestReactComponent.react.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,19 +91,9 @@ ReactComponent.propTypes = {
}
}),

// special dash events

children: React.PropTypes.node,

id: React.PropTypes.string,


// dashEvents is a special prop that is used to events validation
dashEvents: React.PropTypes.oneOf([
'restyle',
'relayout',
'click'
])
};

ReactComponent.defaultProps = {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,25 +35,12 @@ jobs:
paths:
- "venv"

- run:
name: Run lint
command: |
. venv/bin/activate
pylint dash setup.py --rcfile=$PYLINTRC
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109
flake8 dash setup.py
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest tests.development.test_base_component
python -m unittest tests.development.test_component_loader
python -m unittest tests.test_integration
python -m unittest tests.test_resources
python -m unittest tests.test_configs
./test.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


"python-3.6":
<<: *test-template
Expand All@@ -80,4 +67,4 @@ workflows:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
- "python-3.7"
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements-py37.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components==0.12.0rc3
dash-flow-example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components>=0.12.0rc3
dash_flow_example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
## Unreleased
## Removed
- Removed support for `Event` system. Use event properties instead, for example the `n_clicks` property instead of the `click` event, see [#531](https://github.com/plotly/dash/issues/531) for details. `dash_renderer` MUST be upgraded to >=0.17.0 together with this, and it is recommended to update `dash_core_components` to >=0.43.0 and `dash_html_components` to >=0.14.0. [#550](https://github.com/plotly/dash/pull/550)

## [0.35.3] - 2019-01-23
## Fixed
- Asset blueprint takes routes prefix into it's static path. [#547](https://github.com/plotly/dash/pull/547)
Expand Down
51 changes: 17 additions & 34 deletions dash/dash.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,13 +15,14 @@

from functools import wraps

import plotly
import dash_renderer
import flask
from flask import Flask, Response
from flask_compress import Compress

from .dependencies import Event, Input, Output, State
import plotly
import dash_renderer

from .dependencies import Input, Output, State
from .resources import Scripts, Css
from .development.base_component import Component
from . import exceptions
Expand DownExpand Up@@ -622,7 +623,6 @@ def dependencies(self):
},
'inputs': v['inputs'],
'state': v['state'],
'events': v['events']
} for k, v in self.callback_map.items()
])

Expand All@@ -633,7 +633,7 @@ def react(self, *args, **kwargs):
'Use `callback` instead. `callback` has a new syntax too, '
'so make sure to call `help(app.callback)` to learn more.')

def _validate_callback(self, output, inputs, state, events):
def _validate_callback(self, output, inputs, state):
# pylint: disable=too-many-branches
layout = self._cached_layout or self._layout_value()

Expand All@@ -652,8 +652,7 @@ def _validate_callback(self, output, inputs, state, events):

for args, obj, name in [([output], Output, 'Output'),
(inputs, Input, 'Input'),
(state, State, 'State'),
(events, Event, 'Event')]:
(state, State, 'State')]:

if not isinstance(args, list):
raise exceptions.IncorrectTypeException(
Expand DownExpand Up@@ -721,32 +720,20 @@ def _validate_callback(self, output, inputs, state, events):
component.available_properties).replace(
' ', ''))

if (hasattr(arg, 'component_event') and
arg.component_event not in
component.available_events):
if hasattr(arg, 'component_event'):
raise exceptions.NonExistentEventException('''
Attempting to assign a callback with
the event "{}" but the component
"{}" doesn't have "{}" as an event.\n
Here is a list of the available events in "{}":
{}
'''.format(
arg.component_event,
arg.component_id,
arg.component_event,
arg.component_id,
component.available_events).replace(' ', ''))
Events have been removed.
Use the associated property instead.
''')

if state and not events and not inputs:
raise exceptions.MissingEventsException('''
if state and not inputs:
raise exceptions.MissingInputsException('''
This callback has {} `State` {}
but no `Input` elements or `Event` elements.\n
Without `Input` or `Event` elements, this callback
but no `Input` elements.\n
Without `Input` elements, this callback
will never get called.\n
(Subscribing to input components will cause the
callback to be called whenever their values
change and subscribing to an event will cause the
callback to be called whenever the event is fired.)
callback to be called whenever their values change.)
'''.format(
len(state),
'elements' if len(state) > 1 else 'element'
Expand DownExpand Up@@ -888,8 +875,8 @@ def _validate_value(val, index=None):
# TODO - Check this map for recursive or other ill-defined non-tree
# relationships
# pylint: disable=dangerous-default-value
def callback(self, output, inputs=[], state=[], events=[]):
self._validate_callback(output, inputs, state, events)
def callback(self, output, inputs=[], state=[]):
self._validate_callback(output, inputs, state)

callback_id = '{}.{}'.format(
output.component_id, output.component_property
Expand All@@ -902,10 +889,6 @@ def callback(self, output, inputs=[], state=[], events=[]):
'state': [
{'id': c.component_id, 'property': c.component_property}
for c in state
],
'events': [
{'id': c.component_id, 'event': c.component_event}
for c in events
]
}

Expand Down
7 changes: 0 additions & 7 deletions dash/dependencies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,10 +17,3 @@ class State:
def __init__(self, component_id, component_property):
self.component_id = component_id
self.component_property = component_property


# pylint: disable=old-style-class, too-few-public-methods
class Event:
def __init__(self, component_id, component_event):
self.component_id = component_id
self.component_event = component_event
50 changes: 18 additions & 32 deletions dash/development/_py_components_generation.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@
import os

from dash.development.base_component import _explicitize_args
from dash.exceptions import NonExistentEventException
from ._all_keywords import python_keywords
from .base_component import Component

Expand All@@ -27,8 +28,7 @@ def generate_class_string(typename, props, description, namespace):
string

"""
# TODO _prop_names, _type, _namespace, available_events,
# and available_properties
# TODO _prop_names, _type, _namespace, and available_properties
# can be modified by a Dash JS developer via setattr
# TODO - Tab out the repr for the repr of these components to make it
# look more like a hierarchical tree
Expand All@@ -52,7 +52,6 @@ def __init__(self, {default_argtext}):
self._namespace = '{namespace}'
self._valid_wildcard_attributes =\
{list_of_valid_wildcard_attr_prefixes}
self.available_events = {events}
self.available_properties = {list_of_valid_keys}
self.available_wildcard_properties =\
{list_of_valid_wildcard_attr_prefixes}
Expand DownExpand Up@@ -101,11 +100,11 @@ def __repr__(self):
docstring = create_docstring(
component_name=typename,
props=filtered_props,
events=parse_events(props),
description=description).replace('\r\n', '\n')

prohibit_events(props)

# pylint: disable=unused-variable
events = '[' + ', '.join(parse_events(props)) + ']'
prop_keys = list(props.keys())
if 'children' in props:
prop_keys.remove('children')
Expand All@@ -122,7 +121,7 @@ def __repr__(self):
for p in prop_keys
if not p.endswith("-*") and
p not in python_keywords and
p not in ['dashEvents', 'fireEvent', 'setProps']] + ['**kwargs']
p != 'setProps'] + ['**kwargs']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that was intentional but still present for the R generation

@rpkylerpkyleJan 21, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have modified my code to match.

)

required_args = required_props(props)
Expand DownExpand Up@@ -233,7 +232,7 @@ def required_props(props):
if prop['required']]


def create_docstring(component_name, props, events, description):
def create_docstring(component_name, props, description):
"""
Create the Dash component docstring

Expand All@@ -243,8 +242,6 @@ def create_docstring(component_name, props, events, description):
Component name
props: dict
Dictionary with {propName: propMetadata} structure
events: list
List of Dash events
description: str
Component description

Expand All@@ -259,9 +256,7 @@ def create_docstring(component_name, props, events, description):
return (
"""A {name} component.\n{description}

Keyword arguments:\n{args}

Available events: {events}"""
Keyword arguments:\n{args}"""
).format(
name=component_name,
description=description,
Expand All@@ -274,30 +269,26 @@ def create_docstring(component_name, props, events, description):
description=prop['description'],
indent_num=0,
is_flow_type='flowType' in prop and 'type' not in prop)
for p, prop in list(filter_props(props).items())),
events=', '.join(events))
for p, prop in list(filter_props(props).items())))


def parse_events(props):
def prohibit_events(props):
"""
Pull out the dashEvents from the Component props
Events have been removed. Raise an error if we see dashEvents or fireEvents

Parameters
----------
props: dict
Dictionary with {propName: propMetadata} structure

Returns
Raises
-------
list
List of Dash event strings
?
"""
if 'dashEvents' in props and props['dashEvents']['type']['name'] == 'enum':
events = [v['value'] for v in props['dashEvents']['type']['value']]
else:
events = []

return events
if 'dashEvents' in props or 'fireEvents' in props:
raise NonExistentEventException(
'Events are no longer supported by dash. Use properties instead, '
'eg `n_clicks` instead of a `click` event.')


def parse_wildcards(props):
Expand DownExpand Up@@ -349,7 +340,6 @@ def filter_props(props):
Filter props from the Component arguments to exclude:
- Those without a "type" or a "flowType" field
- Those with arg.type.name in {'func', 'symbol', 'instanceOf'}
- dashEvents as a name

Parameters
----------
Expand DownExpand Up@@ -415,10 +405,6 @@ def filter_props(props):
else:
raise ValueError

# dashEvents are a special oneOf property that is used for subscribing
# to events but it's never set as a property
if arg_name in ['dashEvents']:
filtered_props.pop(arg_name)
return filtered_props


Expand DownExpand Up@@ -518,7 +504,7 @@ def map_js_to_py_types_prop_types(type_object):
', '.join(
"'{}'".format(t)
for t in list(type_object['value'].keys())),
'Those keys have the following types:\n{}'.format(
'Those keys have the following types:\n{}'.format(
'\n'.join(create_prop_docstring(
prop_name=prop_name,
type_object=prop,
Expand DownExpand Up@@ -561,7 +547,7 @@ def map_js_to_py_types_flow_types(type_object):
signature=lambda indent_num: 'dict containing keys {}.\n{}'.format(
', '.join("'{}'".format(d['key'])
for d in type_object['signature']['properties']),
'{}Those keys have the following types:\n{}'.format(
'{}Those keys have the following types:\n{}'.format(
' ' * indent_num,
'\n'.join(
create_prop_docstring(
Expand Down
2 changes: 1 addition & 1 deletion dash/exceptions.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@ class IncorrectTypeException(CallbackException):
pass


class MissingEventsException(CallbackException):
class MissingInputsException(CallbackException):
pass


Expand Down
2 changes: 1 addition & 1 deletion dash/extract-meta.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ const componentPaths = process.argv.slice(3);
const ignorePattern = new RegExp(process.argv[2]);

const excludedDocProps = [
'setProps', 'id', 'className', 'style', 'dashEvents', 'fireEvent'
'setProps', 'id', 'className', 'style'
];

if (!componentPaths.length) {
Expand Down
20 changes: 20 additions & 0 deletions test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
EXIT_STATE=0

python -m unittest tests.development.test_base_component || EXIT_STATE=$?
python -m unittest tests.development.test_component_loader || EXIT_STATE=$?
python -m unittest tests.test_integration || EXIT_STATE=$?
python -m unittest tests.test_resources || EXIT_STATE=$?
python -m unittest tests.test_configs || EXIT_STATE=$?

pylint dash setup.py --rcfile=$PYLINTRC || EXIT_STATE=$?
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109 || EXIT_STATE=$?
flake8 dash setup.py || EXIT_STATE=$?
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests || EXIT_STATE=$?

if [ $EXIT_STATE -ne 0 ]; then
Comment thread
alexcjohnson marked this conversation as resolved.
echo "One or more tests failed"
else
echo "All tests passed!"
fi

exit $EXIT_STATE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include the linting also ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'll move linting in here too.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting into test.sh -> 2c9a3c8

10 changes: 0 additions & 10 deletions tests/development/TestReactComponent.react.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,19 +91,9 @@ ReactComponent.propTypes = {
}
}),

// special dash events

children: React.PropTypes.node,

id: React.PropTypes.string,


// dashEvents is a special prop that is used to events validation
dashEvents: React.PropTypes.oneOf([
'restyle',
'relayout',
'click'
])
};

ReactComponent.defaultProps = {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,25 +35,12 @@ jobs:
paths:
- "venv"

- run:
name: Run lint
command: |
. venv/bin/activate
pylint dash setup.py --rcfile=$PYLINTRC
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109
flake8 dash setup.py
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest tests.development.test_base_component
python -m unittest tests.development.test_component_loader
python -m unittest tests.test_integration
python -m unittest tests.test_resources
python -m unittest tests.test_configs
./test.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


"python-3.6":
<<: *test-template
Expand All@@ -80,4 +67,4 @@ workflows:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
- "python-3.7"
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements-py37.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components==0.12.0rc3
dash-flow-example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
2 changes: 1 addition & 1 deletion .circleci/requirements/dev-requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ dash_core_components>=0.40.2
dash_html_components>=0.12.0rc3
dash_flow_example==0.0.3
dash-dangerously-set-inner-html
dash_renderer
git+git://github.com/plotly/dash-renderer@master#egg=dash_renderer
percy
selenium
mock
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
## Unreleased
## Removed
- Removed support for `Event` system. Use event properties instead, for example the `n_clicks` property instead of the `click` event, see [#531](https://github.com/plotly/dash/issues/531) for details. `dash_renderer` MUST be upgraded to >=0.17.0 together with this, and it is recommended to update `dash_core_components` to >=0.43.0 and `dash_html_components` to >=0.14.0. [#550](https://github.com/plotly/dash/pull/550)

## [0.35.3] - 2019-01-23
## Fixed
- Asset blueprint takes routes prefix into it's static path. [#547](https://github.com/plotly/dash/pull/547)
Expand Down
51 changes: 17 additions & 34 deletions dash/dash.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,13 +15,14 @@

from functools import wraps

import plotly
import dash_renderer
import flask
from flask import Flask, Response
from flask_compress import Compress

from .dependencies import Event, Input, Output, State
import plotly
import dash_renderer

from .dependencies import Input, Output, State
from .resources import Scripts, Css
from .development.base_component import Component
from . import exceptions
Expand DownExpand Up@@ -622,7 +623,6 @@ def dependencies(self):
},
'inputs': v['inputs'],
'state': v['state'],
'events': v['events']
} for k, v in self.callback_map.items()
])

Expand All@@ -633,7 +633,7 @@ def react(self, *args, **kwargs):
'Use `callback` instead. `callback` has a new syntax too, '
'so make sure to call `help(app.callback)` to learn more.')

def _validate_callback(self, output, inputs, state, events):
def _validate_callback(self, output, inputs, state):
# pylint: disable=too-many-branches
layout = self._cached_layout or self._layout_value()

Expand All@@ -652,8 +652,7 @@ def _validate_callback(self, output, inputs, state, events):

for args, obj, name in [([output], Output, 'Output'),
(inputs, Input, 'Input'),
(state, State, 'State'),
(events, Event, 'Event')]:
(state, State, 'State')]:

if not isinstance(args, list):
raise exceptions.IncorrectTypeException(
Expand DownExpand Up@@ -721,32 +720,20 @@ def _validate_callback(self, output, inputs, state, events):
component.available_properties).replace(
' ', ''))

if (hasattr(arg, 'component_event') and
arg.component_event not in
component.available_events):
if hasattr(arg, 'component_event'):
raise exceptions.NonExistentEventException('''
Attempting to assign a callback with
the event "{}" but the component
"{}" doesn't have "{}" as an event.\n
Here is a list of the available events in "{}":
{}
'''.format(
arg.component_event,
arg.component_id,
arg.component_event,
arg.component_id,
component.available_events).replace(' ', ''))
Events have been removed.
Use the associated property instead.
''')

if state and not events and not inputs:
raise exceptions.MissingEventsException('''
if state and not inputs:
raise exceptions.MissingInputsException('''
This callback has {} `State` {}
but no `Input` elements or `Event` elements.\n
Without `Input` or `Event` elements, this callback
but no `Input` elements.\n
Without `Input` elements, this callback
will never get called.\n
(Subscribing to input components will cause the
callback to be called whenever their values
change and subscribing to an event will cause the
callback to be called whenever the event is fired.)
callback to be called whenever their values change.)
'''.format(
len(state),
'elements' if len(state) > 1 else 'element'
Expand DownExpand Up@@ -888,8 +875,8 @@ def _validate_value(val, index=None):
# TODO - Check this map for recursive or other ill-defined non-tree
# relationships
# pylint: disable=dangerous-default-value
def callback(self, output, inputs=[], state=[], events=[]):
self._validate_callback(output, inputs, state, events)
def callback(self, output, inputs=[], state=[]):
self._validate_callback(output, inputs, state)

callback_id = '{}.{}'.format(
output.component_id, output.component_property
Expand All@@ -902,10 +889,6 @@ def callback(self, output, inputs=[], state=[], events=[]):
'state': [
{'id': c.component_id, 'property': c.component_property}
for c in state
],
'events': [
{'id': c.component_id, 'event': c.component_event}
for c in events
]
}

Expand Down
7 changes: 0 additions & 7 deletions dash/dependencies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,10 +17,3 @@ class State:
def __init__(self, component_id, component_property):
self.component_id = component_id
self.component_property = component_property


# pylint: disable=old-style-class, too-few-public-methods
class Event:
def __init__(self, component_id, component_event):
self.component_id = component_id
self.component_event = component_event
50 changes: 18 additions & 32 deletions dash/development/_py_components_generation.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@
import os

from dash.development.base_component import _explicitize_args
from dash.exceptions import NonExistentEventException
from ._all_keywords import python_keywords
from .base_component import Component

Expand All@@ -27,8 +28,7 @@ def generate_class_string(typename, props, description, namespace):
string

"""
# TODO _prop_names, _type, _namespace, available_events,
# and available_properties
# TODO _prop_names, _type, _namespace, and available_properties
# can be modified by a Dash JS developer via setattr
# TODO - Tab out the repr for the repr of these components to make it
# look more like a hierarchical tree
Expand All@@ -52,7 +52,6 @@ def __init__(self, {default_argtext}):
self._namespace = '{namespace}'
self._valid_wildcard_attributes =\
{list_of_valid_wildcard_attr_prefixes}
self.available_events = {events}
self.available_properties = {list_of_valid_keys}
self.available_wildcard_properties =\
{list_of_valid_wildcard_attr_prefixes}
Expand DownExpand Up@@ -101,11 +100,11 @@ def __repr__(self):
docstring = create_docstring(
component_name=typename,
props=filtered_props,
events=parse_events(props),
description=description).replace('\r\n', '\n')

prohibit_events(props)

# pylint: disable=unused-variable
events = '[' + ', '.join(parse_events(props)) + ']'
prop_keys = list(props.keys())
if 'children' in props:
prop_keys.remove('children')
Expand All@@ -122,7 +121,7 @@ def __repr__(self):
for p in prop_keys
if not p.endswith("-*") and
p not in python_keywords and
p not in ['dashEvents', 'fireEvent', 'setProps']] + ['**kwargs']
p != 'setProps'] + ['**kwargs']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that was intentional but still present for the R generation

@rpkylerpkyleJan 21, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have modified my code to match.

)

required_args = required_props(props)
Expand DownExpand Up@@ -233,7 +232,7 @@ def required_props(props):
if prop['required']]


def create_docstring(component_name, props, events, description):
def create_docstring(component_name, props, description):
"""
Create the Dash component docstring

Expand All@@ -243,8 +242,6 @@ def create_docstring(component_name, props, events, description):
Component name
props: dict
Dictionary with {propName: propMetadata} structure
events: list
List of Dash events
description: str
Component description

Expand All@@ -259,9 +256,7 @@ def create_docstring(component_name, props, events, description):
return (
"""A {name} component.\n{description}

Keyword arguments:\n{args}

Available events: {events}"""
Keyword arguments:\n{args}"""
).format(
name=component_name,
description=description,
Expand All@@ -274,30 +269,26 @@ def create_docstring(component_name, props, events, description):
description=prop['description'],
indent_num=0,
is_flow_type='flowType' in prop and 'type' not in prop)
for p, prop in list(filter_props(props).items())),
events=', '.join(events))
for p, prop in list(filter_props(props).items())))


def parse_events(props):
def prohibit_events(props):
"""
Pull out the dashEvents from the Component props
Events have been removed. Raise an error if we see dashEvents or fireEvents

Parameters
----------
props: dict
Dictionary with {propName: propMetadata} structure

Returns
Raises
-------
list
List of Dash event strings
?
"""
if 'dashEvents' in props and props['dashEvents']['type']['name'] == 'enum':
events = [v['value'] for v in props['dashEvents']['type']['value']]
else:
events = []

return events
if 'dashEvents' in props or 'fireEvents' in props:
raise NonExistentEventException(
'Events are no longer supported by dash. Use properties instead, '
'eg `n_clicks` instead of a `click` event.')


def parse_wildcards(props):
Expand DownExpand Up@@ -349,7 +340,6 @@ def filter_props(props):
Filter props from the Component arguments to exclude:
- Those without a "type" or a "flowType" field
- Those with arg.type.name in {'func', 'symbol', 'instanceOf'}
- dashEvents as a name

Parameters
----------
Expand DownExpand Up@@ -415,10 +405,6 @@ def filter_props(props):
else:
raise ValueError

# dashEvents are a special oneOf property that is used for subscribing
# to events but it's never set as a property
if arg_name in ['dashEvents']:
filtered_props.pop(arg_name)
return filtered_props


Expand DownExpand Up@@ -518,7 +504,7 @@ def map_js_to_py_types_prop_types(type_object):
', '.join(
"'{}'".format(t)
for t in list(type_object['value'].keys())),
'Those keys have the following types:\n{}'.format(
'Those keys have the following types:\n{}'.format(
'\n'.join(create_prop_docstring(
prop_name=prop_name,
type_object=prop,
Expand DownExpand Up@@ -561,7 +547,7 @@ def map_js_to_py_types_flow_types(type_object):
signature=lambda indent_num: 'dict containing keys {}.\n{}'.format(
', '.join("'{}'".format(d['key'])
for d in type_object['signature']['properties']),
'{}Those keys have the following types:\n{}'.format(
'{}Those keys have the following types:\n{}'.format(
' ' * indent_num,
'\n'.join(
create_prop_docstring(
Expand Down
2 changes: 1 addition & 1 deletion dash/exceptions.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@ class IncorrectTypeException(CallbackException):
pass


class MissingEventsException(CallbackException):
class MissingInputsException(CallbackException):
pass


Expand Down
2 changes: 1 addition & 1 deletion dash/extract-meta.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ const componentPaths = process.argv.slice(3);
const ignorePattern = new RegExp(process.argv[2]);

const excludedDocProps = [
'setProps', 'id', 'className', 'style', 'dashEvents', 'fireEvent'
'setProps', 'id', 'className', 'style'
];

if (!componentPaths.length) {
Expand Down
20 changes: 20 additions & 0 deletions test.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
EXIT_STATE=0

python -m unittest tests.development.test_base_component || EXIT_STATE=$?
python -m unittest tests.development.test_component_loader || EXIT_STATE=$?
python -m unittest tests.test_integration || EXIT_STATE=$?
python -m unittest tests.test_resources || EXIT_STATE=$?
python -m unittest tests.test_configs || EXIT_STATE=$?

pylint dash setup.py --rcfile=$PYLINTRC || EXIT_STATE=$?
pylint tests -d all -e C0410,C0411,C0412,C0413,W0109 || EXIT_STATE=$?
flake8 dash setup.py || EXIT_STATE=$?
flake8 --ignore=E123,E126,E501,E722,E731,F401,F841,W503,W504 --exclude=metadata_test.py tests || EXIT_STATE=$?

if [ $EXIT_STATE -ne 0 ]; then
Comment thread
alexcjohnson marked this conversation as resolved.
echo "One or more tests failed"
else
echo "All tests passed!"
fi

exit $EXIT_STATE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include the linting also ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'll move linting in here too.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting into test.sh -> 2c9a3c8

10 changes: 0 additions & 10 deletions tests/development/TestReactComponent.react.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,19 +91,9 @@ ReactComponent.propTypes = {
}
}),

// special dash events

children: React.PropTypes.node,

id: React.PropTypes.string,


// dashEvents is a special prop that is used to events validation
dashEvents: React.PropTypes.oneOf([
'restyle',
'relayout',
'click'
])
};

ReactComponent.defaultProps = {
Expand Down
Loading