Skip to content

Commit 871f742

Browse files
Work on automatic label generation (#6)
* add * Update paths.py * lets see * Revert "lets see" This reverts commit 7633fac. * Revert "Revert "lets see"" This reverts commit 5238e6a. * Update paths.py * Update paths.py * add * Update guess_label_size.py add Update guess_label_size.py Update guess_label_size.py Update guess_label_size.py add * Update guess_label_size.py add Update guess_label_size.py Update guess_label_size.py Update guess_label_size.py add * Update paths.py * Update paths.py * Update paths.py * Update paths.py * Update paths.py * Update paths.py * Update paths.py Update paths.py * Update paths.py * Update paths.py * Update paths.py * add add Update test_label_generation.py
1 parent 518ef2d commit 871f742

File tree

8 files changed

+211
-122
lines changed

8 files changed

+211
-122
lines changed

django_ltree/managers.py

-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ def create_child(self, parent=None, **kwargs):
2727
path_generator = PathGenerator(
2828
prefix,
2929
skip=paths_in_use.values_list("path", flat=True),
30-
label_size=getattr(self.model, "label_size"),
3130
)
3231
kwargs["path"] = path_generator.next()
3332
return self.create(**kwargs)

django_ltree/paths.py

+36-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
import string
2+
import math
23
from itertools import product
34

4-
from django_ltree.fields import PathValue
5+
from .fields import PathValue
56

67

78
class PathGenerator(object):
8-
_default_label_size = 6 # Postgres limits this to 256
9+
def __init__(self, prefix=None, skip=None):
10+
combinations = string.digits + string.ascii_letters
911

10-
def __init__(self, prefix=None, skip=None, label_size=None):
1112
self.skip_paths = [] if skip is None else skip[:]
1213
self.path_prefix = prefix if prefix else []
1314
self.product_iterator = product(
14-
string.digits + string.ascii_letters,
15-
repeat=label_size or self._default_label_size,
15+
combinations,
16+
repeat=self.guess_the_label_size(
17+
path_size=len(self.skip_paths), combination_size=len(combinations)
18+
),
1619
)
1720

1821
def __iter__(self):
@@ -26,3 +29,31 @@ def __next__(self):
2629
return path
2730

2831
next = __next__
32+
33+
@staticmethod
34+
def guess_the_label_size(path_size: int, combination_size: int) -> int:
35+
# The theoritical limit for this at the time of writing is 2_538_557_185_841_324_496 (python 3.12.2)
36+
calculated_path_size = -1 # -1 is here for 0th index items
37+
# The theoritical limit for this at the time of writing is 32 (python 3.12.2)
38+
label_size = 0
39+
40+
# THIS IS AN VERY IMPORTANT CHECK
41+
last = 0
42+
43+
while True:
44+
possible_cominations = math.comb(combination_size, label_size)
45+
if last > possible_cominations:
46+
raise ValueError("We approached the limit of `math.comb`")
47+
48+
last = possible_cominations
49+
calculated_path_size += possible_cominations
50+
51+
if calculated_path_size > path_size and label_size != 0:
52+
break
53+
54+
label_size += 1
55+
56+
return label_size
57+
58+
59+
print(PathGenerator.guess_the_label_size(62, 62))

poetry.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/taxonomy/models.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55

66
class Taxonomy(TreeModel):
7-
label_size = 2
8-
97
name = models.TextField()
108

119
def __str__(self):
12-
return '{}: {}'.format(self.path, self.name)
10+
return f"{self.path}: {self.name}"

tests/test_label_generation.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from django_ltree.paths import PathGenerator
2+
3+
4+
def test_label_generation():
5+
assert PathGenerator.guess_the_label_size(62, 62) == 2
6+
assert PathGenerator.guess_the_label_size(0, 62) == 1
7+
8+
9+
def test_automatic_name_creation():
10+
from taxonomy.models import Taxonomy
11+
12+
for i in range(0, 1000):
13+
Taxonomy.objects.create_child(name=i)

tests/test_limits.py

Whitespace-only changes.

0 commit comments

Comments
 (0)