fix: Make description field optional in ad_defaults

The description field in the main configuration (ad_defaults) is now optional.
Previously, the bot would fail if no description or affixes were provided in
the main configuration. This change addresses issue #435.

Changes:
- Add fallback to empty string ("") when all description prefix/suffix sources
  are None in __get_description_with_affixes method
- Add comprehensive test suite for description handling in test_init.py
- Fix coverage path in pyproject.toml from 'kleinanzeigen_bot' to
  'src/kleinanzeigen_bot'

New tests cover:
- Description handling without main config description
- New format affixes in configuration
- Mixed old/new format affixes
- Ad-level affix precedence
- None value handling in affixes
- Email address @ symbol replacement

This change maintains backward compatibility while making the description
field optional in the main configuration, improving flexibility for users.
This commit is contained in:
Jens Bergmann
2025-02-17 20:34:53 +01:00
committed by Sebastian Thomschke
parent a8f6817c5c
commit c7f7b832b2
3 changed files with 119 additions and 2 deletions

View File

@@ -253,7 +253,7 @@ addopts = """
--ignore=data
--ignore=dist
--ignore=src/kleinanzeigen_bot/__main__.py
--cov=kleinanzeigen_bot
--cov=src/kleinanzeigen_bot
--cov-report=term-missing
"""
markers = [

View File

@@ -1080,6 +1080,7 @@ class KleinanzeigenBot(WebScrapingMixin):
if dicts.safe_get(ad_cfg, "description", "prefix") is not None
# 3. Global prefix from config
else get_description_affixes(self.config, prefix=True)
or "" # Default to empty string if all sources are None
)
# Get suffix with precedence
@@ -1091,6 +1092,7 @@ class KleinanzeigenBot(WebScrapingMixin):
if dicts.safe_get(ad_cfg, "description", "suffix") is not None
# 3. Global suffix from config
else get_description_affixes(self.config, prefix=False)
or "" # Default to empty string if all sources are None
)
# Combine the parts and replace @ with (at)

View File

@@ -1065,3 +1065,118 @@ class TestKleinanzeigenBotPrefixSuffix:
assert "Length of ad description including prefix and suffix exceeds 4000 chars" in str(exc_info.value)
assert "Description length: 4001" in str(exc_info.value)
class TestKleinanzeigenBotDescriptionHandling:
"""Tests for description handling functionality."""
def test_description_without_main_config_description(self, test_bot: KleinanzeigenBot) -> None:
"""Test that description works correctly when description is missing from main config."""
# Set up config without any description fields
test_bot.config = {
'ad_defaults': {
# No description field at all
}
}
# Test with a simple ad config
ad_cfg = {
"description": "Test Description",
"active": True
}
# The description should be returned as-is without any prefix/suffix
description = getattr(test_bot, "_KleinanzeigenBot__get_description_with_affixes")(ad_cfg)
assert description == "Test Description"
def test_description_with_only_new_format_affixes(self, test_bot: KleinanzeigenBot) -> None:
"""Test that description works with only new format affixes in config."""
test_bot.config = {
'ad_defaults': {
'description_prefix': 'Prefix: ',
'description_suffix': ' :Suffix'
}
}
ad_cfg = {
"description": "Test Description",
"active": True
}
description = getattr(test_bot, "_KleinanzeigenBot__get_description_with_affixes")(ad_cfg)
assert description == "Prefix: Test Description :Suffix"
def test_description_with_mixed_config_formats(self, test_bot: KleinanzeigenBot) -> None:
"""Test that description works with both old and new format affixes in config."""
test_bot.config = {
'ad_defaults': {
'description_prefix': 'New Prefix: ',
'description_suffix': ' :New Suffix',
'description': {
'prefix': 'Old Prefix: ',
'suffix': ' :Old Suffix'
}
}
}
ad_cfg = {
"description": "Test Description",
"active": True
}
description = getattr(test_bot, "_KleinanzeigenBot__get_description_with_affixes")(ad_cfg)
assert description == "New Prefix: Test Description :New Suffix"
def test_description_with_ad_level_affixes(self, test_bot: KleinanzeigenBot) -> None:
"""Test that ad-level affixes take precedence over config affixes."""
test_bot.config = {
'ad_defaults': {
'description_prefix': 'Config Prefix: ',
'description_suffix': ' :Config Suffix'
}
}
ad_cfg = {
"description": "Test Description",
"description_prefix": "Ad Prefix: ",
"description_suffix": " :Ad Suffix",
"active": True
}
description = getattr(test_bot, "_KleinanzeigenBot__get_description_with_affixes")(ad_cfg)
assert description == "Ad Prefix: Test Description :Ad Suffix"
def test_description_with_none_values(self, test_bot: KleinanzeigenBot) -> None:
"""Test that None values in affixes are handled correctly."""
test_bot.config = {
'ad_defaults': {
'description_prefix': None,
'description_suffix': None,
'description': {
'prefix': None,
'suffix': None
}
}
}
ad_cfg = {
"description": "Test Description",
"active": True
}
description = getattr(test_bot, "_KleinanzeigenBot__get_description_with_affixes")(ad_cfg)
assert description == "Test Description"
def test_description_with_email_replacement(self, test_bot: KleinanzeigenBot) -> None:
"""Test that @ symbols in description are replaced with (at)."""
test_bot.config = {
'ad_defaults': {}
}
ad_cfg = {
"description": "Contact: test@example.com",
"active": True
}
description = getattr(test_bot, "_KleinanzeigenBot__get_description_with_affixes")(ad_cfg)
assert description == "Contact: test(at)example.com"