Skip to content

Commit

Permalink
feat(utils): add get_random_choice
Browse files Browse the repository at this point in the history
  • Loading branch information
jd authored and mergify[bot] committed Sep 30, 2020
1 parent 2e922cb commit d1a2809
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 2 deletions.
79 changes: 79 additions & 0 deletions mergify_engine/tests/unit/flycheck_test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#
# Copyright © 2019–2020 Mergify SAS
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import pytest

from mergify_engine import utils


def test_unicode_truncate():
s = "hé ho! how are you√2?"
assert utils.unicode_truncate(s, 0) == ""
assert utils.unicode_truncate(s, 1) == "h"
assert utils.unicode_truncate(s, 2) == "h"
assert utils.unicode_truncate(s, 3) == "hé"
assert utils.unicode_truncate(s, 4) == "hé "
assert utils.unicode_truncate(s, 10) == "hé ho! ho"
assert utils.unicode_truncate(s, 18) == "hé ho! how are yo"
assert utils.unicode_truncate(s, 19) == "hé ho! how are you"
assert utils.unicode_truncate(s, 20) == "hé ho! how are you"
assert utils.unicode_truncate(s, 21) == "hé ho! how are you"
assert utils.unicode_truncate(s, 22) == "hé ho! how are you√"
assert utils.unicode_truncate(s, 23) == "hé ho! how are you√2"
assert utils.unicode_truncate(s, 50) == s


def test_process_identifier():
assert isinstance(utils._PROCESS_IDENTIFIER, str)


def test_get_random_choices():
choices = {
"jd": 10,
"sileht": 1,
"foobar": 3,
}
assert utils.get_random_choices(0, choices, 1) == {"foobar"}
assert utils.get_random_choices(1, choices, 1) == {"foobar"}
assert utils.get_random_choices(2, choices, 1) == {"foobar"}
assert utils.get_random_choices(3, choices, 1) == {"jd"}
assert utils.get_random_choices(4, choices, 1) == {"jd"}
assert utils.get_random_choices(11, choices, 1) == {"jd"}
assert utils.get_random_choices(12, choices, 1) == {"jd"}
assert utils.get_random_choices(13, choices, 1) == {"sileht"}
assert utils.get_random_choices(14, choices, 1) == {"foobar"}
assert utils.get_random_choices(15, choices, 1) == {"foobar"}
assert utils.get_random_choices(16, choices, 1) == {"foobar"}
assert utils.get_random_choices(17, choices, 1) == {"jd"}
assert utils.get_random_choices(18, choices, 1) == {"jd"}
assert utils.get_random_choices(19, choices, 1) == {"jd"}
assert utils.get_random_choices(20, choices, 1) == {"jd"}
assert utils.get_random_choices(21, choices, 1) == {"jd"}
assert utils.get_random_choices(22, choices, 1) == {"jd"}
assert utils.get_random_choices(23, choices, 1) == {"jd"}
assert utils.get_random_choices(24, choices, 1) == {"jd"}
assert utils.get_random_choices(25, choices, 1) == {"jd"}
assert utils.get_random_choices(26, choices, 1) == {"jd"}
assert utils.get_random_choices(27, choices, 1) == {"sileht"}
assert utils.get_random_choices(28, choices, 1) == {"foobar"}
assert utils.get_random_choices(29, choices, 1) == {"foobar"}
assert utils.get_random_choices(30, choices, 1) == {"foobar"}
assert utils.get_random_choices(31, choices, 1) == {"jd"}
assert utils.get_random_choices(32, choices, 1) == {"jd"}
assert utils.get_random_choices(23, choices, 2) == {"sileht", "jd"}
assert utils.get_random_choices(2, choices, 2) == {"jd", "foobar"}
assert utils.get_random_choices(4, choices, 2) == {"jd", "foobar"}
assert utils.get_random_choices(0, choices, 3) == {"jd", "sileht", "foobar"}
with pytest.raises(ValueError):
assert utils.get_random_choices(4, choices, 4) == {"jd", "sileht"}
57 changes: 57 additions & 0 deletions mergify_engine/tests/unit/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
#
# Copyright © 2019–2020 Mergify SAS
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import pytest

from mergify_engine import utils


Expand All @@ -20,3 +36,44 @@ def test_unicode_truncate():

def test_process_identifier():
assert isinstance(utils._PROCESS_IDENTIFIER, str)


def test_get_random_choices():
choices = {
"jd": 10,
"sileht": 1,
"foobar": 3,
}
assert utils.get_random_choices(0, choices, 1) == {"foobar"}
assert utils.get_random_choices(1, choices, 1) == {"foobar"}
assert utils.get_random_choices(2, choices, 1) == {"foobar"}
assert utils.get_random_choices(3, choices, 1) == {"jd"}
assert utils.get_random_choices(4, choices, 1) == {"jd"}
assert utils.get_random_choices(11, choices, 1) == {"jd"}
assert utils.get_random_choices(12, choices, 1) == {"jd"}
assert utils.get_random_choices(13, choices, 1) == {"sileht"}
assert utils.get_random_choices(14, choices, 1) == {"foobar"}
assert utils.get_random_choices(15, choices, 1) == {"foobar"}
assert utils.get_random_choices(16, choices, 1) == {"foobar"}
assert utils.get_random_choices(17, choices, 1) == {"jd"}
assert utils.get_random_choices(18, choices, 1) == {"jd"}
assert utils.get_random_choices(19, choices, 1) == {"jd"}
assert utils.get_random_choices(20, choices, 1) == {"jd"}
assert utils.get_random_choices(21, choices, 1) == {"jd"}
assert utils.get_random_choices(22, choices, 1) == {"jd"}
assert utils.get_random_choices(23, choices, 1) == {"jd"}
assert utils.get_random_choices(24, choices, 1) == {"jd"}
assert utils.get_random_choices(25, choices, 1) == {"jd"}
assert utils.get_random_choices(26, choices, 1) == {"jd"}
assert utils.get_random_choices(27, choices, 1) == {"sileht"}
assert utils.get_random_choices(28, choices, 1) == {"foobar"}
assert utils.get_random_choices(29, choices, 1) == {"foobar"}
assert utils.get_random_choices(30, choices, 1) == {"foobar"}
assert utils.get_random_choices(31, choices, 1) == {"jd"}
assert utils.get_random_choices(32, choices, 1) == {"jd"}
assert utils.get_random_choices(23, choices, 2) == {"sileht", "jd"}
assert utils.get_random_choices(2, choices, 2) == {"jd", "foobar"}
assert utils.get_random_choices(4, choices, 2) == {"jd", "foobar"}
assert utils.get_random_choices(0, choices, 3) == {"jd", "sileht", "foobar"}
with pytest.raises(ValueError):
assert utils.get_random_choices(4, choices, 4) == {"jd", "sileht"}
42 changes: 40 additions & 2 deletions mergify_engine/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2019–2020 Mergify SAS
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
Expand All @@ -11,7 +12,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import asyncio
import datetime
import hashlib
Expand All @@ -21,6 +21,7 @@
import socket
import subprocess
import tempfile
import typing
import urllib.parse

import aredis
Expand Down Expand Up @@ -143,3 +144,40 @@ def add_cred(self, username, password, path):
parsed[2] = path
url = urllib.parse.urlunparse(parsed)
self("credential", "approve", input=f"url={url}\n\n".encode("utf8"))


def get_random_choices(
random_number: int, population: typing.Dict[typing.Any, int], k: int = 1
) -> set:
"""Return a random number of item from a population without replacement.
You need to provide the random number yourself.
The output is always the same based on that number.
The population is a dict where the key is the choice and the value is the weight.
The argument k is the number of item that should be picked.
:param random_number: The random_number that should be picked.
:param population: The dict of {item: weight}.
:param k: The number of choices to make.
:return: A set with the choices.
"""
picked = set()
population = population.copy()

if k > len(population):
raise ValueError("k cannot be greater than the population size")

while len(picked) < k:
total_weight = sum(population.values())
choice_index = (random_number % total_weight) + 1
for item in sorted(population):
choice_index -= population[item]
if choice_index <= 0:
picked.add(item)
del population[item]
break

return picked

0 comments on commit d1a2809

Please sign in to comment.