Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fixes to address unintended props reshuffling behaviour #545

Merged
merged 38 commits into from
Jan 29, 2019
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d208936
fixes to address default values, support for source maps
Jan 12, 2019
af56606
adjust R package dependencies
Jan 14, 2019
96c69c1
added file to .gitignore
Jan 14, 2019
c8573ad
corrected error in help
Jan 15, 2019
34837df
inserted whitespace as suggested by alexcjohnson
Jan 15, 2019
e53cca2
fixed deps naming issue for install_github
Jan 17, 2019
45a7dcd
added import for _get_metadata
Jan 18, 2019
9fe81f4
restored _get_metadata call for JSON imports
Jan 18, 2019
04d2b3f
fixed .Rbuildignore strings
Jan 18, 2019
f54fee1
fix for lone flake8 error
Jan 18, 2019
624c389
replaced second occurrence of json.loads() with _get_metadata
Jan 18, 2019
5498307
addressed flake8 errors
Jan 18, 2019
aa8c6dc
modifed metadata load path
Jan 18, 2019
74a4d5b
replaced missing parenthesis
Jan 18, 2019
bcb3d48
flake8 passes
Jan 18, 2019
5a4c5fb
attempting alternative approach for JSON>>OrderedDict
Jan 18, 2019
3eca5be
corrected inst/lib to inst/deps
Jan 18, 2019
be0646b
removed import of _get_metadata
Jan 18, 2019
85ada0c
pylint and flake8 passing
Jan 18, 2019
d5fdc19
removed spurious ref to metadata
Jan 18, 2019
c90d0e5
refactored prop_keys exclusion
Jan 18, 2019
4e4a57a
pylint fix for indentation
Jan 18, 2019
c20ced1
edits to fully address :hocho: events
Jan 21, 2019
b9552ab
updated .gitignore
Jan 21, 2019
8aa3f25
:left_right_arrow: added byteify fn to prevent str >> unicode
Jan 22, 2019
5e251f0
:two::three: attempt to preserve version compatibility
Jan 22, 2019
1aeb507
:bug: revised byteify to use items() vs iteritems in :three:
Jan 22, 2019
a334699
:hammer: rewrote code to only use byteify in :two:
Jan 22, 2019
01b6d9d
prop_keys as list to handle TypeError for odict_keys in :three:
Jan 22, 2019
2251b30
:rewind: do not set sort_keys
Jan 26, 2019
4ee280b
Merge branch 'master' into RPK2
rpkyle Jan 26, 2019
9108f1e
:hammer: wildcards only available when props contain -*
Jan 26, 2019
a97d523
Merge branch 'RPK2' of github.com:plotly/dash into RPK2
Jan 26, 2019
38d693e
updated R component generation to properly provide package help
Jan 29, 2019
3499cd8
:shirt: flake8 edits
Jan 29, 2019
a622ccb
:hammer: version information now sourced consistently
Jan 29, 2019
817bfb0
:shirt: pylint ws removal
Jan 29, 2019
c65084f
updated R package description to note two langs
Jan 29, 2019
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ dist
npm-debug*
/.tox
.idea
package-lock.json
Copy link
Collaborator

Choose a reason for hiding this comment

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

It shouldn't be necessary to ignore this, though there are occasional issues.

Copy link
Contributor Author

@rpkyle rpkyle Jan 21, 2019

Choose a reason for hiding this comment

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

K, this has been 🔪 ... as has the package-lock.json.

102 changes: 42 additions & 60 deletions dash/development/_r_components_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@
# Declaring longer string templates as globals to improve
# readability, make method logic clearer to anyone inspecting
# code below
r_component_string = '''{prefix}{name} <- function(..., {default_argtext}) {{
r_component_string = '''{prefix}{name} <- function({default_argtext}, ...) {{

wildcard_names = names(list(...))

component <- list(
props = list({default_paramtext}),
props = list({default_paramtext}, ...),
type = '{name}',
namespace = '{project_shortname}',
propNames = c({prop_names}),
propNames = c({prop_names}, wildcard_names),
package = '{package_name}'
)

component$props <- filter_null(component$props)
component <- append_wildcard_props(component, wildcards = {default_wildcards}, ...)

structure(component, class = c('dash_component', 'list'))

structure(component, class = c('dash_component', 'list'))
}}''' # noqa:E501

# the following strings represent all the elements in an object
Expand All @@ -38,14 +39,14 @@

frame_element_template = '''`{dep_name}` = structure(list(name = "{dep_name}",
version = "{project_ver}", src = list(href = NULL,
file = "lib/"), meta = NULL,
file = "deps/"), meta = NULL,
script = "{dep_rpp}",
stylesheet = NULL, head = NULL, attachment = NULL, package = "{rpkgname}",
all_files = FALSE), class = "html_dependency")'''

frame_body_template = '''`{project_shortname}` = structure(list(name = "{project_shortname}",
version = "{project_ver}", src = list(href = NULL,
file = "lib/"), meta = NULL,
file = "deps/"), meta = NULL,
script = "{dep_rpp}",
stylesheet = NULL, head = NULL, attachment = NULL, package = "{rpkgname}",
all_files = FALSE), class = "html_dependency")''' # noqa:E501
Expand All @@ -56,14 +57,19 @@

help_string = '''% Auto-generated: do not edit by hand
\\name{{{prefix}{name}}}

\\alias{{{prefix}{name}}}

\\title{{{name} component}}

\\description{{
{description}
}}

\\usage{{
{prefix}{name}(..., {default_argtext})
{prefix}{name}({default_argtext}, ...)
}}

\\arguments{{
{item_text}
}}
Expand All @@ -74,6 +80,7 @@
Version: {package_version}
Authors @R: as.person(c({package_author}))
Description: {package_description}
Depends: R (>= 3.5.0)
Suggests: testthat, roxygen2
License: {package_license}
URL: {package_url}
Expand All @@ -97,9 +104,9 @@
# demo folder has special meaning in R
# this should hopefully make it still
# allow for the possibility to make R demos
demo/*.js
demo/*.html
demo/*.css
demo/.*\.js
demo/.*\.html
demo/.*\.css

# ignore python files/folders
setup.py
Expand All @@ -116,42 +123,14 @@
'''


# This is an initial attempt at resolving type inconsistencies
# between R and JSON.
def props_to_r_type(current_prop):
object_type = current_prop['type']['name']
if 'defaultValue' in current_prop and object_type == 'string':
if "\"" in current_prop['defaultValue']['value']:
argument = current_prop['defaultValue']['value']
else:
argument = "{}".format(current_prop['defaultValue']['value'])
elif object_type == 'custom' and 'raw' in current_prop['type']:
argument = current_prop['defaultValue'].get('value', 'numeric()')
elif object_type == 'enum':
argument = current_prop.get('defaultValue', {}).get('value', 'NULL')
elif 'defaultValue' in current_prop and object_type == 'object':
argument = 'list()'
elif 'defaultValue' in current_prop and \
current_prop['defaultValue']['value'] == '[]':
argument = 'list()'
elif object_type == 'number':
argument = current_prop['defaultValue'].get('value', 'NULL')
elif object_type == 'bool':
argument = current_prop['defaultValue'].get('value')
if argument:
argument = 'TRUE'
else:
argument = 'logical()'
else:
argument = 'NULL'
return argument


# pylint: disable=R0914
def generate_class_string(name, props, project_shortname, prefix):
# Here we convert from snake case to camel case
package_name = snake_case_to_camel_case(project_shortname)

# Ensure props are ordered with children first
props = reorder_props(props=props)

prop_keys = props.keys()

default_paramtext = ''
Expand Down Expand Up @@ -180,15 +159,13 @@ def generate_class_string(name, props, project_shortname, prefix):
default_wildcards = 'c({})'.format(default_wildcards)

# Filter props to remove those we don't want to expose
for p in prop_keys:
if p.endswith("-*") \
or p in r_keywords \
or p in ['setProps', 'dashEvents', 'fireEvent']:
prop_keys.remove(p)
for item in prop_keys[:]:
if item.endswith('-*') \
or item in r_keywords \
or item in ['setProps']:
prop_keys.remove(item)

default_argtext += ", ".join(
'{}={}'.format(p, props_to_r_type(props[p]))
if 'defaultValue' in props[p] else
'{}=NULL'.format(p)
for p in prop_keys
)
Expand All @@ -197,18 +174,18 @@ def generate_class_string(name, props, project_shortname, prefix):
default_paramtext += ", ".join(
'{}={}'.format(p, p)
if p != "children" else
'{}=c(children, assert_valid_children(..., wildcards = {}))'
.format(p, default_wildcards)
'{}=children'
.format(p)
for p in prop_keys
)

return r_component_string.format(prefix=prefix,
name=name,
default_argtext=default_argtext,
default_paramtext=default_paramtext,
project_shortname=project_shortname,
prop_names=prop_names,
package_name=package_name,
default_wildcards=default_wildcards)
package_name=package_name)


# pylint: disable=R0914
Expand Down Expand Up @@ -309,8 +286,6 @@ def write_help_file(name, props, description, prefix):
prop_keys.remove(p)

default_argtext += ", ".join(
'{}={}'.format(p, props_to_r_type(props[p]))
if 'defaultValue' in props[p] else
'{}=NULL'.format(p)
for p in prop_keys
)
Expand All @@ -320,6 +295,8 @@ def write_help_file(name, props, description, prefix):
for p in prop_keys
)

item_text += '\n\n\\item{...}{wildcards of the form: `data-*` or `aria-*`}'

file_path = os.path.join('man', file_name)
with open(file_path, 'w') as f:
f.write(help_string.format(
Expand All @@ -336,6 +313,8 @@ def write_class_file(name,
description,
project_shortname,
prefix=None):
props = reorder_props(props=props)

import_string =\
"# AUTO GENERATED FILE - DO NOT EDIT\n\n"
class_string = generate_class_string(
Expand Down Expand Up @@ -397,14 +376,17 @@ def write_js_metadata(project_shortname):
# now copy over all JS dependencies from the (Python) components dir
# the inst/lib directory for the package won't exist on first call
# create this directory if it is missing
if not os.path.exists('inst/lib'):
os.makedirs('inst/lib')
if not os.path.exists('inst/deps'):
os.makedirs('inst/deps')

for javascript in glob.glob('{}/*.js'.format(project_shortname)):
shutil.copy(javascript, 'inst/lib/')
shutil.copy(javascript, 'inst/deps/')

for css in glob.glob('{}/*.css'.format(project_shortname)):
shutil.copy(css, 'inst/lib/')
shutil.copy(css, 'inst/deps/')

for sourcemap in glob.glob('{}/*.map'.format(project_shortname)):
shutil.copy(sourcemap, 'inst/deps/')


# pylint: disable=R0914
Expand Down
7 changes: 4 additions & 3 deletions dash/development/component_generator.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from __future__ import print_function
from collections import OrderedDict

import json
import sys
Expand Down Expand Up @@ -64,7 +65,7 @@ def generate_components(components_source, project_shortname,
file=sys.stderr)
sys.exit(1)

metadata = json.loads(out.decode())
metadata = json.loads(out.decode(), object_pairs_hook=OrderedDict)
generator_methods = [generate_class_file]

if rprefix:
Expand All @@ -82,13 +83,13 @@ def generate_components(components_source, project_shortname,
)

with open(os.path.join(project_shortname, 'metadata.json'), 'w') as f:
json.dump(metadata, f)
json.dump(metadata, f, sort_keys=True)
Copy link
Contributor

Choose a reason for hiding this comment

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

⏪ Sorting the key reorder the keys, the ordered dict will keep the right order alone.


generate_imports(project_shortname, components)

if rprefix:
with open('package.json', 'r') as f:
pkg_data = json.load(f)
pkg_data = json.load(f, object_pairs_hook=OrderedDict)

generate_exports(
project_shortname, components, metadata, pkg_data, prefix
Expand Down