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
53 changes: 45 additions & 8 deletions did/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,12 @@ class User():

some@email.org; bz: bugzilla@email.org; gh: githublogin

By default, the alias type is autodetected based on the presence of
"@" character (email if present, login otherwise). However, you can
explicitly specify the alias type using the extended syntax::

some@email.org; jira.login: user@example.com; gh.email: user

Use config section name to identify stats where given alias should
be used. The exactly same syntax can be used both in the config file
and on the command line. Finally it's also possible to include the
Expand Down Expand Up @@ -469,16 +475,47 @@ def alias(self, aliases, stats):
# Check for aliases specified in the email string
if aliases is not None:
try:
aliases = dict([
re.split(r"\s*:\s*", definition, maxsplit=1)
for definition in re.split(r"\s*;\s*", aliases.strip())])
explicit_aliases = {} # For stats.type: value format
implicit_aliases = {} # For stats: value format

for definition in re.split(r"\s*;\s*", aliases.strip()):
parts = re.split(r"\s*:\s*", definition, 1)
if len(parts) != 2:
raise ValueError(f"Invalid alias format: '{definition}'")

key, value = parts

# Check if key contains type specification
# (e.g., "jira.login")
if "." in key:
stats_name, alias_type = key.split(".", 1)
if alias_type not in ("email", "login"):
raise ValueError(f"Invalid alias type '{alias_type}', "
"must be 'email' or 'login'")
if stats_name not in explicit_aliases:
explicit_aliases[stats_name] = {}
explicit_aliases[stats_name][alias_type] = value
else:
# Standard format: stats: value
# (autodetect type)
implicit_aliases[key] = value

# Apply explicit aliases first
if stats in explicit_aliases:
if "email" in explicit_aliases[stats]:
email = explicit_aliases[stats]["email"]
if "login" in explicit_aliases[stats]:
login = explicit_aliases[stats]["login"]
# Then apply implicit aliases
# (only if no explicit alias found)
elif stats in implicit_aliases:
if "@" in implicit_aliases[stats]:
email = implicit_aliases[stats]
else:
login = implicit_aliases[stats]

except ValueError as exc:
raise ConfigError(f"Invalid alias definition: '{aliases}'") from exc
if stats in aliases:
if "@" in aliases[stats]:
email = aliases[stats]
else:
login = aliases[stats]
# Update login/email if alias detected
if email is not None:
self.email = email
Expand Down
47 changes: 47 additions & 0 deletions tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,53 @@ def test_user_class():
clone = user.clone("bz")
assert clone.login == "bzlogin"

# Explicit email alias type
user = did.base.User("some@email.org; jira.email: jirauser", stats="jira")
assert user.email == "jirauser"
assert user.login == "jirauser" # should update login from email

# Explicit login alias type
user = did.base.User("some@email.org; jira.login: user@example.com", stats="jira")
assert user.login == "user@example.com"
assert user.email == "some@email.org" # original email unchanged

# Invalid alias type
with pytest.raises(did.base.ConfigError, match="Invalid alias definition"):
did.base.User("some@email.org; jira.invalid: value", stats="jira")

# Invalid alias format (missing colon)
with pytest.raises(did.base.ConfigError, match="Invalid alias definition"):
did.base.User("some@email.org; jira.login value", stats="jira")

# Case sensitive alias types - uppercase should fail
with pytest.raises(did.base.ConfigError, match="Invalid alias definition"):
did.base.User("some@email.org; jira.EMAIL: jirauser", stats="jira")

with pytest.raises(did.base.ConfigError, match="Invalid alias definition"):
did.base.User("some@email.org; jira.LOGIN: user@example.com", stats="jira")

# Both login and email aliases for the same stats service on same
# line When both are defined, both should be applied
user = did.base.User(
"some@email.org; jira.login: jirauser; jira.email: jira@example.com",
stats="jira")
assert user.login == "jirauser"
assert user.email == "jira@example.com"

# Test different order - email first, then login
user = did.base.User(
"some@email.org; jira.email: jira@example.com; jira.login: jirauser",
stats="jira")
assert user.login == "jirauser"
assert user.email == "jira@example.com"

# Explicit aliases take precedence over implicit ones
user = did.base.User(
"some@email.org; jira: implicit_value; jira.login: explicit_login",
stats="jira")
assert user.login == "explicit_login"
assert user.email == "some@email.org" # original email unchanged


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Exceptions
Expand Down
Loading