Skip to content

Commit f589d05

Browse files
add
1 parent 518ef2d commit f589d05

File tree

4 files changed

+44
-14
lines changed

4 files changed

+44
-14
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

+31-4
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@
22
from itertools import product
33

44
from django_ltree.fields import PathValue
5+
import math
56

67

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

10-
def __init__(self, prefix=None, skip=None, label_size=None):
1114
self.skip_paths = [] if skip is None else skip[:]
1215
self.path_prefix = prefix if prefix else []
1316
self.product_iterator = product(
14-
string.digits + string.ascii_letters,
15-
repeat=label_size or self._default_label_size,
17+
combinations,
18+
repeat=self.guess_the_label_size(
19+
path_size=len(self.skip_paths), combination_size=len(combinations)
20+
),
1621
)
1722

1823
def __iter__(self):
@@ -26,3 +31,25 @@ def __next__(self):
2631
return path
2732

2833
next = __next__
34+
35+
@staticmethod
36+
def guess_the_label_size(path_size: int, combination_size: int):
37+
# The theoritical limit for this at the time of writing is 2538557185841324496 (python 3.12.2)
38+
calculated_path_size = 0
39+
# The theoritical limit for this at the time of writing is 32 (python 3.12.2)
40+
label_size = 0
41+
42+
# THIS IS AN VERY IMPORTANT CHECK
43+
last = 0
44+
45+
while calculated_path_size < path_size:
46+
possible_cominations = math.comb(combination_size, label_size)
47+
48+
if last > possible_cominations:
49+
raise ValueError("We approached the limit of `math.comb`")
50+
51+
last = possible_cominations
52+
calculated_path_size += possible_cominations
53+
label_size += 1
54+
55+
return label_size

poetry.lock

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

tests/test_path_value.py

+12-8
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44

55

66
def test_create():
7-
assert str(PathValue([1, 2, 3, 4, 5])) == '1.2.3.4.5'
8-
assert str(PathValue((1, 3, 5, 7))) == '1.3.5.7'
9-
assert str(PathValue('hello.world')) == 'hello.world'
7+
assert str(PathValue([1, 2, 3, 4, 5])) == "1.2.3.4.5"
8+
assert str(PathValue((1, 3, 5, 7))) == "1.3.5.7"
9+
assert str(PathValue("hello.world")) == "hello.world"
1010
assert str(PathValue(5)) == "5"
1111

1212
def generator():
13-
yield '100'
14-
yield 'bottles'
15-
yield 'of'
16-
yield 'beer'
13+
yield "100"
14+
yield "bottles"
15+
yield "of"
16+
yield "beer"
1717

18-
assert str(PathValue(generator())) == '100.bottles.of.beer'
18+
assert str(PathValue(generator())) == "100.bottles.of.beer"
19+
20+
21+
def test_automatic_generation_of_label():
22+
pass

0 commit comments

Comments
 (0)