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

Allow generate-spec to take optional output file #3174

Merged
merged 3 commits into from
Aug 10, 2021
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
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ jobs:
pip install file://$PWD#egg=ipywidgets
- name: Compare spec with latest version
run: |
python ./packages/schema/generate-spec.py -f markdown > spec.md
python ./packages/schema/generate-spec.py -f markdown spec.md
diff -u ./packages/schema/jupyterwidgetmodels.latest.md ./spec.md
ui-test:
name: Visual Regression
Expand Down
4 changes: 2 additions & 2 deletions docs/source/dev_install.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ Updating widget model specification
To update the widget model specification with changes, do something like this in the repo root:
```
python ./packages/schema/generate-spec.py -f json-pretty > packages/schema/jupyterwidgetmodels.latest.json
python ./packages/schema/generate-spec.py -f markdown > packages/schema/jupyterwidgetmodels.latest.md
python ./packages/schema/generate-spec.py -f json-pretty packages/schema/jupyterwidgetmodels.latest.json
python ./packages/schema/generate-spec.py -f markdown packages/schema/jupyterwidgetmodels.latest.md
```
Releasing new versions
Expand Down
4 changes: 2 additions & 2 deletions docs/source/dev_release.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ First, update the relevant model specification versions. For example, the commit

Next, regenerate the model spec with the new version numbers by doing something like this in the repository root directory:
```
python ./packages/schema/generate-spec.py -f json-pretty > packages/schema/jupyterwidgetmodels.latest.json
python ./packages/schema/generate-spec.py -f markdown > packages/schema/jupyterwidgetmodels.latest.md
python ./packages/schema/generate-spec.py -f json-pretty packages/schema/jupyterwidgetmodels.latest.json
python ./packages/schema/generate-spec.py -f markdown packages/schema/jupyterwidgetmodels.latest.md
```

Copy `packages/schema/jupyterwidgetmodels.latest.md` to an appropriately-named
Expand Down
6 changes: 6 additions & 0 deletions ipywidgets/widgets/widget_link.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ class WidgetTraitTuple(Tuple):

def __init__(self, **kwargs):
super().__init__(Instance(Widget), Unicode(), **kwargs)
if "default_value" not in kwargs and not kwargs.get("allow_none", False):
# This is to keep consistent behavior for spec generation between traitlets 4 and 5
# Having a default empty container is explicitly not allowed in traitlets 5 when
# there are traits specified (as the default value will be invalid), but we do it
# anyway as there is no empty "default" that makes sense.
self.default_args = ()

def validate_elements(self, obj, value):
value = super().validate_elements(obj, value)
Expand Down
41 changes: 28 additions & 13 deletions packages/schema/generate-spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import argparse
import json
from operator import itemgetter
import pathlib
import sys

from traitlets import (
CaselessStrEnum,
Expand Down Expand Up @@ -231,21 +233,34 @@ def create_markdown(spec):
parser = argparse.ArgumentParser(description='Description of your program')
parser.add_argument('-f', '--format', choices=['json', 'json-pretty', 'markdown'],
help='Format to generate', default='json')
parser.add_argument('output', nargs='?', type=pathlib.Path)
args = parser.parse_args()
format = args.format

widgets_to_document = sorted(widgets.Widget._widget_types.items())
spec = create_spec(widgets_to_document)
if format == 'json':
try:
print(json.dumps(spec, sort_keys=True))
except TypeError:
print('Encountered error when converting spec to JSON. Here is the spec:')
print(spec)
raise
elif format == 'json-pretty':
print(json.dumps(spec, sort_keys=True,
indent=2, separators=(',', ': ')))
elif format == 'markdown':
# We go through the json engine to convert tuples to lists, etc.
print(create_markdown(json.loads(json.dumps(spec))))

if args.output:
args.output.parent.mkdir(exist_ok=True)
output = open(args.output, mode='w', encoding='utf8')
else:
output = sys.stdout

try:
if format == 'json':
try:
json.dump(spec, output, sort_keys=True)
except TypeError:
print('Encountered error when converting spec to JSON. Here is the spec:')
print(spec)
raise
elif format == 'json-pretty':
json.dump(spec, output, sort_keys=True,
indent=2, separators=(',', ': '))
elif format == 'markdown':
# We go through the json engine to convert tuples to lists, etc.
output.write(create_markdown(json.loads(json.dumps(spec))))
output.write('\n')
finally:
if args.output:
output.close()