pythondialog News
This page describes the main changes since pythondialog 2.12 in a form suitable for human consumption. For the full details, or for changes in older versions, you may refer to the Git repository (you can click on “History”, or clone the repository and use git log). Alternatively, you should be able to find a ChangeLog file in any release tarball.
Python 2 backport not supported anymore
As you should know, Python 2 reached its end of life on January 1, 2020. There used to be a backport of pythondialog for Python 2, but it is now unsupported. No updates or fixes will be provided for it anymore. For people still using Python 2, it is high time to switch to Python 3 (Python 3.0 was released in 2008...).
Main changes in version 3.5.3
The only change in version 3.5.3 is:
-
Switch to the new https-based URL: the pythondialog home page is now https://pythondialog.sourceforge.io/. The previous URL, which didn't use HTTPS, still works and automatically redirects to the new one.
Main changes in version 3.5.2
The main changes in version 3.5.2 are:
-
Improved support for the
--timeoutdialog option. -
Show use of
d.add_persistent_args(["--no-nl-expand"])in examples. This should probably always be used in your code; the only reason why it is not enabled by default in pythondialog is to avoid breaking compatibility.
Main changes in version 3.5.1
The main changes in version 3.5.1 are:
-
The default used when the PATH environment variable is unset is now
"/bin:/usr/bin"instead of":/bin:/usr/bin". This is relevant when thedialogargument of theDialogconstructor contains no slash (/), which is the case by default. The benefit of this change is that in such a situation (PATH unset anddialogargument containing no slash), the dialog-like program will not be searched in the current directory anymore (unless of course the current directory is /bin or /usr/bin). This is a much safer behavior; fortunately, the risky behavior only ever existed on bogus setups where the PATH environment variable is unset.Note that in this respect, we have been following what the GNU C Library (glibc) does for its
execvp()function—the corresponding change in glibc happened in version 2.24, released in 2016. -
When a
Dialoginstance is created, it now immediately stores the result of callingos.path.realpath()on the specified executable (which is searched using the PATH if thedialogargument passed to the constructor contains no slash—cf. documentation of theDialogconstructor). This way, a pythondialog-based program can change its current directory after creating aDialoginstance without fearing that this might cause subsequentDialogmethod calls to fail or to invoke an executable from a different directory (additionally,os.path.realpath()resolves symbolic links). -
The Python 2 backport of pythondialog has been released for this version and should be on par with pythondialog 3.5.1 (this is why version 3.5.0 of the backport has been skipped). The packaging of the backport has been switched from distutils to setuptools too, just as was done in pythondialog 3.5.0 (see below). As a consequence, it is now available in wheel format. However, as said above, Python 2 is deprecated and the Python 2 backport of pythondialog is not supported anymore. Don't expect any further updates to it.
Main changes in version 3.5.0
The main change in version 3.5.0 is:
-
pythondialog's packaging has been switched from distutils to setuptools (this is the modern way, see the Python Packaging User Guide). Thanks to this change, pythondialog is now available in wheel format. The normal installation method using pip didn't change (see the INSTALL file for details).
The Python 2 backport of pythondialog has not been released for this version (version 3.5.1 will be the last one).
Main changes in version 3.4.0
The main changes in version 3.4.0 are:
-
The Python 2 backport has been updated to this version.
-
Add method
Dialog.editbox_str(). This is a convenience wrapper aroundDialog.editbox()that automatically creates and deletes a temporary file containing the initial box contents, which is passed as a string (Dialog.editbox()needs it in a file). -
Add the
week_startcommon option, mapped to dialog's--week-startoption (it is useful with the widget). The value may be an integer or a string (cf. dialog's manual page for more details).
Main changes in version 3.3.0
The main changes in version 3.3.0 are:
-
The Python 2 backport has been updated to this version.
-
Allow passing dialog arguments via a temporary file
In order to prevent information leak through the process table (which normally shows all commands executed by any user, along with their arguments), pythondialog can now write dialog arguments to a temporary file and call dialog with the
--fileoption to point him to this temporary file, where it will read the “real” arguments (such as--msgbox, box titles, messages to display in boxes, etc.). This new behavior is enabled by default starting from pythondialog 3.3.0 if the dialog version is 1.2-20150513 or later. TheDialogclass constructor accepts a new keyword-only argument,pass_args_via_file, that allows one to explicitly choose whether to use the feature or not.Dialog.setup_debug()offers a newexpand_file_optparameter to allow producing debug log files with full dialog commands as before, instead of dialog calls containing only one--fileoption followed by a path to a temporary file.Similarly, examples/demo.py accepts a new option (
-E,--debug-expand-file-opt) to allow obtaining the same dialog commands as before in the file generated by--debug(i.e., with the--fileoptions expanded instead of referring to the temporary files).Thanks to Bernd Geiser for the feature request that led to these improvements.
-
Bug fix in
Dialog._dialog_version_check()(which is typically used to check whether a given widget is available in the selected dialog version): the message passed when raisingInadequateBackendVersionhad a hardcoded “the programbox widget” substring where it should have been using thefeatureparameter.
Main changes in version 3.2.2
The main changes in version 3.2.2 are:
-
The Python 2 backport has been updated to this version.
-
Fix backend version check for , , and .
-
Bug fixes related to old versions of dialog (e.g., 1.1-20100428) and Python (3.0 and 3.1, untested on 3.0—please report if you care about this ancient version).
(This includes a fix for a crash in examples/demo.py when the dialog backend is too old to have the widget.)
Main changes in version 3.2.1
The main change in version 3.2.1 is an improved tutorial chapter in the pythondialog Manual.
Main changes in version 3.2.0
The main changes in version 3.2.0 are:
-
New manual generated with Sphinx. Check it out!
-
The default values for day, month and year in the widget have been changed from 0 to -1. This is unfortunately BACKWARD-INCOMPATIBLE, but 0 doesn't work well for day and month in dialog, and it would be quite unintuitive to have them default to -1 with the year still defaulting to 0.
This change should affect very few people, if any, which is why I decided to fix the API now without increasing the major version number.
Main changes in version 3.1.0
The main changes in version 3.1.0 are:
-
Experimental support for automatic widget size
The
Dialogclass constructor accepts a new keyword-only argument:autowidgetsize. It is a boolean and currently defaults toFalsein order to preserve backward-compatibility.When set to
True, pythondialog's widget-producing methods will behave as ifwidth=0,height=0, etc. had been passed, except where these parameters are explicitely specified with different values. This has the effect that, except where you explicitely specify a size parameter such aswidthorheight, the dialog backend will automatically compute a suitable widget size for you.Notes:
-
In order to differentiate between a default value obtained when
autowidgetsizeis disabled and an explicitely-specifiedwidth,height, etc., the size parameters modified by this change now default toNone. In order to compensate for this information loss, the effective default values whenautowidgetsizeisFalseare now mentioned in the docstrings of the corresponding widget-producing methods. -
The
autowidgetsizeoption is currently marked as experimental. It may default toTruein the next major release; please give some feedback on the mailing list if you care. -
You may encounter questionable results if you only set one of the
widthandheightparameters to 0 for a given widget (seen in dialog 1.2-20140219).
Examples using the
autowidgetsizeoption can be found in the examples/with-autowidgetsize directory of the pythondialog distribution. -
-
Improved installation instructions
-
Removal of
_create_temporary_directory()in favor oftempfile.NamedTemporaryFile()There was no security problem in
_create_temporary_directory()as far as I know, however it is usually better to use well-tested library functions whenever possible instead of custom ones. When_create_temporary_directory()was written, what was available from the tempfile module was not satisfactory, but this is not the case anymore.This change brings a small BACKWARD INCOMPATIBILITY: the
UnableToCreateTemporaryDirectoryexception is not defined anymore.Dialog.scrollbox()now creates a temporary file without any temporary directory, therefore there is no place anymore for this exception to be used. The equivalent condition intempfile.NamedTemporaryFile()generates anOSErrorexception (more precisely, aFileExistsErrorin Python 3.3 or later, which is a subclass ofOSError). As usual, this exception is wrapped by pythondialog and seen as aPythonDialogOSErrorby user code.Conclusion: wherever user code was expecting
UnableToCreateTemporaryDirectoryin previous versions, it should now expect aPythonDialogOSError, consistently with the tempfile module andOSErrorwrapping by pythondialog.This incompability should affect so few users, if any, that I think increasing the major number just for it would have caused more harm than good.
-
The widget has been improved in dialog 1.2-20140112 and the demo uses it in a better way.
-
The files demo.py and simple_example.py have been moved to the examples directory of the source distribution.
Main changes in version 3.0.1
Compared to version 3.0.0, version 3.0.1 has minor improvements and a backport to Python 2. Go to the PyPI entry for the Python 2 backport for more information concerning this backport.
Main changes in version 3.0.0
The major version number has been increased because this version is not completely backward-compatible with version 2. However, the backward-incompatible changes are small and unlikely to affect many people, if any (see below). The main changes in version 3.0.0 are:
-
Full help support for all widgets
You can now use the keyword arguments (“dialog common options”)
help_button,help_label,item_help,help_tagsandhelp_statuswith any widget to provide help facilities to the user (as long as the dialog backend supports the corresponding options). Please refer to the pythondialog Manual for details. demo.py has a number of examples showing how to implement help support in user code.The API extends what was already present for help support in the widget. Backward-compatibility is only affected for people who used to parse the dialog output after the Help button has been pressed, because this is now automatically done by pythondialog in order to return ready to use, structured data. If you only check the Dialog exit code, you are not affected.
pythondialog should now offer access to all help facilities provided by the dialog backend.
-
Nicer exit codes for widget-producing methods
The old, low-level exit codes
d.DIALOG_OK,d.DIALOG_CANCEL,d.DIALOG_ESC,d.DIALOG_HELP,d.DIALOG_ITEM_HELPandd.DIALOG_EXTRAare deprecated (where d is aDialoginstance). They still work, but trigger a DeprecationWarning (see README.rst or its HTML rendering for instructions on how to enable deprecation warnings).You should now use
d.OK,d.CANCEL,d.ESC,d.HELPandd.EXTRA, or equivalentlyDialog.OK,Dialog.CANCEL,Dialog.ESC,Dialog.HELPandDialog.EXTRA(attributes of theDialogclass). These are called the high-level exit codes, or Dialog exit codes, and defined as strings:"ok","cancel","esc","help"and"extra". You should use the==operator when comparing to these codes.Notes:
-
There is no ITEM_HELP in the high-level exit codes: the DIALOG_HELP and DIALOG_ITEM_HELP low-level codes are both translated into
Dialog.HELP. Indeed, the program that has to interpret the code already knows whether it useditem_help=Truein the widget call or not. Both cases correspond to the same user action: the Help button being pressed. Therefore, the distinction is not useful to user code. -
As said, the values of the high-level exit codes are strings:
"ok","cancel","esc","help"and"extra". You may use the string literals directly in your code, instead ofd.OKorDialog.OK,d.CANCELorDialog.CANCEL, etc. With proper syntax highlighting, this produces good-looking code, but offers no protection against typos, contrary to theDialogclass attributesDialog.OKand friends. Apart from that, it is mostly a matter of taste. -
Backward-compatibility should only be affected for code that relies on the nature of
d.DIALOG_OK,d.DIALOG_CANCEL,d.DIALOG_ESC,d.DIALOG_HELP,d.DIALOG_ITEM_HELPandd.DIALOG_EXTRA, which were integers in pythondialog 2 and are now strings (the deprecated attributes are mapped to the high-level exit codes, so that the vast majority of old user code still works without modification, despite the changes).
-
-
Better Extra button support
-
A few widgets, when the Extra button was pressed, used to return
Noneinstead of the expected value corresponding to user input. This is fixed. -
Similarly to help support, pythondialog now automatically parses the dialog output when the Extra button has been pressed, in order to return ready to use, structured data (normally: the same as if OK had been pressed). This is backward-incompatible.
Extra button support should now be as good as in the dialog backend. See the
Dialogclass docstring for details. -
-
widget support
-
New
retval_is_codedecorator that sets the attribute of the same name on its argument. This attribute allows to reliably detect if a widget-producing method returns a Dialog exit code or a sequence whose first element is a Dialog exit code. This is used in the demo, and was necessary since the new exit codes from widget-producing methods are strings, and thus sequences.
Main changes in version 2.14.1
The main changes in version 2.14.1 are:
-
decorate
Dialog.formwith thewidgetdecorator (forgotten in version 2.14.0); -
better reporting of dialog errors: when dialog exits with status DIALOG_ERROR, write its output as part of the
DialogErrorexception that is raised. This should make it much easier to understand the cause of errors. -
in the demo, handle the case where
subprocess.DEVNULLis not defined, since this attribute was added in Python 3.3; -
easier management of the ChangeLog file.
Main changes in version 2.14.0
The main changes in version 2.14.0 are:
-
Add support for the , and widgets.
-
Add support for new dialog common options:
--default-buttonand--no-tags. -
In dialog.py, use a context manager to factor out
OSErrorandIOErrorhandling throughout the module. -
dialog.py has a new
version_infomodule-level attribute, similar to what thesysmodule provides. This avoids the need to parse__version__when one wants to extract for instance the major and/or minor version number of pythondialog. -
Backend version caching and comparing
Slight modification to a recent API: when the dialog-like backend does not return DIALOG_OK,
Dialog.backend_version()raisesUnableToRetrieveBackendVersion(new exception) instead of returning None. This way, the method either returns a string or raises an exception.dialog.py has a new
DialogBackendVersionclass (andBackendVersionabstract base class) for parsing the version string of the dialog backend, storing it in a structured format, and providing easy and reliable comparisons between versions using the standard comparison operators (<, <=, ==, !=, >=, >).Dialog.__init__retrieves the backend version and stores the corresponding (Dialog)BackendVersion instance into a publiccached_backend_versionattribute. This should avoid having to run 'backend --print-version' every time someone needs the version. -
Check for too old versions of the backend
dialog.py has a new exception called
InadequateBackendVersionthat is raised when the user tries to use a , or widget with a dialog version that does not implement the widget in question (of course, similar checks will be added for future widgets).Similarly, for the latest widgets added to dialog, the demo checks the version of the backend if it's dialog and displays an explanation instead of the widget demo when it is too old.
-
Add an
is_widgetattribute toDialogwidget-producing methodsdialog.widgetis a new decorator to mark theDialogmethods that provide a widget. As explained in the docstring, this allows code to perform automatic operations on these specific methods. For instance, one can define a class that behaves similarly toDialog, except that after every widget-producing call, it spawns a "confirm quit" dialog if the widget returned DIALOG_ESC, and loops in case the user doesn't actually want to quit. -
Improve structure and ESC handling in the demo
-
New
MyAppclass that implements the core of the demo. This class relies on a newMyDialogclass that automatically wraps every widget-producing method ofdialog.Dialogin order to display the "confirm quit" dialog if the user presses the Escape key or the Cancel button. This class also provides a few dialog-related methods used in the demo. -
This new structure should completely fix handling of the
Escape key, which was not satisfactory in previous versions
since it required a while loop for every widget call that made
the code redundant and harder to read. The new wrapping
mechanism is completely transparent for most of the code in
MyApp, which thus becomes shorter, more reliable and easier to read. The "magic" is contained within theMyDialogclass.
-
New
-
Add a sample program called simple_example.py that is really intended for newcomers: short, straightforward, with absolutely no magic.
-
In demo.py, move a bunch of widget demos from
MyApp.additional_widgets()to the mainMyApp.demo()method to give them more visibility. The remaining widgets inMyApp.additional_widgets()either have little warts (like which is waiting for a fix in the dialog backend), are cumbersome for the person running the demo (this is the case ofprogressbox_demo_with_filepath), or are almost identical to widgets already presented in the main part of the demo.
Main changes in version 2.13.1
The main change in version 2.13.1 is:
-
remove the default /usr/local installation prefix in setup.cfg that broke installations with pip in a virtualenv, at least.
Main changes in version 2.13
The main changes in version 2.13 are:
-
a new
set_background_title()method (replacing the long-obsoletesetBackgroundTitle()from pythondialog 1.0) that does proper “dash escaping”1; -
documentation improvements for the
Dialogclass.
Main changes in version 2.12
The main changes in version 2.12 are:
-
Python 3 support. You can (and should) now pass “normal” strings to pythondialog calls, which correspond to Unicode strings in Python 2-speak. Python will automatically encode the arguments according to the current locale when calling dialog. pythondialog-based scripts can be written in any encoding (using an encoding declaration if the encoding is not UTF-8), and everything will be automatically recoded according to the user's locale when he runs the script.
Of course, if the script tries to display a character that can't be represented in the user's locale, there is a problem. For instance, the “Ÿ” (LATIN CAPITAL LETTER Y WITH DIAERESIS) and euro sign don't exist in ISO 8859-1, therefore if the terminal is running under a locale based on ISO 8859-1, it can't display any of these characters and there is nothing that pythondialog can do about that. However, if using only characters that can be represented in the user's locale, there is no problem and everything is automatically translated between the encoding of the Python script and the encoding defined by the user's locale. In particular, this last condition is almost always satisfied when the user's locale is based on Unicode, since this character set can represent just about anything that can be found in the myriad of legacy character sets.
-
Proper escaping of user-supplied values in case they start with two dashes (“--”). Such strings could be confused with dialog options in previous versions, since pythondialog didn't do any such escaping before version 2.12.
-
Much easier debugging, with
Dialog.setup_debug(), its optional use in the demo and the new traceback handling thanks to thetracebackmodule (see the pythondialog Manual, history link on the Git repository, or ChangeLog file in a release tarball for details). In case there is a problem with the demo, or if you just want to look under the hood, you can now run it with --debug (and optionally --debug-file) to make it write the full dialog command lines to a file. -
Standard exception behavior: if e is a
dialog.errorinstance (or an instance of adialog.errorsubclass), thenstr(e)returns nothing more than the exception message, as with all Python built-in exceptions. No need to writee.complete_message()anymore. -
Support for many “common options” has been added:
--ascii-lines,--colors,--column-separator,--date-format,--exit-label,--extra-button,--extra-label,--hfile,--hline,--keep-tite,--keep-window,--no-collapse,--no-lines,--no-mouse,--no-nl-expand,--no-ok,--scrollbar,--time-format,--traceand--visit-items. The new methodDialog.maxsize()allows one to find the terminal size and know how many lines and columns are available for a dialog box. -
The pythondialog version is now accessible as
dialog.__version__(attribute of thedialogmodule), as per Python standards; additionally, the version of the dialog backend in use can be obtained withDialog.backend_version()(method ofDialoginstances). -
Transition from
PythonDialogIOErrortoPythonDialogOSError. As you may be aware of, the exception hierarchy has been reworked in Python 3.3, and from this version onwards,IOErroris an alias ofOSError. In this context, it would be nice to get rid ofPythonDialogIOErrorin favor ofPythonDialogOSError. pythondialog 2.12 prepares this transition in the following way.PythonDialogIOErroris now a subclass ofPythonDialogOSErrorso that users can safely replaceexcept PythonDialogIOErrorclauses withexcept PythonDialogOSErroreven if running under Python < 3.3. pythondialog will raisePythonDialogOSErrorinstead ofPythonDialogIOErrorwhen Python stops distinguishing betweenIOErrorandOSError, i.e. when running under Python 3.3 or later.
Footnotes
1. This could be useful if you (somewhat strangely) chose a backtitle that starts with a double dash (“--”). Without dash escaping, it might be mistaken for a dialog option.