Repository navigation
Conversation
The doctest workaround replaced only sys.displayhook. Doctest sets sys.displayhook to sys.__displayhook__ before each example, so the default hook was used again and assigned the printed values to _ in builtins, replacing the gettext function. Any later _() call in the tested code failed with "'str' object is not callable". Replace sys.__displayhook__ as well. The change was developed with the help of an AI assistant (Claude).
The temporal doctest wrapper was disabled with a comment that it stalls with Python 3. It does not stall, but about half of the doctests failed. - Use tgis.init() with an import in the docstrings that called init() or get_current_mapset() without importing them, and import datetime where it is used. - Do not expect 0 from run_command(), which returns None. - Update expected output for the insertion order of dictionaries, the new semantic label line, floating point precision, and exceptions which are qualified in Python 3. - Call get_time_tuple_function() with a list of maps and call the private method of an instance in _update_where_statement_by_spatial_extent(). - Return None from STRDSMetadata.get_semantic_labels() when there is no register table, instead of querying a table named None. - Enable the wrapper and the list_stds doctests. The changes were developed with the help of an AI assistant (Claude).
Only the grass.script.array doctests were run. Load the doctests of the other modules in the gunittest wrapper and fix the examples, which were written for another dataset or an older Python and never ran. - Use the maps of the CI dataset (lsat7_2002_*, lakes) and qualify a mask from another mapset with its mapset name. - Import grass.script as gs where it is used, use gs.run_command() and continue multiline examples with "...". - Do not expect 0 from run_command() and write_command(), which return None. - Use "map" instead of "raster" in the r.support calls, and overwrite maps and regions which are created by more than one example. - Match values which are random or differ between runs and builds (temporary names, version(), Popen repr, mapset names) with ellipsis. - Update expected output for the insertion order of dictionaries and the results of command_info(), raster_info(), vector_info() and others. - Use Python 3 syntax for the encoding examples, and call encode() in the example of encode(). - Use db_connection(force=True) so the result does not depend on whether the mapset already has a connection. The changes were developed with the help of an AI assistant (Claude).
The file is written by the ply parser when the temporal algebra tests run and was committed by accident. It does not pass the whitespace checks of pre-commit. The change was developed with the help of an AI assistant (Claude).
| ... gs.run_command("r.mask", raster="state_boundary") | ||
| ... gs.parse_command("r.univar", map="elevation", format="json") | ||
| ... gs.run_command("r.mask", raster="lakes") |
There was a problem hiding this comment.
Find more about the old raster. I don't really like changing layers like that
There was a problem hiding this comment.
state_boundary was added in OSGeo#2392 (Feb 2025) as an illustrative name. It is not in nc_spm_full_v2beta1, nc_spm_08_grass7, or anywhere else in the repository, so the example could never run. The closest real raster is ncmask_500m, but it covers the whole elevation region, so the mask would change nothing (n stays 2025000). lakes does mask cells (n = 36011), so the example shows an effect. Happy to switch to ncmask_500m if you prefer keeping the state-wide idea.
Generated by Claude Code
| ... "r.mapcalc", expression="masked_elevation = elevation", overwrite=True | ||
| ... ) |
There was a problem hiding this comment.
Can you find what needed you to add overwrite? Just have different names for different examples
There was a problem hiding this comment.
Examples in the same docstrings reused output names (slope, study_area) in one mapset. Fixed in 71eaef1 with distinct names (slope_activated, study_area_env), and all the overwrite=True I added are removed. The one on manager.save("elevation_region", overwrite=True) was already there, so I left it.
Generated by Claude Code
| ... "r.mapcalc", expression=f"masked_elevation = elevation", env=manager.env | ||
| ... "r.mapcalc", | ||
| ... expression="masked_elevation = elevation", | ||
| ... overwrite=True, |
There was a problem hiding this comment.
Can you make sure overwrite is really needed, and not a workaround
There was a problem hiding this comment.
It was a workaround: the two examples both wrote masked_elevation, so the second needed overwrite. In 71eaef1 the second one writes masked_elevation_env and overwrite=True is gone.
Generated by Claude Code
| import grass.script.core as gcore | ||
| import grass.script.db as gdb | ||
| import grass.script.imagery as gimagery | ||
| import grass.script.raster as graster | ||
| import grass.script.raster3d as graster3d | ||
| import grass.script.task as gtask | ||
| import grass.script.utils as gutils | ||
| import grass.script.vector as gvector |
There was a problem hiding this comment.
I don't like these renames, can you justifie more on this?
There was a problem hiding this comment.
There was no strong reason for the aliases. In 71eaef1 the modules are loaded by name in a loop (DocTestSuite(f"grass.script.{name}")), so there are no new imports or renames.
Generated by Claude Code
| PRECISION'}, 'SHAPE_len': {'index': 7, 'type': 'DOUBLE PRECISION'}, | ||
| 'cat': {'index': 0, 'type': 'INTEGER'}, 'GEOL250_ID': {'index': 4, 'type': | ||
| 'INTEGER'}, 'GEO_NAME': {'index': 5, 'type': 'CHARACTER'}} | ||
| {'cat': {'type': 'INTEGER', 'index': 0}, 'onemap_pro': {'type': 'DOUBLE PRECISION', 'index': 1}, 'PERIMETER': {'type': 'DOUBLE PRECISION', 'index': 2}, 'GEOL250_': {'type': 'INTEGER', 'index': 3}, 'GEOL250_ID': {'type': 'INTEGER', 'index': 4}, 'GEO_NAME': {'type': 'CHARACTER', 'index': 5}, 'SHAPE_area': {'type': 'DOUBLE PRECISION', 'index': 6}, 'SHAPE_len': {'type': 'DOUBLE PRECISION', 'index': 7}} |
There was a problem hiding this comment.
Can this be reformatted? Also, I thought that our doctest examples were reformatted with ruff, how come this wasn't?
There was a problem hiding this comment.
Reformatted in 71eaef1, with the results wrapped across lines and +NORMALIZE_WHITESPACE. Ruff's docstring-code-format only formats the code after >>>, never the expected output lines, and E501 is ignored, so nothing flagged the long lines. I pasted the actual outputs without wrapping them.
Generated by Claude Code
Give each doctest example its own output name instead of overwriting the output of an earlier example in the same mapset, wrap the long expected results across lines, and load the grass.script modules by name in the doctest wrapper instead of importing each one under a new alias.
Description
Builds on #744 (this PR is based on that branch, so only the last three commits are new).
grass.gunittest: the gettext workaround for doctests replaced onlysys.displayhook. Doctest resets it tosys.__displayhook__before each example, so printed values replaced the_gettext function in builtins and later_()calls failed.sys.__displayhook__is replaced as well.grass.temporal: the doctest wrapper was disabled with "stalls" for Python 3. It does not stall, but about half of the doctests failed (missing imports,run_command()returningNone, dictionary order, exceptions in Python 3). Fix them and enable the wrapper.STRDSMetadata.get_semantic_labels()now returnsNonewithout a register table instead of querying a table namedNone.grass.script: onlyarraywas in the doctest wrapper. Load all modules with doctests and fix the examples, which were written for another dataset or older Python.Motivation and context
Doctests only run through the gunittest wrappers, so broken examples were not noticed.
How has this been tested?
python3 -m grass.gunittest.main --location-type nc --config .gunittest.cfgwithnc_spm_full_v2beta1onpython/grass/script,python/grass/gunittest,python/grass/pygrassandpython/grass/temporal. All files pass, except the two temporal files that are already excluded in.gunittest.cfg. The doctest wrappers also pass with differentPYTHONHASHSEEDvalues.ruff formatandruff checkpass.Not done:
gui_supportdoctests (they expect a space time dataset inPERMANENT), andtest_pygrass_modules_grid_doctests.pystill loads no tests.Types of changes
functionality to not work as before)
Checklist
pre-defined prefixes
of this project.
The changes were developed with the help of an AI assistant (Claude).
Generated by Claude Code