Support for a nicer structure for ID maps (#12)

This adds support for a more expressive (albeit more verbose) IdentMap
structure. It makes it easier to annotate the structure with additional
data (such as names to associate with the IDs), to assist with
maintaining the IdentMap.
This commit is contained in:
Matthew 2017-02-19 00:58:23 +11:00 committed by Thor77
parent 2816c2ecfa
commit 5968dc31dd
4 changed files with 73 additions and 7 deletions

View File

@ -2,19 +2,40 @@ IdentMap
******** ********
An IdentMap is used to map multiple (U)ID's of one client to one client. An IdentMap is used to map multiple (U)ID's of one client to one client.
This can be useful, if a user creates multiple identities and you want to summarize all actions from all identities. This can be useful, if a user creates multiple identities and you want to summarize all actions from all identities.
To pass an IdentMap to TeamspeakStats, create your IdentMap as shown above and pass it to the cli::
tsstats --idmap <path to idmap.json>
TeamspeakStats' IdentMap-file is saved in json-format:: TeamspeakStats' IdentMap-file is saved in json-format::
[
{
"primary_id": "1",
"alternate_ids": ["2", "3", "4"]
}
]
If you would pass this IdentMap to TeamspeakStats and your log would contain entries for clients with id's 1, 2, 3 and 4,
your output will just show data for one client (1).
The format is flexible enough to support other arbitrary data to assist you in maintaining your IdentMap::
[
{
"name": "Friend 1",
"primary_id": "1",
"alternate_ids": ["2", "3", "4"]
}
]
The parser will ignore all nodes other than the "primary_id" and "alternate_ids" nodes, allowing you to use them for whatever you want.
The original IdentMap format is still supported:
{ {
'2': '1', '2': '1',
'3': '1', '3': '1',
'4': '1' '4': '1'
} }
While it is less expressive, it is also less verbose.
If you would pass this IdentMap to TeamspeakStats and your log would contain entries for clients with id's 1, 2, 3 and 4,
your output will just show data for one client (1).
To pass an IdentMap to TeamspeakStats, create your IdentMap as shown above and pass it to the cli::
tsstats --idmap <path to idmap.json>

View File

@ -9,6 +9,7 @@ from tsstats import config
from tsstats.exceptions import InvalidConfiguration from tsstats.exceptions import InvalidConfiguration
from tsstats.log import parse_logs from tsstats.log import parse_logs
from tsstats.template import render_servers from tsstats.template import render_servers
from tsstats.utils import transform_pretty_identmap
logger = logging.getLogger('tsstats') logger = logging.getLogger('tsstats')
@ -77,6 +78,8 @@ def main(configuration):
identmap = json.load(open(idmap)) identmap = json.load(open(idmap))
else: else:
identmap = None identmap = None
if isinstance(identmap, list):
identmap = transform_pretty_identmap(identmap)
log = configuration.get('General', 'log') log = configuration.get('General', 'log')
if not log: if not log:

View File

@ -1,6 +1,7 @@
import pytest import pytest
from tsstats.client import Client, Clients from tsstats.client import Client, Clients
from tsstats.utils import transform_pretty_identmap
@pytest.fixture(scope='module') @pytest.fixture(scope='module')
@ -24,3 +25,25 @@ def test_ident_map(identmap_clients):
assert clients['5'] == cl assert clients['5'] == cl
assert clients['UID1'] == uidcl assert clients['UID1'] == uidcl
assert clients['UID5'] == uidcl assert clients['UID5'] == uidcl
@pytest.mark.parametrize('test_input,expected', [
(
[
{'primary_id': '1', 'alternate_ids': ['3', '6']},
{'primary_id': '4', 'alternate_ids': ['9', '42', '23']}
],
(('3', '1'), ('6', '1'), ('9', '4'), ('42', '4'), ('23', '4'))
),
(
[
{'name': 'Friend 1', 'primary_id': '2', 'alternate_ids': ['4']},
{'name': 'Friend 3', 'primary_id': '8', 'alternate_ids': ['9', '14']}
],
(('4', '2'), ('9', '8'), ('14', '8'))
)
])
def test_transform_pretty_identmap(test_input, expected):
transformed_identmap = transform_pretty_identmap(test_input)
for alternate, primary in expected:
assert transformed_identmap[alternate] == primary

View File

@ -78,3 +78,22 @@ def tz_aware_datime(datetime, timezone=UTC()):
:type timezone: datetime.timezone :type timezone: datetime.timezone
''' '''
return datetime.replace(tzinfo=timezone) return datetime.replace(tzinfo=timezone)
def transform_pretty_identmap(pretty_identmap):
'''
Transforms a list of client ID mappings from a more descriptive format
to the traditional format of alternative IDs to actual ID.
:param pretty_identmap: ID mapping in "nice" form
:type pretty_identmap: list
:return: ID mapping in simple key/value pairs
:rtype: dict
'''
final_identmap = {}
for mapping in pretty_identmap:
for alt_id in mapping['alternate_ids']:
final_identmap[alt_id] = mapping['primary_id']
return final_identmap