Ruff fixes
This commit is contained in:
+66
-91
@@ -8,19 +8,22 @@ Updated for Phase 4.1 - Pydantic models integration.
|
||||
"""
|
||||
|
||||
import json
|
||||
import pytest
|
||||
from unittest.mock import Mock, patch
|
||||
from unittest.mock import patch
|
||||
|
||||
from nadlan_mcp import fastmcp_server
|
||||
from nadlan_mcp.govmap.models import (
|
||||
Deal, AutocompleteResponse, AutocompleteResult, CoordinatePoint,
|
||||
DealStatistics, MarketActivityScore, InvestmentAnalysis, LiquidityMetrics
|
||||
AutocompleteResponse,
|
||||
AutocompleteResult,
|
||||
CoordinatePoint,
|
||||
Deal,
|
||||
DealStatistics,
|
||||
)
|
||||
|
||||
|
||||
class TestAutocompleteAddress:
|
||||
"""Test autocomplete_address MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_autocomplete(self, mock_client):
|
||||
"""Test successful address autocomplete with correct field mapping."""
|
||||
# Now returns AutocompleteResponse model
|
||||
@@ -33,7 +36,7 @@ class TestAutocompleteAddress:
|
||||
type="address",
|
||||
score=100,
|
||||
coordinates=CoordinatePoint(longitude=180000.5, latitude=650000.3),
|
||||
shape="POINT(180000.5 650000.3)"
|
||||
shape="POINT(180000.5 650000.3)",
|
||||
),
|
||||
AutocompleteResult(
|
||||
id="address|ADDR|124",
|
||||
@@ -41,9 +44,9 @@ class TestAutocompleteAddress:
|
||||
type="address",
|
||||
score=95,
|
||||
coordinates=CoordinatePoint(longitude=180010.2, latitude=650005.7),
|
||||
shape="POINT(180010.2 650005.7)"
|
||||
)
|
||||
]
|
||||
shape="POINT(180010.2 650005.7)",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
result = fastmcp_server.autocomplete_address("דיזנגוף תל אביב")
|
||||
@@ -56,20 +59,19 @@ class TestAutocompleteAddress:
|
||||
assert parsed[0]["coordinates"]["longitude"] == 180000.5
|
||||
assert parsed[0]["coordinates"]["latitude"] == 650000.3
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_autocomplete_no_results(self, mock_client):
|
||||
"""Test autocomplete with no results."""
|
||||
# Now returns AutocompleteResponse model
|
||||
mock_client.autocomplete_address.return_value = AutocompleteResponse(
|
||||
resultsCount=0,
|
||||
results=[]
|
||||
resultsCount=0, results=[]
|
||||
)
|
||||
|
||||
result = fastmcp_server.autocomplete_address("nonexistent address")
|
||||
# With empty results, returns a message string
|
||||
assert "No addresses found" in result
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_autocomplete_invalid_coordinates(self, mock_client):
|
||||
"""Test autocomplete with invalid/missing coordinate format."""
|
||||
# Now returns AutocompleteResponse model with result that has no coordinates
|
||||
@@ -82,9 +84,9 @@ class TestAutocompleteAddress:
|
||||
type="address",
|
||||
score=100,
|
||||
coordinates=None, # No coordinates parsed
|
||||
shape="INVALID_FORMAT"
|
||||
shape="INVALID_FORMAT",
|
||||
)
|
||||
]
|
||||
],
|
||||
)
|
||||
|
||||
result = fastmcp_server.autocomplete_address("test")
|
||||
@@ -93,7 +95,7 @@ class TestAutocompleteAddress:
|
||||
assert len(parsed) == 1
|
||||
assert parsed[0]["text"] == "דיזנגוף 50"
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_autocomplete_missing_shape(self, mock_client):
|
||||
"""Test autocomplete with missing shape field."""
|
||||
# Mock with AutocompleteResponse model
|
||||
@@ -105,9 +107,9 @@ class TestAutocompleteAddress:
|
||||
text="דיזנגוף 50",
|
||||
type="address",
|
||||
score=100,
|
||||
coordinates=None # No coordinates
|
||||
coordinates=None, # No coordinates
|
||||
)
|
||||
]
|
||||
],
|
||||
)
|
||||
|
||||
result = fastmcp_server.autocomplete_address("test")
|
||||
@@ -115,7 +117,7 @@ class TestAutocompleteAddress:
|
||||
# When coordinates are None, the field isn't included in the response
|
||||
assert "coordinates" not in parsed[0]
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_autocomplete_error_handling(self, mock_client):
|
||||
"""Test autocomplete error handling."""
|
||||
mock_client.autocomplete_address.side_effect = Exception("API Error")
|
||||
@@ -128,7 +130,7 @@ class TestAutocompleteAddress:
|
||||
class TestGetDealsByRadius:
|
||||
"""Test get_deals_by_radius MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_get_deals(self, mock_client):
|
||||
"""Test successful polygon metadata retrieval."""
|
||||
# Mock with polygon metadata dicts (not Deal objects)
|
||||
@@ -139,7 +141,7 @@ class TestGetDealsByRadius:
|
||||
"settlementNameHeb": "תל אביב-יפו",
|
||||
"streetNameHeb": "דיזנגוף",
|
||||
"houseNum": 50,
|
||||
"polygon_id": "123-456"
|
||||
"polygon_id": "123-456",
|
||||
}
|
||||
]
|
||||
mock_client.get_deals_by_radius.return_value = mock_polygons
|
||||
@@ -152,7 +154,7 @@ class TestGetDealsByRadius:
|
||||
assert parsed["total_polygons"] == 1
|
||||
mock_client.get_deals_by_radius.assert_called_once()
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_get_deals_no_results(self, mock_client):
|
||||
"""Test polygon metadata retrieval with no results."""
|
||||
mock_client.get_deals_by_radius.return_value = []
|
||||
@@ -160,7 +162,7 @@ class TestGetDealsByRadius:
|
||||
result = fastmcp_server.get_deals_by_radius(650000.0, 180000.0, 500)
|
||||
assert "No polygons found" in result
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_get_deals_strips_bloat_fields(self, mock_client):
|
||||
"""Test that polygon metadata is returned as-is."""
|
||||
# Mock with polygon metadata dicts
|
||||
@@ -169,7 +171,7 @@ class TestGetDealsByRadius:
|
||||
"objectid": 123,
|
||||
"dealscount": "10",
|
||||
"polygon_id": "abc123",
|
||||
"settlementNameHeb": "Tel Aviv"
|
||||
"settlementNameHeb": "Tel Aviv",
|
||||
}
|
||||
]
|
||||
mock_client.get_deals_by_radius.return_value = mock_polygons
|
||||
@@ -182,7 +184,7 @@ class TestGetDealsByRadius:
|
||||
assert polygon["polygon_id"] == "abc123"
|
||||
assert polygon["dealscount"] == "10"
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_get_deals_error_handling(self, mock_client):
|
||||
"""Test error handling for deal retrieval."""
|
||||
mock_client.get_deals_by_radius.side_effect = ValueError("Invalid coordinates")
|
||||
@@ -194,7 +196,7 @@ class TestGetDealsByRadius:
|
||||
class TestFindRecentDealsForAddress:
|
||||
"""Test find_recent_deals_for_address MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_find_deals(self, mock_client):
|
||||
"""Test successful deal finding with statistics."""
|
||||
# Mock with Deal models
|
||||
@@ -204,21 +206,19 @@ class TestFindRecentDealsForAddress:
|
||||
deal_amount=2000000,
|
||||
deal_date="2023-01-01",
|
||||
asset_area=80.0,
|
||||
priority=0
|
||||
priority=0,
|
||||
),
|
||||
Deal(
|
||||
objectid=124,
|
||||
deal_amount=1800000,
|
||||
deal_date="2023-01-02",
|
||||
asset_area=70.0,
|
||||
priority=1
|
||||
)
|
||||
priority=1,
|
||||
),
|
||||
]
|
||||
mock_client.find_recent_deals_for_address.return_value = mock_deals
|
||||
|
||||
result = fastmcp_server.find_recent_deals_for_address(
|
||||
"דיזנגוף 50 תל אביב", 2, 100, 100
|
||||
)
|
||||
result = fastmcp_server.find_recent_deals_for_address("דיזנגוף 50 תל אביב", 2, 100, 100)
|
||||
parsed = json.loads(result)
|
||||
|
||||
assert "search_parameters" in parsed
|
||||
@@ -227,20 +227,18 @@ class TestFindRecentDealsForAddress:
|
||||
assert len(parsed["deals"]) == 2
|
||||
assert parsed["market_statistics"]["deal_breakdown"]["total_deals"] == 2
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_find_deals_no_results(self, mock_client):
|
||||
"""Test deal finding with no results."""
|
||||
mock_client.find_recent_deals_for_address.return_value = []
|
||||
|
||||
result = fastmcp_server.find_recent_deals_for_address(
|
||||
"nonexistent address", 2, 100, 100
|
||||
)
|
||||
result = fastmcp_server.find_recent_deals_for_address("nonexistent address", 2, 100, 100)
|
||||
|
||||
# When no deals, returns a text message, not JSON
|
||||
assert "No second hand (used) deals found" in result
|
||||
assert "nonexistent address" in result
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_find_deals_strips_bloat(self, mock_client):
|
||||
"""Test that bloat fields are stripped."""
|
||||
# Mock with Deal models
|
||||
@@ -250,14 +248,12 @@ class TestFindRecentDealsForAddress:
|
||||
deal_amount=2000000,
|
||||
deal_date="2023-01-01",
|
||||
shape="MULTIPOLYGON(...)",
|
||||
sourceorder=1
|
||||
sourceorder=1,
|
||||
)
|
||||
]
|
||||
mock_client.find_recent_deals_for_address.return_value = mock_deals
|
||||
|
||||
result = fastmcp_server.find_recent_deals_for_address(
|
||||
"test address", 2, 100, 100
|
||||
)
|
||||
result = fastmcp_server.find_recent_deals_for_address("test address", 2, 100, 100)
|
||||
parsed = json.loads(result)
|
||||
|
||||
assert "shape" not in parsed["deals"][0]
|
||||
@@ -267,7 +263,7 @@ class TestFindRecentDealsForAddress:
|
||||
class TestAnalyzeMarketTrends:
|
||||
"""Test analyze_market_trends MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_market_analysis(self, mock_client):
|
||||
"""Test successful market trend analysis."""
|
||||
# Mock with Deal models
|
||||
@@ -279,7 +275,7 @@ class TestAnalyzeMarketTrends:
|
||||
asset_area=80.0,
|
||||
property_type_description="דירה",
|
||||
neighborhood="תל אביב",
|
||||
priority=1
|
||||
priority=1,
|
||||
)
|
||||
]
|
||||
mock_client.find_recent_deals_for_address.return_value = mock_deals
|
||||
@@ -292,7 +288,7 @@ class TestAnalyzeMarketTrends:
|
||||
assert "yearly_trends" in parsed
|
||||
assert "top_property_types" in parsed
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_market_analysis_no_data(self, mock_client):
|
||||
"""Test market analysis with no data."""
|
||||
mock_client.find_recent_deals_for_address.return_value = []
|
||||
@@ -307,25 +303,23 @@ class TestAnalyzeMarketTrends:
|
||||
class TestCompareAddresses:
|
||||
"""Test compare_addresses MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_comparison(self, mock_client):
|
||||
"""Test successful address comparison."""
|
||||
# Mock different deals for each address
|
||||
mock_client.find_recent_deals_for_address.side_effect = [
|
||||
[{"dealAmount": 2000000, "assetArea": 80, "price_per_sqm": 25000}],
|
||||
[{"dealAmount": 1500000, "assetArea": 60, "price_per_sqm": 25000}]
|
||||
[{"dealAmount": 1500000, "assetArea": 60, "price_per_sqm": 25000}],
|
||||
]
|
||||
|
||||
result = fastmcp_server.compare_addresses(
|
||||
["דיזנגוף 50 תל אביב", "הרצל 1 חולון"]
|
||||
)
|
||||
result = fastmcp_server.compare_addresses(["דיזנגוף 50 תל אביב", "הרצל 1 חולון"])
|
||||
parsed = json.loads(result)
|
||||
|
||||
assert "addresses_compared" in parsed
|
||||
assert parsed["addresses_compared"] == 2
|
||||
assert "all_results" in parsed
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_comparison_error_handling(self, mock_client):
|
||||
"""Test error handling in address comparison."""
|
||||
mock_client.find_recent_deals_for_address.side_effect = ValueError("Invalid address")
|
||||
@@ -340,10 +334,10 @@ class TestCompareAddresses:
|
||||
class TestGetValuationComparables:
|
||||
"""Test get_valuation_comparables MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_get_comparables(self, mock_client):
|
||||
"""Test successful comparable retrieval with filtering."""
|
||||
from nadlan_mcp.govmap.models import DealStatistics
|
||||
|
||||
# Mock with Deal models
|
||||
mock_deals = [
|
||||
Deal(
|
||||
@@ -352,24 +346,21 @@ class TestGetValuationComparables:
|
||||
deal_date="2023-01-01",
|
||||
asset_area=80.0,
|
||||
rooms=3.0,
|
||||
property_type_description="דירה"
|
||||
property_type_description="דירה",
|
||||
)
|
||||
]
|
||||
mock_stats = DealStatistics(
|
||||
total_deals=1,
|
||||
price_statistics={"mean": 2000000},
|
||||
area_statistics={"mean": 80},
|
||||
price_per_sqm_statistics={"mean": 25000}
|
||||
price_per_sqm_statistics={"mean": 25000},
|
||||
)
|
||||
mock_client.find_recent_deals_for_address.return_value = mock_deals
|
||||
mock_client.filter_deals_by_criteria.return_value = mock_deals
|
||||
mock_client.calculate_deal_statistics.return_value = mock_stats
|
||||
|
||||
result = fastmcp_server.get_valuation_comparables(
|
||||
"דיזנגוף 50 תל אביב",
|
||||
property_type="דירה",
|
||||
min_rooms=2,
|
||||
max_rooms=4
|
||||
"דיזנגוף 50 תל אביב", property_type="דירה", min_rooms=2, max_rooms=4
|
||||
)
|
||||
parsed = json.loads(result)
|
||||
|
||||
@@ -378,10 +369,10 @@ class TestGetValuationComparables:
|
||||
assert "comparables" in parsed
|
||||
assert parsed["filters_applied"]["property_type"] == "דירה"
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_comparables_strips_bloat(self, mock_client):
|
||||
"""Test that bloat fields are stripped from comparables."""
|
||||
from nadlan_mcp.govmap.models import DealStatistics
|
||||
|
||||
# Mock with Deal models
|
||||
mock_deals = [
|
||||
Deal(
|
||||
@@ -390,13 +381,10 @@ class TestGetValuationComparables:
|
||||
deal_date="2023-01-01",
|
||||
shape="MULTIPOLYGON(...)",
|
||||
sourceorder=1,
|
||||
source_polygon_id="abc"
|
||||
source_polygon_id="abc",
|
||||
)
|
||||
]
|
||||
mock_stats = DealStatistics(
|
||||
total_deals=1,
|
||||
price_statistics={"mean": 2000000}
|
||||
)
|
||||
mock_stats = DealStatistics(total_deals=1, price_statistics={"mean": 2000000})
|
||||
mock_client.find_recent_deals_for_address.return_value = mock_deals
|
||||
mock_client.filter_deals_by_criteria.return_value = mock_deals
|
||||
mock_client.calculate_deal_statistics.return_value = mock_stats
|
||||
@@ -413,23 +401,18 @@ class TestGetValuationComparables:
|
||||
class TestGetDealStatistics:
|
||||
"""Test get_deal_statistics MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_statistics_calculation(self, mock_client):
|
||||
"""Test successful statistics calculation."""
|
||||
from nadlan_mcp.govmap.models import DealStatistics
|
||||
|
||||
# Mock with Deal models
|
||||
mock_deals = [
|
||||
Deal(objectid=1, deal_amount=2000000, deal_date="2023-01-01", asset_area=80.0),
|
||||
Deal(objectid=2, deal_amount=1800000, deal_date="2023-01-02", asset_area=70.0)
|
||||
Deal(objectid=2, deal_amount=1800000, deal_date="2023-01-02", asset_area=70.0),
|
||||
]
|
||||
mock_stats = DealStatistics(
|
||||
total_deals=2,
|
||||
price_statistics={
|
||||
"mean": 1900000,
|
||||
"median": 1900000,
|
||||
"min": 1800000,
|
||||
"max": 2000000
|
||||
}
|
||||
price_statistics={"mean": 1900000, "median": 1900000, "min": 1800000, "max": 2000000},
|
||||
)
|
||||
mock_client.find_recent_deals_for_address.return_value = mock_deals
|
||||
mock_client.filter_deals_by_criteria.return_value = mock_deals
|
||||
@@ -446,28 +429,24 @@ class TestGetDealStatistics:
|
||||
class TestGetMarketActivityMetrics:
|
||||
"""Test get_market_activity_metrics MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_activity_metrics(self, mock_client):
|
||||
"""Test successful market activity calculation."""
|
||||
mock_deals = [
|
||||
{
|
||||
"dealDate": "2024-01-15T00:00:00.000Z",
|
||||
"dealAmount": 2000000,
|
||||
"assetArea": 80
|
||||
}
|
||||
{"dealDate": "2024-01-15T00:00:00.000Z", "dealAmount": 2000000, "assetArea": 80}
|
||||
]
|
||||
mock_client.find_recent_deals_for_address.return_value = mock_deals
|
||||
mock_client.calculate_market_activity_score.return_value = {
|
||||
"activity_score": 75,
|
||||
"activity_level": "high"
|
||||
"activity_level": "high",
|
||||
}
|
||||
mock_client.get_market_liquidity.return_value = {
|
||||
"velocity_score": 8.5,
|
||||
"liquidity_rating": "high"
|
||||
"liquidity_rating": "high",
|
||||
}
|
||||
mock_client.analyze_investment_potential.return_value = {
|
||||
"investment_score": 80,
|
||||
"recommendation": "positive"
|
||||
"recommendation": "positive",
|
||||
}
|
||||
|
||||
result = fastmcp_server.get_market_activity_metrics("test address")
|
||||
@@ -481,13 +460,11 @@ class TestGetMarketActivityMetrics:
|
||||
class TestGetStreetDeals:
|
||||
"""Test get_street_deals MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_street_deals(self, mock_client):
|
||||
"""Test successful street deal retrieval."""
|
||||
# Mock with Deal models
|
||||
mock_deals = [
|
||||
Deal(objectid=123, deal_amount=2000000, deal_date="2023-01-01")
|
||||
]
|
||||
mock_deals = [Deal(objectid=123, deal_amount=2000000, deal_date="2023-01-01")]
|
||||
mock_client.get_street_deals.return_value = mock_deals
|
||||
|
||||
result = fastmcp_server.get_street_deals("12345", 100)
|
||||
@@ -500,13 +477,11 @@ class TestGetStreetDeals:
|
||||
class TestGetNeighborhoodDeals:
|
||||
"""Test get_neighborhood_deals MCP tool."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
@patch("nadlan_mcp.fastmcp_server.client")
|
||||
def test_successful_neighborhood_deals(self, mock_client):
|
||||
"""Test successful neighborhood deal retrieval."""
|
||||
# Mock with Deal models
|
||||
mock_deals = [
|
||||
Deal(objectid=123, deal_amount=2000000, deal_date="2023-01-01")
|
||||
]
|
||||
mock_deals = [Deal(objectid=123, deal_amount=2000000, deal_date="2023-01-01")]
|
||||
mock_client.get_neighborhood_deals.return_value = mock_deals
|
||||
|
||||
result = fastmcp_server.get_neighborhood_deals("12345", 100)
|
||||
|
||||
Reference in New Issue
Block a user