-
Notifications
You must be signed in to change notification settings - Fork 92
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
374 add hypothesis tests for times and views #379
Conversation
Changed Files
|
Reviewer's Guide by SourceryThis PR removes time primitives from views and adds hypothesis tests for times and views modules. The changes also include improvements to KmlDateTime handling and type corrections for Lod parameters. Class diagram for updated views moduleclassDiagram
class _AbstractView {
-heading: Optional[float]
-tilt: Optional[float]
-altitude_mode: Optional[AltitudeMode]
-times: Union[TimeSpan, TimeStamp, None] // Removed
}
class Camera {
-roll: Optional[float]
-time_primitive: Union[TimeSpan, TimeStamp, None] // Removed
}
class LookAt {
-range: Optional[float]
-time_primitive: Union[TimeSpan, TimeStamp, None] // Removed
}
class LatLonAltBox {
-north: float
-south: float
-east: float
-west: float
-min_altitude: float
-max_altitude: float
-altitude_mode: AltitudeMode
}
class Lod {
-min_lod_pixels: int // Changed from float
-max_lod_pixels: int // Changed from float
-min_fade_extent: int // Changed from float
-max_fade_extent: int // Changed from float
}
_AbstractView <|-- Camera
_AbstractView <|-- LookAt
Class diagram for KmlDateTime changesclassDiagram
class KmlDateTime {
-dt: Union[date, datetime]
-resolution: Optional[DateTimeResolution]
+__init__(dt: Union[date, datetime], resolution: Optional[DateTimeResolution])
+parse(datestr: str): Optional[KmlDateTime]
}
class DateTimeResolution {
<<enumeration>>
date
datetime
year
year_month
}
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
WalkthroughThe pull request introduces significant changes to the Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Summary
|
Failed to generate code suggestions for PR |
CI Failure Feedback 🧐(Checks updated until commit 36f0573)
✨ CI feedback usage guide:The CI feedback tool (
In addition to being automatically triggered, the tool can also be invoked manually by commenting on a PR:
where Configuration options
See more information about the |
PR Code Suggestions ✨Explore these optional code suggestions:
|
Preparing review... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @cleder - I've reviewed your changes and they look great!
Here's what I looked at during the review
- 🟡 General issues: 2 issues found
- 🟢 Security: all looks good
- 🟡 Testing: 2 issues found
- 🟡 Complexity: 1 issue found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
max_lod_pixels: typing.Optional[int], | ||
min_fade_extent: typing.Optional[int], | ||
max_fade_extent: typing.Optional[int], | ||
) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (testing): Missing validation tests for coordinate relationships
The test should include assertions to verify that north > south and east > west when both values are provided. This would help catch potential validation issues with the coordinate bounds.
id: typing.Optional[str], | ||
target_id: typing.Optional[str], | ||
timestamp: typing.Optional[fastkml.times.KmlDateTime], | ||
) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (testing): Missing validation for begin/end time relationship
The test should include assertions to verify that when both begin and end times are provided, end time is always greater than or equal to begin time. This would help catch potential temporal validation issues.
@@ -377,6 +343,18 @@ | |||
default=0.0, | |||
), | |||
) | |||
registry.register( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider extracting the altitude_mode registration logic into a reusable helper function
The altitude_mode registration is duplicated across Camera, LookAt, and LatLonAltBox classes. Consider creating a helper function to reduce duplication while preserving namespace flexibility:
def register_altitude_mode(cls, ns_ids=("kml",)):
"""Helper to register altitude_mode with custom namespaces."""
registry.register(
cls,
RegistryItem(
ns_ids=ns_ids,
attr_name="altitude_mode",
node_name="altitudeMode",
classes=(AltitudeMode,),
get_kwarg=subelement_enum_kwarg,
set_element=enum_subelement,
default=AltitudeMode.clamp_to_ground,
),
)
# Usage:
register_altitude_mode(Camera, ns_ids=("kml", "gx", ""))
register_altitude_mode(LookAt, ns_ids=("kml", "gx", ""))
register_altitude_mode(LatLonAltBox, ns_ids=("kml", "gx", ""))
This maintains the namespace customization while eliminating code duplication.
from fastkml.views import LatLonAltBox | ||
from fastkml.views import Lod | ||
from tests.base import Lxml | ||
from tests.hypothesis.common import assert_repr_roundtrip |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (code-quality): Don't import test modules. (dont-import-test-modules
)
Explanation
Don't import test modules.Tests should be self-contained and don't depend on each other.
If a helper function is used by multiple tests,
define it in a helper module,
instead of importing one test from the other.
from fastkml.views import Lod | ||
from tests.base import Lxml | ||
from tests.hypothesis.common import assert_repr_roundtrip | ||
from tests.hypothesis.common import assert_str_roundtrip |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (code-quality): Don't import test modules. (dont-import-test-modules
)
Explanation
Don't import test modules.Tests should be self-contained and don't depend on each other.
If a helper function is used by multiple tests,
define it in a helper module,
instead of importing one test from the other.
from tests.base import Lxml | ||
from tests.hypothesis.common import assert_repr_roundtrip | ||
from tests.hypothesis.common import assert_str_roundtrip | ||
from tests.hypothesis.common import assert_str_roundtrip_terse |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (code-quality): Don't import test modules. (dont-import-test-modules
)
Explanation
Don't import test modules.Tests should be self-contained and don't depend on each other.
If a helper function is used by multiple tests,
define it in a helper module,
instead of importing one test from the other.
from tests.hypothesis.common import assert_repr_roundtrip | ||
from tests.hypothesis.common import assert_str_roundtrip | ||
from tests.hypothesis.common import assert_str_roundtrip_terse | ||
from tests.hypothesis.common import assert_str_roundtrip_verbose |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (code-quality): Don't import test modules. (dont-import-test-modules
)
Explanation
Don't import test modules.Tests should be self-contained and don't depend on each other.
If a helper function is used by multiple tests,
define it in a helper module,
instead of importing one test from the other.
from tests.hypothesis.common import assert_str_roundtrip | ||
from tests.hypothesis.common import assert_str_roundtrip_terse | ||
from tests.hypothesis.common import assert_str_roundtrip_verbose | ||
from tests.hypothesis.strategies import nc_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (code-quality): Don't import test modules. (dont-import-test-modules
)
Explanation
Don't import test modules.Tests should be self-contained and don't depend on each other.
If a helper function is used by multiple tests,
define it in a helper module,
instead of importing one test from the other.
Preparing review... |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #379 +/- ##
===========================================
+ Coverage 98.93% 99.08% +0.15%
===========================================
Files 60 62 +2
Lines 5060 5131 +71
Branches 146 148 +2
===========================================
+ Hits 5006 5084 +78
+ Misses 44 37 -7
Partials 10 10 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Looks good to me! Reviewed everything up to 871fe7c in 1 minute and 18 seconds
More details
- Looked at
1060
lines of code in11
files - Skipped
0
files when reviewing. - Skipped posting
2
drafted comments based on config settings.
1. fastkml/times.py:160
- Draft comment:
The change fromarrow.get(year, month, day).datetime
todate(year, month, day)
may affect timezone handling. The original code usedarrow
, which is timezone-aware, while the new code usesdate
, which is not. Ensure this change aligns with the intended behavior regarding timezones. - Reason this comment was not posted:
Comment did not seem useful.
2. fastkml/views.py:763
- Draft comment:
The change fromfloat
toint
formin_fade_extent
andmax_fade_extent
in theLod
class is significant. Ensure this change aligns with the intended functionality and update any dependent code accordingly. - Reason this comment was not posted:
Comment did not seem useful.
Workflow ID: wflow_V0Fas648RKmRZW5i
You can customize Ellipsis with 👍 / 👎 feedback, review rules, user-specific overrides, quiet
mode, and more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Looks good to me! Incremental review on 36f0573 in 15 seconds
More details
- Looked at
14
lines of code in1
files - Skipped
0
files when reviewing. - Skipped posting
1
drafted comments based on config settings.
1. docs/working_with_kml.rst:234
- Draft comment:
The change in the order of<kml:altitudeMode>
does not affect functionality but should be consistent with the intended structure. Ensure this change is intentional and consistent with the rest of the document. - Reason this comment was not posted:
Confidence changes required:33%
The change in the order of XML elements does not affect functionality but should be consistent with the intended structure.
Workflow ID: wflow_yU5y2Rb4j66QYmvE
You can customize Ellipsis with 👍 / 👎 feedback, review rules, user-specific overrides, quiet
mode, and more.
Preparing review... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Outside diff range and nitpick comments (9)
tests/hypothesis/strategies.py (1)
56-75
: Consider these improvements for better test coverage.
- The date range (2000-2050) might be too restrictive. Consider extending it to test edge cases.
- The resolution parameter has a redundant nested
st.none()
:resolution=st.one_of( - st.none(), - st.one_of(st.none(), st.sampled_from(fastkml.enums.DateTimeResolution)), + st.none(), + st.sampled_from(fastkml.enums.DateTimeResolution), ),
- Consider addressing the datetime timezone warnings (DTZ001) by using timezone-aware min/max values:
min_value=datetime.datetime(2000, 1, 1, tzinfo=datetime.UTC) max_value=datetime.datetime(2050, 1, 1, tzinfo=datetime.UTC)tests/hypothesis/times_test.py (1)
39-57
: Consider enhancing test coverage with additional assertions.The property-based test implementation is solid, but could be strengthened by:
- Adding assertions to verify the actual values of TimeStamp attributes match the input parameters
- Including explicit test cases for edge cases alongside the property-based tests
Consider adding these assertions:
def test_fuzz_time_stamp( self, id: typing.Optional[str], target_id: typing.Optional[str], timestamp: typing.Optional[fastkml.times.KmlDateTime], ) -> None: time_stamp = fastkml.TimeStamp(id=id, target_id=target_id, timestamp=timestamp) + # Verify attributes match input parameters + assert time_stamp.id == id + assert time_stamp.target_id == target_id + assert time_stamp.timestamp == timestamp assert_repr_roundtrip(time_stamp) assert_str_roundtrip(time_stamp)tests/times_test.py (2)
105-105
: LGTM! Consider adding edge case tests.The changes consistently update assertions to use
datetime.date
instead ofdatetime.datetime
, which aligns with the simplified date handling approach. This is a good change as it makes the API more precise about date-only values.Consider adding test cases for:
- Invalid date formats
- Dates near system limits (e.g., year 9999)
- Leap year edge cases
Also applies to: 119-119, 126-126, 141-141, 148-148
396-396
: LGTM! Consider adding string representation tests.The changes consistently update timespan and feature tests to use date objects. The test coverage is good, but could be enhanced.
Consider adding tests to verify:
- String representation of dates in KML output
- Parsing of different date formats from KML input
- Handling of mixed date and datetime values in the same timespan
Also applies to: 418-418
tests/hypothesis/geometry_test.py (1)
72-72
: LGTM! Improved test coverage with enum sampling.The change to sample directly from
AltitudeMode
enum is a good improvement because:
- It automatically includes all enum values in tests, including any future additions
- Reduces maintenance overhead by eliminating manual enum value listing
- Aligns with property-based testing best practices
Consider adding a comment explaining that this samples from all altitude modes to help future maintainers understand the test coverage.
altitude_mode=st.one_of( st.none(), st.sampled_from( - AltitudeMode, + AltitudeMode, # Samples from all available altitude modes for comprehensive testing ), ),tests/hypothesis/views_test.py (2)
87-88
: Consider inclusive ranges for heading and tiltThe strategies for
heading
andtilt
usemin_value=0
but may not cover values exactly at zero due to potential floating-point precision issues or previous filters observed in other strategies. Ensure that zero values are included to fully test boundary conditions.Verify that zero values are properly generated in these strategies. If necessary, adjust the strategies to explicitly include zero:
heading=st.one_of( st.none(), st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=360), + st.just(0.0), ), tilt=st.one_of( st.none(), st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180), + st.just(0.0), ),Also applies to: 91-92
216-221
: Avoid shadowing built-in names with variable namesThe parameters
roll
andrange
intest_fuzz_camera
andtest_fuzz_look_at
may shadow built-in functions (roll
is less common, butrange
is a built-in function in Python). While it's acceptable in context, renaming these parameters can prevent any potential confusion.Consider renaming
range
to, for example,range_distance
orrange_value
:# In test_fuzz_look_at @common_view( - range=st.one_of( + range_value=st.one_of( st.none(), st.floats(allow_nan=False, allow_infinity=False), ), ) # Update parameter names accordingly def test_fuzz_look_at( self, id: typing.Optional[str], target_id: typing.Optional[str], longitude: typing.Optional[float], latitude: typing.Optional[float], altitude: typing.Optional[float], heading: typing.Optional[float], tilt: typing.Optional[float], altitude_mode: typing.Optional[fastkml.enums.AltitudeMode], - range: typing.Optional[float], + range_value: typing.Optional[float], ) -> None: look_at = fastkml.LookAt( id=id, target_id=target_id, longitude=longitude, latitude=latitude, altitude=altitude, heading=heading, tilt=tilt, - range=range, + range=range_value, altitude_mode=altitude_mode, )Also applies to: 254-256
fastkml/times.py (2)
98-102
: Simplifydt
assignment for readabilityThe ternary expression used in assigning
dt
may reduce readability.Consider refactoring as:
if isinstance(dt, datetime) and resolution != DateTimeResolution.datetime: dt = dt.date()
Line range hint
160-168
: Handle incomplete date strings more explicitly inKmlDateTime.parse
When parsing date strings that lack month or day components, the code defaults missing values to 1, constructing a
date
object with potentially unintended values (e.g., January 1st). Consider whether it's more appropriate to handle these as separate cases without defaulting missing components, to preserve the accuracy of the original input.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (11)
fastkml/times.py
(2 hunks)fastkml/views.py
(7 hunks)tests/hypothesis/geometry_test.py
(1 hunks)tests/hypothesis/gx_test.py
(2 hunks)tests/hypothesis/multi_geometry_test.py
(1 hunks)tests/hypothesis/strategies.py
(2 hunks)tests/hypothesis/times_test.py
(1 hunks)tests/hypothesis/views_test.py
(1 hunks)tests/repr_eq_test.py
(0 hunks)tests/times_test.py
(9 hunks)tests/views_test.py
(0 hunks)
💤 Files with no reviewable changes (2)
- tests/repr_eq_test.py
- tests/views_test.py
🔇 Additional comments (16)
tests/hypothesis/strategies.py (2)
18-18
: LGTM: Import statements are well-organized.
The new imports are properly organized following the standard convention (standard library, third-party, local) and are all necessary for the new datetime functionality.
Also applies to: 26-29
56-75
: LGTM: Well-structured strategy for generating KML datetime objects.
The strategy correctly handles both date and datetime objects with proper timezone support and resolution options.
tests/hypothesis/times_test.py (1)
1-37
: LGTM! Well-structured file header with clear documentation.
The file header is well-organized with proper copyright notice, clear documentation of the module's purpose, and appropriate imports with type hints.
tests/hypothesis/gx_test.py (3)
35-35
: LGTM: Import change aligns with enhanced datetime testing strategy
The switch to importing kml_datetimes
from strategies module indicates a good move towards using a dedicated strategy for datetime testing, which should provide more comprehensive datetime coverage.
Line range hint 57-132
: LGTM: Comprehensive property-based testing implementation
The test methods provide excellent coverage through:
- Property-based testing of all relevant parameters
- Comprehensive roundtrip testing (repr, str, terse, verbose)
- Testing of nested structures (MultiTrack with Track items)
52-52
: LGTM: Simplified datetime strategy implementation
The switch to using kml_datetimes()
strategy simplifies the test data generation while potentially providing better datetime coverage.
Let's verify the datetime strategy implementation:
✅ Verification successful
Let me gather more context about the strategy implementation:
Strategy provides comprehensive datetime coverage
The kml_datetimes()
strategy is well-implemented with:
- Both date and datetime generators with reasonable bounds (2000-2050)
- Proper timezone handling via
timezones()
- Resolution handling using
fastkml.enums.DateTimeResolution
- Used consistently across multiple test files (gx_test.py, times_test.py)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the kml_datetimes strategy implementation
# Expected: Find the strategy definition with datetime constraints
# Look for the kml_datetimes strategy definition
rg -A 10 "def kml_datetimes" tests/hypothesis/strategies.py
# Look for any datetime-related constraints
rg "datetime" tests/hypothesis/strategies.py
Length of output: 405
Script:
#!/bin/bash
# Get the full implementation of kml_datetimes
ast-grep --pattern 'kml_datetimes = $_'
# Look for usages of this strategy
rg -l "kml_datetimes" tests/
Length of output: 1425
tests/times_test.py (2)
298-298
: LGTM! Timestamp reading tests are well structured.
The changes consistently update timestamp reading tests to use date objects, maintaining alignment with the new API design. The test coverage for different timestamp formats is comprehensive.
Also applies to: 311-311, 324-324, 337-337
Line range hint 1-424
: Consider adding property-based tests using hypothesis.
While the current test coverage is good, the date/time handling could benefit from property-based testing to discover edge cases automatically.
Consider adding hypothesis tests to:
- Generate random valid dates and verify parsing
- Generate random timespans and verify serialization
- Verify date/datetime resolution handling
tests/hypothesis/multi_geometry_test.py (1)
68-68
: LGTM! Enhanced test coverage for altitude modes.
The change to sample directly from AltitudeMode
enum improves test coverage by automatically including all possible altitude mode values, making the tests more maintainable and comprehensive.
Let's verify that we're testing all possible altitude modes:
✅ Verification successful
Let me gather more information to see the actual enum values.
Let me get the actual enum values to complete the verification.
Let me try a different approach to find the enum values.
Let me try one final approach to find the enum values.
Verified: Using sampled_from(AltitudeMode)
correctly covers all altitude modes
The change to use sampled_from(AltitudeMode)
is correct and comprehensive. The AltitudeMode
enum includes all five possible values:
- clampToGround (default)
- relativeToGround
- absolute
- clampToSeaFloor
- relativeToSeaFloor
Using Hypothesis's sampled_from
strategy with the enum ensures all these values will be tested, making the tests more robust and maintainable.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that all AltitudeMode values are covered in tests
# Test: Extract AltitudeMode enum values from the codebase
rg -A 5 "class AltitudeMode"
Length of output: 334
Script:
#!/bin/bash
# Get more context around AltitudeMode enum definition
rg -A 15 "class AltitudeMode"
Length of output: 1092
Script:
#!/bin/bash
# Get the actual enum values
ast-grep --pattern 'class AltitudeMode($_) {
$$$
}'
Length of output: 55
Script:
#!/bin/bash
# Find the enum values using ripgrep
rg -B 2 -A 10 "clampToGround = " fastkml/enums.py
Length of output: 51
Script:
#!/bin/bash
# Show the entire enums.py file content
cat fastkml/enums.py
Length of output: 8189
fastkml/views.py (5)
38-38
: LGTM: Complete public API exposure
The __all__
list now correctly includes all public classes defined in the module: Camera
, LatLonAltBox
, Lod
, LookAt
, and Region
.
690-693
: LGTM: Improved type accuracy for LOD parameters
The parameter types have been correctly changed from float
to int
for min_lod_pixels
, max_lod_pixels
, min_fade_extent
, and max_fade_extent
. This change better reflects the KML specification where these values represent pixel counts.
346-357
: LGTM: Enhanced altitude mode support
The registration of altitude_mode
for both Camera
and LookAt
classes now correctly includes the gx
namespace, enabling proper handling of Google Earth extensions for altitude modes.
Also applies to: 460-471
764-765
: LGTM: Consistent type handling for LOD values
The registry entries for LOD-related attributes now correctly use integer handlers (subelement_int_kwarg
and int_subelement
) instead of float handlers, maintaining consistency with the type changes in the class definition.
Also applies to: 776-777
37-37
: Verify the impact of removing time_primitive support
The removal of time_primitive
parameter from view classes might affect existing code. Let's verify if there are any direct usages that need to be updated.
fastkml/times.py (2)
93-114
: Verify consistency in KmlDateTime.__init__
with dt
and resolution
handling
The updated logic in __init__
adjusts dt
and resolution
based on their types and values. Please ensure that this logic correctly handles all edge cases, especially when dt
is a datetime
object and resolution
is not DateTimeResolution.datetime
. There is a possibility that time information could be lost if dt
is converted to a date
object unintentionally.
110-114
: Potential confusion with self.resolution
adjustment
The logic adjusting self.resolution
may lead to unexpected results if self.dt
is not a datetime
but resolution
is DateTimeResolution.datetime
. Verify that this adjustment aligns with the intended behavior of the class.
@given( | ||
id=st.one_of(st.none(), nc_name()), | ||
target_id=st.one_of(st.none(), nc_name()), | ||
begin=st.one_of(st.none(), kml_datetimes()), | ||
end=st.one_of(st.none(), kml_datetimes()), | ||
) | ||
def test_fuzz_time_span( | ||
self, | ||
id: typing.Optional[str], | ||
target_id: typing.Optional[str], | ||
begin: typing.Optional[fastkml.times.KmlDateTime], | ||
end: typing.Optional[fastkml.times.KmlDateTime], | ||
) -> None: | ||
time_span = fastkml.TimeSpan(id=id, target_id=target_id, begin=begin, end=end) | ||
|
||
assert_repr_roundtrip(time_span) | ||
assert_str_roundtrip(time_span) | ||
assert_str_roundtrip_terse(time_span) | ||
assert_str_roundtrip_verbose(time_span) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add validation for time range consistency.
The test should verify that when both begin
and end
times are provided, they form a valid time range (begin ≤ end). This validation is important for generating valid KML documents.
Consider adding this validation:
def test_fuzz_time_span(
self,
id: typing.Optional[str],
target_id: typing.Optional[str],
begin: typing.Optional[fastkml.times.KmlDateTime],
end: typing.Optional[fastkml.times.KmlDateTime],
) -> None:
time_span = fastkml.TimeSpan(id=id, target_id=target_id, begin=begin, end=end)
+ # Verify attributes match input parameters
+ assert time_span.id == id
+ assert time_span.target_id == target_id
+ assert time_span.begin == begin
+ assert time_span.end == end
+
+ # Verify time range consistency
+ if begin is not None and end is not None:
+ assert begin <= end, "Begin time must be before or equal to end time"
assert_repr_roundtrip(time_span)
assert_str_roundtrip(time_span)
Additionally, consider using hypothesis' assume()
to filter out invalid time ranges during test generation:
from hypothesis import assume
# Add at the start of the test function
if begin is not None and end is not None:
assume(begin <= end)
st.none(), | ||
st.floats( | ||
allow_nan=False, | ||
allow_infinity=False, | ||
min_value=-180, | ||
max_value=180, | ||
).filter(lambda x: x != 0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Include zero values for longitude and latitude in test strategies
In the common_view
function, the strategies for longitude
and latitude
exclude zero by filtering out values where x != 0
. Zero is a valid value for both longitude and latitude (representing the Prime Meridian and the Equator). Excluding zero may result in missing important test scenarios.
Modify the strategies to include zero:
longitude=st.one_of(
st.none(),
st.floats(
allow_nan=False,
allow_infinity=False,
min_value=-180,
max_value=180,
- ).filter(lambda x: x != 0),
+ ),
),
latitude=st.one_of(
st.none(),
st.floats(
allow_nan=False,
allow_infinity=False,
min_value=-90,
max_value=90,
- ).filter(lambda x: x != 0),
+ ),
),
Also applies to: 74-81
st.floats(allow_nan=False, allow_infinity=False).filter(lambda x: x != 0), | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Allow zero value for altitude in test strategy
The strategy for altitude
currently excludes zero by filtering out values where x != 0
. Since an altitude of zero is valid (representing sea level), it's important to include zero in the tests to cover this case.
Remove the filter to include zero values:
altitude=st.one_of(
st.none(),
st.floats(allow_nan=False, allow_infinity=False),
- ).filter(lambda x: x != 0),
+ ),
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
st.floats(allow_nan=False, allow_infinity=False).filter(lambda x: x != 0), | |
), | |
st.floats(allow_nan=False, allow_infinity=False), | |
), |
min_altitude=st.floats(allow_nan=False, allow_infinity=False).filter( | ||
lambda x: x != 0, | ||
), | ||
max_altitude=st.floats(allow_nan=False, allow_infinity=False).filter( | ||
lambda x: x != 0, | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Allow zero values for min_altitude and max_altitude
The strategies for min_altitude
and max_altitude
currently exclude zero by filtering out values where x != 0
. In KML, an altitude of zero is valid and represents sea level. Excluding zero may omit important test cases. Including zero ensures comprehensive test coverage.
Apply this diff to remove the filter excluding zero:
min_altitude=st.floats(allow_nan=False, allow_infinity=False).filter(
- lambda x: x != 0,
+ lambda x: True,
),
max_altitude=st.floats(allow_nan=False, allow_infinity=False).filter(
- lambda x: x != 0,
+ lambda x: True,
),
Or simply remove the .filter
:
min_altitude=st.floats(allow_nan=False, allow_infinity=False),
max_altitude=st.floats(allow_nan=False, allow_infinity=False),
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
min_altitude=st.floats(allow_nan=False, allow_infinity=False).filter( | |
lambda x: x != 0, | |
), | |
max_altitude=st.floats(allow_nan=False, allow_infinity=False).filter( | |
lambda x: x != 0, | |
), | |
min_altitude=st.floats(allow_nan=False, allow_infinity=False), | |
max_altitude=st.floats(allow_nan=False, allow_infinity=False), |
north=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90), | ||
south=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90), | ||
east=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180), | ||
west=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include negative values for latitude and longitude in test strategies
The current test strategies for north
, south
, east
, and west
coordinates only include positive values (min_value=0
). However, in KML, latitude ranges from -90 to 90 degrees, and longitude ranges from -180 to 180 degrees. Excluding negative values may result in insufficient test coverage.
Apply this diff to adjust the coordinate ranges:
north=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90),
south=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90),
east=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180),
west=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180),
to:
north=st.floats(allow_nan=False, allow_infinity=False, min_value=-90, max_value=90),
south=st.floats(allow_nan=False, allow_infinity=False, min_value=-90, max_value=90),
east=st.floats(allow_nan=False, allow_infinity=False, min_value=-180, max_value=180),
west=st.floats(allow_nan=False, allow_infinity=False, min_value=-180, max_value=180),
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
north=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90), | |
south=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90), | |
east=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180), | |
west=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180), | |
north=st.floats(allow_nan=False, allow_infinity=False, min_value=-90, max_value=90), | |
south=st.floats(allow_nan=False, allow_infinity=False, min_value=-90, max_value=90), | |
east=st.floats(allow_nan=False, allow_infinity=False, min_value=-180, max_value=180), | |
west=st.floats(allow_nan=False, allow_infinity=False, min_value=-180, max_value=180), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<kml:range>632.584179697442</kml:range> | ||
<kml:altitudeMode>absolute</kml:altitudeMode> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Documentation change to absolute
altitudeMode is inconsistent with implementation
The documentation change to use absolute
altitudeMode in the example doesn't align with the codebase implementation, where:
- The default altitudeMode across the codebase is
clampToGround
(seefastkml/views.py
,fastkml/geometry.py
, etc.) - Test cases primarily use
relativeToGround
orclampToGround
(seetests/views_test.py
,tests/overlays_test.py
) - The only usage of
absolute
mode is in specific test cases, not as a default or common pattern
The documentation should maintain consistency with the codebase's default behavior and common usage patterns.
🔗 Analysis chain
Verify altitudeMode documentation consistency with code changes.
The change from an unspecified previous value to absolute
in the documentation example needs verification to ensure it accurately reflects the current implementation in the views module.
Let's verify the altitudeMode implementation in the views module:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check the implementation of altitudeMode in view-related classes
# Test 1: Search for altitudeMode in view classes
rg -A 5 "altitudeMode" "src/**/views.py"
# Test 2: Search for altitude_mode attribute declarations
ast-grep --pattern 'class $_ {
$$$
altitude_mode: $_
$$$
}'
Length of output: 164
Script:
#!/bin/bash
# Let's try a broader search approach
# Search for any Python files containing altitudeMode
rg -t py "altitudeMode" -A 5
# Search for KML-related files that might contain the implementation
fd -e py -e pyx -e pxd | xargs rg "(?i)kml.*altitude"
# Look for any test files that might verify altitude mode behavior
fd -e py "test" | xargs rg "altitudeMode"
# Search for any configuration or constant definitions related to altitude modes
rg -t py "(?i)altitude.*mode.*=|ALTITUDE.*MODE"
Length of output: 45072
Summary by Sourcery
Remove the time_primitive attribute from view classes and refactor KmlDateTime for better date resolution handling. Add property-based tests for views and times modules using Hypothesis.
Enhancements:
Tests:
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Documentation
find
andfind_all
functions in thefastkml
library.Important
Add Hypothesis-based property tests for
times
andviews
modules, refactorKmlDateTime
, and remove unused attributes.time_primitive
attribute fromCamera
andLookAt
classes inviews.py
.KmlDateTime
intimes.py
for better date resolution handling.times
andviews
modules intimes_test.py
andviews_test.py
.kml_datetimes
strategy instrategies.py
for generating KML datetime objects.datetime.date
instead ofdatetime.datetime
for date handling.This description was created by for 36f0573. It will automatically update as commits are pushed.