Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 增加自动 uppercase unit 参数 #28

Merged
merged 1 commit into from
Jan 19, 2024
Merged
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
3 changes: 3 additions & 0 deletions outplan/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ def get_tracking_group(
if not unit:
unit = {"pdid": pdid, "user_id": user_id}.get(namespace_item.unit_type, "") # type: ignore

if namespace_item.auto_upper_unit:
unit = str(unit).upper()

if unit and allow_specify_group and callable(self._get_specified_group_func):
group = self._get_specified_group_func(
experiment_context, namespace_name, unit, user_id=user_id, pdid=pdid, **params
Expand Down
4 changes: 3 additions & 1 deletion outplan/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class NamespaceItem(object):
但如果多个实验影响同一个结果,则多个实验必须处于同一个 namespace
"""

def __init__(self, name, experiment_items, bucket=10, unit="unit", unit_type=""):
def __init__(self, name, experiment_items, bucket=10, unit="unit", unit_type="", auto_upper_unit=False):
if not all([name, experiment_items]):
raise ValueError("Namespace name and experiment_items required.")

Expand All @@ -113,6 +113,7 @@ def __init__(self, name, experiment_items, bucket=10, unit="unit", unit_type="")
self.bucket = bucket
self.unit = unit
self.unit_type = unit_type
self.auto_upper_unit = auto_upper_unit

self.validate()

Expand Down Expand Up @@ -246,6 +247,7 @@ def from_dict(cls, data, tag_filter_func=None):
bucket=int(data.get('bucket', 10)),
experiment_items=[ExperimentItem.from_dict(spec, tag_filter_func) for spec in data['experiment_items']],
unit_type=data.get('unit_type'),
auto_upper_unit=data.get('auto_upper_unit', False),
)


Expand Down
88 changes: 87 additions & 1 deletion tests/test_experiment.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# coding: utf-8
import random
import string
import time

from collections import defaultdict

import pytest
Expand Down Expand Up @@ -439,8 +442,56 @@ def tag_filter(experiment_name, tag_id, device_id, **ignored):
test_tag_namespace_spec_dict, tag_filter_func=tag_filter
)

AutoUpperUnitNamespace = NamespaceItem(
name="auto_upper_namespace1",
experiment_items=[
ExperimentItem(
name="auto_upper_experiment1",
bucket=9,
group_items=[
GroupItem(
name="auto_upper_group1",
weight=0.5,
),
GroupItem(
name="auto_upper_group2",
weight=0.5,
),
]
)
],
bucket=10,
unit_type="pdid",
auto_upper_unit=True
)

auto_upper_namespace_spec_dict = {
"name": "auto_upper_namespace2",
"experiment_items": [
{
"name": "auto_upper_experiment2",
"bucket": 9,
"group_items": [
{
"name": "auto_upper_group1",
"weight": 0.5,
},
{
"name": "auto_upper_group2",
"weight": 0.5,
},
]
},
],
"bucket": 10,
"unit_type": "pdid",
"auto_upper_unit": True
}

AutoUpperUnitNamespace2 = NamespaceItem.from_dict(auto_upper_namespace_spec_dict)

client = ExperimentGroupClient(
[HomepageNamespace, HomepageNamespace2, TestTagNamespace, TestTagNamespace2]
[HomepageNamespace, HomepageNamespace2, TestTagNamespace, TestTagNamespace2, AutoUpperUnitNamespace, AutoUpperUnitNamespace2]
)


Expand Down Expand Up @@ -656,3 +707,38 @@ def test_not_full_bucket_namespace_get_group():
while cnt <= 10 and namespace.get_group(unit="foo-{}".format(cnt)) is None:
cnt += 1
assert cnt <= 10


def test_auto_upper_unit_namespace():

def same_group(group_a, group_b):
if group_a is None and group_b is None:
return True
if group_a is None or group_b is None:
return False
return group_a.experiment_trace() == group_b.experiment_trace() and group_a.group_trace() == group_b.group_trace()

# test auto_upper_namespace1
assert same_group(client.get_tracking_group("auto_upper_namespace1", unit="abc-12345"),
client.get_tracking_group("auto_upper_namespace1", unit="ABC-12345"))

for _ in range(100):
rand_pdid = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
assert same_group(client.get_tracking_group("auto_upper_namespace1", unit=rand_pdid),
client.get_tracking_group("auto_upper_namespace1", unit=rand_pdid.upper()))

# test auto_upper_namespace2
assert same_group(client.get_tracking_group("auto_upper_namespace2", unit="abc-12345"),
client.get_tracking_group("auto_upper_namespace2", unit="ABC-12345"))

for _ in range(100):
rand_pdid = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
assert same_group(client.get_tracking_group("auto_upper_namespace2", unit=rand_pdid),
client.get_tracking_group("auto_upper_namespace2", unit=rand_pdid.upper()))

# test normal namespace
res = []
for _ in range(1000):
rand_pdid = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
res.append(same_group(client.get_tracking_group("namespace_1", unit=rand_pdid), client.get_tracking_group("namespace_1", unit=rand_pdid.upper())))
assert not all(res)
Loading