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
3 changes: 3 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

**Checklist**
- [ ] Add a news fragment if this PR is news-worthy for end users. (see docs/releases/README.rst)
149 changes: 148 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,153 @@
Traits UI Changelog
===================

Release 7.2.0
-------------
TraitsUI 7.2.0 is a minor release which includes numerous bug fixes,
documentation improvements, code maintenance changes, and enhancements.

Highlights of this release
~~~~~~~~~~~~~~~~~~~~~~~~~~

* The migration from ``on_trait_change`` to ``observe`` is underway. As a
result, TraitsUI now requires Traits >= 6.1.
* New display-only VideoEditor (currently only on Qt backend).
* Exapnsion of features for the new ``UITester`` including the ability to
inspect UI object visibility / enabledness. Also documentation for testing
has been updated.

Notes on upgrading
~~~~~~~~~~~~~~~~~~

* This release of TraitsUI now depends on Traits 6.1+. Also, deprecated code /
modules have been removed. Namely, the :mod:`traitsui.image <traitsui.image>`
module which was moved to ``pyface.image``, ``editors_gen`` modules, Editor
and EditorFactory factory methods on Toolkit objects, and more. For a
complete list, see PRs in the "Removals" section below. These were all
generally unused / deprecated for sometime. Also, importing directly from
``traitsui.editors`` has been deprecated. Please update imports to import
directly from :mod:`traitsui.api` or :mod:`traitsui.editors.api`.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Which should we be recommending here? I listed both currently, but I imagine we just want people to import from traitsui.api?
This has been discussed before

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.

This has been discussed before

I dont remember that discussion - or the conclusion of that discussion.
I'm fine with listing both. I completely forgot about the fact that the editor factories are also importable via traitsui.api. I think we can leave it up to the users to choose. I don't think we'll remove traitsui.editors.api.


Detailed changes
~~~~~~~~~~~~~~~~

Thanks to:

* Aaron Ayres
* Kit Yan Choi
* Mark Dickinson
* Rahul Poruri
* Corran Webster

Enhancements
~~~~~~~~~~~~

* Open links externally instead of in the html editor in etsdemo application (#1446)
* Hide demo tab when the demo is None (#1456)
* Extract an interface from TargetRegistry to allow wider testing support for IsEnabled (#1490)
* Expose clearButtonEnabled for Qt TextEditor (#1516)
* Extend / document secret TreeNode api for passing tuples into add list trait (#1527)
* Add 'IsVisible` query class for UI Tester (#1552)
* Extend button editor to allow dynamically changing button image (#1566)
* Support testing with simple FileEditor (without dialog) (#1571)
* Qt VideoEditor (#745, #1609, #1621)
* Add item_factory callable for specifying creation of new list items (#1634)

Fixes
~~~~~

* Support HTMLEditor.open_externally on QtWebEngine (#1451)
* Qt InstanceEditor button should never be the default (#1498)
* Propagate UI errors to the UI's parent (#1503)
* Fix resizable readonly enum editor (#1532)
* StartStyling API changed for new Wx version (#1536)
* Don't use html for a variable name when using html module from standard library (#1540)
* Label {visible/enabled}_when (#1544)
* manually set the text format to plain text in error (#1546)
* Fix RGBColor hex int to tuple color conversion (#1554)
* Make Scrollable group respect visible_when (#1555)
* Use correct source_path in example (#1433)
* Move EnumEditor import in table_filter into the methods that need it (#1616)

Documentation
~~~~~~~~~~~~~

* Add a module docstring to the api modules (#1441)
* Use viewcode sphinx extension (#1443)
* Add links to API docs in a etsdemo examples for traitsui standard editors (#1445)
* Clarify which of traitsui.api and traitsui.editors.api is recommended (#1471)
* traitsui.testing documentation updates (#1482, #1483, #1485, #1486, #1487, #1488)
* Fix link label to the documentation home page (#1489)
* Document enabled_when / visible_when better (#1537)
* Document entries parameter not supported qt for FileEditor/DirectoryEditor (#1557
* Add script to regenerate screenshots of editors for documentation (#1574)
* Remove unused images in docs (#1584)
* replace # with #: to document traits in traitsui.editors.* (#1596)
* User facing docs for VideoEditor (#1630)
* Format code examples in the user documentation (#1640)

Build and continuous integration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* Fix cron job not installing additional dependencies (#1427)
* Remove job on Travis for testing against Traits 6.0 (#1430)
* Drop Python 3.5 support in TraitsUI (#1436)
* Declare Python 3.5 not supported for ets-demo (#1437)
* Fix link for installing wxPython on CI (for etsdemo) (#1491)
* Add GitHub Actions to test against EDM (#1492)
* Add GitHub Actions workflow for testing ets-demo (#1496)
* Use EDM 3.2.3 instead of EDM 3.2.1 (#1548)
* Drop support for PyQt < 4.3.2 (#1607)
* Remove CI test against Traits 6.0 (#1637)

Test suite
~~~~~~~~~~

* Refactor and extend tests for Qt HTMLEditor handling of opening links (#1465)
* Update new test_editor_error_msg (#1553)
* Unskip "EnumEditor" tests that were failing earlier on windows (#1615)
* skip video editor test without numpy / move numpy import to when it is needed
/ list numpy as test dependency (#1639)
* skip test if no QtWebkit or QtWebEngine (#1649)

Maintenance and code organization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* Add pygments to etsdemo's etstool.py (#1453)
* Add help aliases to etsdemo etstool module (#1457)
* Fix/Update copyright headers (#1467, #1486)
* work towards flake8 clean codebase (#1469, #1562, #1563)
* Remove meaningless comments from an outdated coding style. (#1472)
* Remove clause that deviates from PEP8 backward compatibility convention in the testing package (#1481)
* Formal editor interface for tooltips (#1493
* Add instance choice classes to traitsui.api (#1495)
* Undo/Redo cleanup (#1510
* start on_trait_change to observe migration (#1519, #1520, #1523, #1525, #1545, #1622, #1644)
* Refactor TreeEditor _new_actions and _menu_new_node to avoid hacky eval (#1524)
* Refactor _add_items method of _GroupPanel object (#1549)
* Add new trait to eventually replace scroll_to_row_hint (#1560)
* Add 'default': True to the etsdemo eam metadata (#1568)
* update "super" usage (#1583, #1587, #1588, #1589, #1604)
* Use "str.capitalize" directly instead of an alias (#1598)
* Use "PrefixList" from traits >= 6.1 (#1599)
* Update use of deprecated "Thread.setDaemon" (#1601)
* Replace deprecated "wx.ListItemAttr" with "wx.ItemAttr" (#1602)
* Adds "traitsui.toolkit.toolkit_object" to "traitsui.api" (#1603)
* Import "TraitFactory" from "traits.api" (#1606)
* Rename editor factory classes (#1610)
* Cleanup imports in "traitsui.editors.*" (#1619)

Removals
~~~~~~~~

* Remove deprecated classes/modules (#1594)
* remove traitsui.image submodule (#1595)
* Remove Editor and EditorFactory factory methods on Toolkit objects (#1600)
* Remove backwards compatibility toolkit factory imports (#1608)
* Remove unused "Item.full_size" trait (#1613)
* Remove code handling old/outdated versions of wx (#1614)
* Remove unused editors_gen modules (#1626)

Release 7.1.1
-------------

Expand All @@ -18,7 +165,7 @@ Fixes
Release 7.1.0
-------------

TraitsUI is a minor feature release which introduces a new testing library
TraitsUI 7.1.0 is a minor feature release which introduces a new testing library
and a number of significant fixes. Demo examples are also distributed as
package data such that they are visible via the "etsdemo" GUI application (to
be installed separately).
Expand Down
29 changes: 29 additions & 0 deletions docs/releases/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
The `upcoming` directory contains news fragments that will be added to the
changelog for the NEXT release.

Changes that are not of interest to the end-user can skip adding news fragment.

Add a news fragment
-------------------
Create a new file with a name like ``<pull-request>.<type>.rst``, where
``<pull-request>`` is a pull request number, and ``<type>`` is one of:

- ``feature``: New feature
- ``bugfix``: Bug fixes
- ``deprecation``: Deprecations of public API
- ``removal``: Removal of public API
- ``doc``: Documentation changes
- ``test``: Changes to test suite ('end users' are distribution packagers)
- ``build``: Build system changes that affect how the distribution is installed

Then write a short sentence in the file that describes the changes for the
end users, e.g. in ``123.removal.rst``::

Remove package xyz.

Alternatively, use the following command, run from the project root directory
and answer the questions::

python etstool.py changelog create

(This command requires ``click`` in the environment.)
122 changes: 122 additions & 0 deletions etstool.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@
commands for each task. See the EDM documentation for more information about
how to run commands within an EDM enviornment.

Build changelog
---------------
To create a first-cut changelog from the news fragments, use this command::

python etstool.py changelog build

This will update the changelog file. You should review and edit it.
"""

import glob
Expand Down Expand Up @@ -186,6 +193,15 @@
'null': {'ETS_TOOLKIT': 'null'},
}

# Location of documentation files
HERE = os.path.dirname(__file__)
DOCS_DIR = os.path.join(HERE, "docs")

# Location of news fragment for creating changelog.
NEWS_FRAGMENT_DIR = os.path.join(DOCS_DIR, "releases", "upcoming")

# Location of the Changelog file.
CHANGELOG_PATH = os.path.join(HERE, "CHANGES.txt")

def normalize(name):
return name.replace("_", "-")
Expand Down Expand Up @@ -477,6 +493,112 @@ def flake8(runtime, toolkit, environment):
execute(commands, parameters)


@cli.group("changelog")
@click.pass_context
def changelog(ctx):
""" Group of commands related to creating changelog."""

ctx.obj = {
# Mapping from news fragment type to their description in
# the changelog.
"type_to_description": {
"feature": "Features",
"bugfix": "Fixes",
"deprecation": "Deprecations",
"removal": "Removals",
"doc": "Documentation changes",
"test": "Test suite",
"build": "Build System",
}
}


@changelog.command("create")
@click.pass_context
def create_news_fragment(ctx):
""" Create a news fragment for your PR."""

pr_number = click.prompt('Please enter the PR number', type=int)
type_ = click.prompt(
"Choose a fragment type:",
type=click.Choice(ctx.obj["type_to_description"])
)

filepath = os.path.join(
NEWS_FRAGMENT_DIR, f"{pr_number}.{type_}.rst"
)

if os.path.exists(filepath):
click.echo("FAILED: File {} already exists.".format(filepath))
ctx.exit(1)

content = click.prompt(
"Describe the changes to the END USERS.\n"
"Example: 'Remove subpackage xyz.'\n",
type=str,
)
if not os.path.exists(NEWS_FRAGMENT_DIR):
os.makedirs(NEWS_FRAGMENT_DIR)
with open(filepath, "w", encoding="utf-8") as fp:
fp.write(content + f" (#{pr_number})")

click.echo("Please commit the file created at: {}".format(filepath))


@changelog.command("build")
@click.pass_context
def build_changelog(ctx):
""" Build Changelog created from all the news fragments."""
# This is a rather simple first-cut generation of the changelog.
# It removes the laborious concatenation, but the end results might
# still require some tweaking.
contents = []

# Collect news fragment files as we go, and then optionally remove them.
handled_file_paths = []

for type_, description in ctx.obj["type_to_description"].items():
pattern = os.path.join(NEWS_FRAGMENT_DIR, f"*.{type_}.rst")
file_paths = sorted(glob.glob(pattern))

if file_paths:
contents.append("")
contents.append(description)
contents.append("-" * len(description))

for filename in file_paths:
with open(filename, "r", encoding="utf-8") as fp:
contents.append("* " + fp.read())
handled_file_paths.append(filename)

# Prepend content to the changelog file.

with open(CHANGELOG_PATH, "r", encoding="utf-8") as fp:
original_changelog = fp.read()

with open(CHANGELOG_PATH, "w", encoding="utf-8") as fp:
if contents:
print(*contents, sep="\n", file=fp)
fp.write(original_changelog)

click.echo(f"Changelog is updated. Please review it at {CHANGELOG_PATH}")

# Optionally clean up collected news fragments.
should_clean = click.confirm(
"Do you want to remove the news fragments?"
)
if should_clean:
for file_path in handled_file_paths:
os.remove(file_path)

# Report any leftover for developers to inspect.
leftovers = sorted(glob.glob(os.path.join(NEWS_FRAGMENT_DIR, "*")))
if leftovers:
click.echo("These files are not collected:")
click.echo("\n ".join([""] + leftovers))

click.echo("Done")

# ----------------------------------------------------------------------------
# Utility routines
# ----------------------------------------------------------------------------
Expand Down