Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sarracenia/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def __repr__(self) -> str:
'post_documentRoot': None,
'post_baseDir': None,
'post_baseUrl': None,
'post_format': 'v03',
'post_format': None,
'realpathPost': False,
'recursive' : True,
'runStateThreshold_reject': 80,
Expand Down
8 changes: 6 additions & 2 deletions sarracenia/config/publisher.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,17 @@ def __init__(self, options ):
if hasattr(options,'tlsRigour') :
self['tlsRigour'] = options.tlsRigour

if hasattr(options,'post_format') :
if hasattr(options, 'post_format') and options.post_format is not None:
self['format'] = options.post_format
elif hasattr(options,'post_topicPrefix') and options.post_topicPrefix[0] in [ 'v02', 'v03' ]:
elif hasattr(options, 'post_topicPrefix') and options.post_topicPrefix \
and options.post_topicPrefix[0] in ['v02', 'v03']:
self['format'] = options.post_topicPrefix[0]
else:
self['format'] = 'v03'

# exportAny and exportMine expect 'post_format' in the options dict
self['post_format'] = self['format']

if hasattr(options,'post_topicPrefix') and options.post_topicPrefix:
self['topicPrefix'] = options.post_topicPrefix
elif hasattr(options, 'topicPrefix') and options.topicPrefix:
Expand Down
4 changes: 4 additions & 0 deletions sarracenia/moth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ def pubFactory(props) -> 'Moth':
props['broker'] = broker
if 'exchange' in publisher:
props['exchange'] = publisher['exchange']
if 'format' in publisher:
props['format'] = publisher['format']

elif not props['broker']:
logger.error('no broker specified')
Expand Down Expand Up @@ -347,6 +349,8 @@ def __init__(self, props=None, is_subscriber=True) -> None:
self.o['exchange'] = publisher['exchange']
if 'topicPrefix' in publisher:
self.o['topicPrefix'] = publisher['topicPrefix']
if 'format' in publisher:
self.o['format'] = publisher['format']

# apply settings from props.
if 'settings' in self.o:
Expand Down
105 changes: 105 additions & 0 deletions tests/sarracenia/config/publisher_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import pytest
from tests.conftest import *
from unittest.mock import MagicMock

from sarracenia.config.publisher import Publisher


def make_options(**overrides):
"""Minimal options object for Publisher."""
opts = MagicMock()
opts.post_broker = MagicMock()
opts.post_broker.url = MagicMock()
opts.post_broker.url.username = 'tsource'
opts.post_broker.url.scheme = 'amqp'
opts.post_exchange = ['xs_tsource']
opts.post_baseDir = '/tmp'
opts.post_baseUrl = 'http://localhost'
opts.post_exchangeSplit = 0

# defaults matching config/__init__.py
opts.post_format = None
opts.post_topicPrefix = ['v03', 'post']

for k, v in overrides.items():
setattr(opts, k, v)

return opts


def test_format_defaults_to_v03():
"""When neither post_format nor post_topicPrefix is set, default to v03."""
opts = make_options()
del opts.post_topicPrefix
del opts.post_format
pub = Publisher(opts)
assert pub['format'] == 'v03'
assert pub['post_format'] == 'v03'


def test_format_derived_from_v02_topicprefix():
"""post_topicPrefix v02.post should derive format v02.

This is the bug that Peter found -- post_format defaulted to 'v03'
which always took priority, so post_topicPrefix was never used.
"""
opts = make_options(post_topicPrefix=['v02', 'post'])
pub = Publisher(opts)
assert pub['format'] == 'v02'
assert pub['post_format'] == 'v02'


def test_format_derived_from_v03_topicprefix():
"""post_topicPrefix v03.post should derive format v03."""
opts = make_options(post_topicPrefix=['v03', 'post'])
pub = Publisher(opts)
assert pub['format'] == 'v03'
assert pub['post_format'] == 'v03'


def test_explicit_post_format_overrides_topicprefix():
"""If user explicitly sets post_format, it wins over topicPrefix."""
opts = make_options(
post_format='v03',
post_topicPrefix=['v02', 'post'],
)
pub = Publisher(opts)
assert pub['format'] == 'v03'
assert pub['post_format'] == 'v03'


def test_explicit_v02_post_format():
"""If user explicitly sets post_format v02, use it."""
opts = make_options(post_format='v02')
pub = Publisher(opts)
assert pub['format'] == 'v02'
assert pub['post_format'] == 'v02'


def test_topicprefix_fallback_is_empty_list():
"""When neither post_topicPrefix nor topicPrefix is set, fallback must
be [] (empty list), not None. Peter fixed this in bab4b9424 -- None
causes TypeError when downstream code iterates or concatenates."""
opts = make_options()
del opts.post_topicPrefix
del opts.topicPrefix
pub = Publisher(opts)
assert pub['topicPrefix'] == [], \
"topicPrefix fallback must be [] not None (see commit bab4b9424)"


def test_basedir_missing_no_keyerror():
"""Publisher must not raise KeyError when baseDir is absent from the
dict. The guard must use 'or' (short-circuit) not 'and'."""
opts = make_options(post_baseUrl='file:/data/incoming')
del opts.post_baseDir
# This must not raise KeyError
pub = Publisher(opts)
assert pub['baseDir'] == '/data/incoming'


def test_basedir_empty_string_derives_from_url():
"""When baseDir is set but empty, it should still derive from baseUrl."""
opts = make_options(post_baseDir='', post_baseUrl='file:/data/output')
pub = Publisher(opts)
assert pub['baseDir'] == '/data/output'
Loading