Skip to content

DOC/TST: use scipy-doctest, update examples with complete imports#2200

Merged
jorisvandenbossche merged 3 commits intoshapely:mainfrom
mwtoews:scipy-doctest
Feb 18, 2025
Merged

DOC/TST: use scipy-doctest, update examples with complete imports#2200
jorisvandenbossche merged 3 commits intoshapely:mainfrom
mwtoews:scipy-doctest

Conversation

@mwtoews
Copy link
Copy Markdown
Member

@mwtoews mwtoews commented Jan 15, 2025

This switches from using doctest to scipy-doctest to run the doctesting. This is the same extension used by NumPy and SciPy.

The motivation for this switch is that it allows flexibility of minor floating-point differences in some outputs, and allows legacy NumPy repr formatting, e.g.:

>>> import shapely
>>> from shapely import Point
>>> shapely.get_x(Point(1, 2))
1.0

instead of testing against np.float64(1.0) as with NumPy 2.0+. While this PR keeps the doctest CI job with NumPy 1.26.2, it runs the same locally with newer versions.

Most of the changes in this PR are to provide complete examples, and to call module-level ufuncs from the module. The previous version used (e.g.) get_x(pt) with an implicit from shapely import get_x. However, I think it is better to keep the module-level calls like shapely.get_x(pt). An exception to this rule is the geometry classes (Point, etc.).

Other changes are to set conftest.py to the module root shapely/, and this is inspired directly from NumPy's numpy/conftest.py. This allows some options for scipy-doctest and fine-tuning filtering warnings in the doctests.

Copy link
Copy Markdown
Contributor

@sgillies sgillies left a comment

Choose a reason for hiding this comment

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

@mwtoews obscuring the real type of values in the doctest might be a little misleading, though? Showing that a value is a Python int when it really is a numpy typed object could trip up somebody. So maybe we use scipy-doctest, but be pedantic about the values?

@jorisvandenbossche
Copy link
Copy Markdown
Member

It's certainly a trade-off, but the benefit of keeping the output as it is shown now in the docstrings (and so adopting scipy-doctest to be able to keep doing that also when updating numpy > 2) is that it gives less visual clutter in the example and focuses more on the message to show to the user.

If we show an example like:

>>> shapely.has_z(Point(0, 0))
False

the main message is that it returns False for a XY point. If this shows np.False_ (or np.float64(1.0) for 1.0), that feels like unnecessary clutter and potentially distracting the reader.

It's like putting a print(..) around each example, except for not doing that explicitly..

Copy link
Copy Markdown
Contributor

@sgillies sgillies left a comment

Choose a reason for hiding this comment

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

Okay, I'm convinced about relaxing the type check.

@coveralls
Copy link
Copy Markdown

coveralls commented Jan 15, 2025

Pull Request Test Coverage Report for Build 13386052724

Details

  • 23 of 31 (74.19%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.3%) to 87.764%

Changes Missing Coverage Covered Lines Changed/Added Lines %
shapely/conftest.py 23 31 74.19%
Totals Coverage Status
Change from base Build 13364938053: 0.3%
Covered Lines: 2618
Relevant Lines: 2983

💛 - Coveralls

@mwtoews
Copy link
Copy Markdown
Member Author

mwtoews commented Jan 16, 2025

If/when NumPy changes their docstrings, then I'd be convinced to change it here too. For instance, see numpy.sin where currently np.sin(np.pi/2.) shows 1.0 rather than np.float(1.0) as with modern versions of NumPy.

Also, I should note that scipy-doctest has an option dt_config.strict_check = True that does dtype checks where applicable, which is related to numpy/numpy@90c34cb. If we were to enable this feature, it would require changes like:

>>> shapely.get_coordinate_dimension(Point(0, 0))
np.int32(2)

but this option still relaxes np.float64(0.0) stuff as 0.0. But I don't think it's really important to most users that (e.g.) coordinate dimensions have a int32 type, so I didn't enable this feature. But perhaps it's more important for users to see (e.g.)

>>> shapely.get_srid(shapely.set_srid(Point(0, 0), 1234567890))
np.int32(1234567890)

@jorisvandenbossche
Copy link
Copy Markdown
Member

jorisvandenbossche commented Jan 16, 2025

But perhaps it's more important for users to see (e.g.)

That also doesn't seem that important to know the SRID is returned as an int32 vs int64? (SRID numbers are typically smaller numbers than the int32 limits)

Comment on lines +1165 to +1194
>>> snap(line1, LineString([]), 0.25)
<LINESTRING (0.1 0.1, 0.49 0.51, 1.01 0.89)>
>>> shapely.snap(line1, LineString([]), 0.25).wkt # TODO: why is '.wkt' needed?
'LINESTRING (0.1 0.1, 0.49 0.51, 1.01 0.89)'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this todo get resolved first?

Copy link
Copy Markdown
Member

@jorisvandenbossche jorisvandenbossche left a comment

Choose a reason for hiding this comment

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

Looks good!

Added some small comments for consistency

@jorisvandenbossche
Copy link
Copy Markdown
Member

I am going to merge those small suggestions, so I can merge this PR now to avoid another round of updating an fixing merge conflicts if I continue merging other PRs!

@jorisvandenbossche jorisvandenbossche merged commit 79a094b into shapely:main Feb 18, 2025
@jorisvandenbossche
Copy link
Copy Markdown
Member

Thanks @mwtoews!

@theroggy theroggy mentioned this pull request Feb 18, 2025
@theroggy theroggy added this to the 2.1 milestone Feb 20, 2025
@mwtoews mwtoews deleted the scipy-doctest branch April 13, 2025 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants