django-spire 0.16.12__py3-none-any.whl → 0.16.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. django_spire/ai/admin.py +3 -1
  2. django_spire/ai/apps.py +2 -0
  3. django_spire/ai/chat/admin.py +15 -9
  4. django_spire/ai/chat/apps.py +4 -1
  5. django_spire/ai/chat/auth/controller.py +3 -1
  6. django_spire/ai/chat/choices.py +2 -0
  7. django_spire/ai/chat/intelligence/maps/intent_llm_map.py +8 -5
  8. django_spire/ai/chat/intelligence/prompts.py +4 -2
  9. django_spire/ai/chat/intelligence/workflows/chat_workflow.py +27 -28
  10. django_spire/ai/chat/message_intel.py +7 -4
  11. django_spire/ai/chat/models.py +8 -9
  12. django_spire/ai/chat/querysets.py +3 -1
  13. django_spire/ai/chat/responses.py +19 -10
  14. django_spire/ai/chat/tools.py +20 -15
  15. django_spire/ai/chat/urls/message_urls.py +2 -1
  16. django_spire/ai/chat/urls/page_urls.py +1 -0
  17. django_spire/ai/chat/views/message_request_views.py +2 -0
  18. django_spire/ai/chat/views/message_response_views.py +4 -4
  19. django_spire/ai/chat/views/message_views.py +2 -0
  20. django_spire/ai/chat/views/page_views.py +7 -2
  21. django_spire/ai/chat/views/template_views.py +2 -0
  22. django_spire/ai/decorators.py +13 -7
  23. django_spire/ai/mixins.py +4 -2
  24. django_spire/ai/models.py +7 -2
  25. django_spire/ai/prompt/bots.py +14 -32
  26. django_spire/ai/prompt/intel.py +1 -1
  27. django_spire/ai/prompt/prompts.py +7 -1
  28. django_spire/ai/prompt/system/bots.py +42 -75
  29. django_spire/ai/prompt/system/intel.py +5 -4
  30. django_spire/ai/prompt/system/prompts.py +5 -1
  31. django_spire/ai/prompt/system/system_prompt_cli.py +15 -9
  32. django_spire/ai/prompt/tests/test_bots.py +14 -11
  33. django_spire/ai/prompt/text_to_prompt_cli.py +5 -2
  34. django_spire/ai/prompt/tuning/bot_tuning_cli.py +14 -13
  35. django_spire/ai/prompt/tuning/bots.py +68 -116
  36. django_spire/ai/prompt/tuning/intel.py +1 -1
  37. django_spire/ai/prompt/tuning/mixins.py +2 -0
  38. django_spire/ai/prompt/tuning/prompt_tuning_cli.py +8 -8
  39. django_spire/ai/prompt/tuning/prompts.py +4 -2
  40. django_spire/ai/sms/admin.py +3 -1
  41. django_spire/ai/sms/apps.py +2 -0
  42. django_spire/ai/sms/decorators.py +2 -0
  43. django_spire/ai/sms/intel.py +4 -2
  44. django_spire/ai/sms/intelligence/workflows/sms_conversation_workflow.py +8 -8
  45. django_spire/ai/sms/models.py +16 -14
  46. django_spire/ai/sms/querysets.py +4 -1
  47. django_spire/ai/sms/tools.py +18 -16
  48. django_spire/ai/sms/urls.py +1 -1
  49. django_spire/ai/sms/views.py +2 -0
  50. django_spire/ai/tests/test_ai.py +3 -5
  51. django_spire/ai/urls.py +1 -0
  52. django_spire/consts.py +1 -1
  53. django_spire/contrib/seeding/field/django/seeder.py +6 -4
  54. django_spire/contrib/seeding/field/llm.py +1 -2
  55. django_spire/contrib/seeding/intelligence/bots/field_seeding_bots.py +7 -8
  56. django_spire/contrib/seeding/intelligence/bots/seeder_generator_bot.py +15 -16
  57. django_spire/contrib/seeding/intelligence/intel.py +1 -1
  58. django_spire/contrib/seeding/intelligence/prompts/factory.py +5 -7
  59. django_spire/contrib/seeding/intelligence/prompts/foreign_key_selection_prompt.py +3 -5
  60. django_spire/contrib/seeding/intelligence/prompts/generate_django_model_seeder_prompts.py +1 -2
  61. django_spire/contrib/seeding/intelligence/prompts/generic_relationship_selection_prompt.py +3 -5
  62. django_spire/contrib/seeding/intelligence/prompts/hierarchical_selection_prompt.py +1 -1
  63. django_spire/contrib/seeding/intelligence/prompts/model_field_choices_prompt.py +3 -3
  64. django_spire/contrib/seeding/intelligence/prompts/negation_prompt.py +1 -1
  65. django_spire/contrib/seeding/intelligence/prompts/objective_prompt.py +2 -4
  66. django_spire/contrib/seeding/management/commands/seeding.py +5 -2
  67. django_spire/contrib/seeding/model/base.py +12 -10
  68. django_spire/contrib/seeding/model/django/seeder.py +13 -10
  69. django_spire/contrib/seeding/tests/test_seeding.py +1 -1
  70. django_spire/knowledge/admin.py +2 -0
  71. django_spire/knowledge/apps.py +2 -0
  72. django_spire/knowledge/auth/controller.py +2 -0
  73. django_spire/knowledge/collection/admin.py +3 -0
  74. django_spire/knowledge/collection/forms.py +2 -0
  75. django_spire/knowledge/collection/models.py +4 -0
  76. django_spire/knowledge/collection/querysets.py +3 -3
  77. django_spire/knowledge/collection/seeding/seed.py +2 -0
  78. django_spire/knowledge/collection/tests/factories.py +2 -0
  79. django_spire/knowledge/collection/tests/test_services/test_transformation_service.py +2 -0
  80. django_spire/knowledge/collection/tests/test_urls/test_form_urls.py +2 -0
  81. django_spire/knowledge/collection/tests/test_urls/test_json_urls.py +2 -0
  82. django_spire/knowledge/collection/tests/test_urls/test_page_urls.py +2 -0
  83. django_spire/knowledge/collection/views/json_views.py +2 -0
  84. django_spire/knowledge/collection/views/page_views.py +2 -0
  85. django_spire/knowledge/context_processors.py +2 -0
  86. django_spire/knowledge/entry/services/tool_service.py +1 -0
  87. django_spire/knowledge/entry/services/transformation_services.py +0 -1
  88. django_spire/knowledge/entry/tests/factories.py +3 -0
  89. django_spire/knowledge/entry/tests/test_urls/test_form_urls.py +2 -0
  90. django_spire/knowledge/entry/tests/test_urls/test_json_urls.py +2 -0
  91. django_spire/knowledge/entry/tests/test_urls/test_page_urls.py +2 -0
  92. django_spire/knowledge/entry/urls/form_urls.py +1 -0
  93. django_spire/knowledge/entry/urls/json_urls.py +1 -0
  94. django_spire/knowledge/entry/urls/page_urls.py +1 -0
  95. django_spire/knowledge/entry/urls/template_urls.py +1 -0
  96. django_spire/knowledge/entry/version/admin.py +2 -0
  97. django_spire/knowledge/entry/version/block/admin.py +2 -0
  98. django_spire/knowledge/entry/version/block/blocks/heading_block.py +2 -0
  99. django_spire/knowledge/entry/version/block/blocks/sub_heading_block.py +2 -0
  100. django_spire/knowledge/entry/version/block/blocks/text_block.py +2 -0
  101. django_spire/knowledge/entry/version/block/maps.py +2 -0
  102. django_spire/knowledge/entry/version/block/models.py +2 -0
  103. django_spire/knowledge/entry/version/block/tests/factories.py +2 -0
  104. django_spire/knowledge/entry/version/block/tests/test_urls/test_json_urls.py +2 -0
  105. django_spire/knowledge/entry/version/block/views/json_views.py +2 -0
  106. django_spire/knowledge/entry/version/intelligence/bots/markdown_format_llm_bot.py +12 -9
  107. django_spire/knowledge/entry/version/maps.py +2 -0
  108. django_spire/knowledge/entry/version/models.py +2 -0
  109. django_spire/knowledge/entry/version/querysets.py +2 -0
  110. django_spire/knowledge/entry/version/seeding/seeder.py +1 -0
  111. django_spire/knowledge/entry/version/tests/factories.py +2 -0
  112. django_spire/knowledge/entry/version/tests/test_converters/test_docx_converter.py +3 -0
  113. django_spire/knowledge/entry/version/tests/test_urls/test_form_urls.py +2 -0
  114. django_spire/knowledge/entry/version/tests/test_urls/test_json_urls.py +2 -0
  115. django_spire/knowledge/entry/version/tests/test_urls/test_page_urls.py +2 -0
  116. django_spire/knowledge/entry/version/urls/form_urls.py +1 -0
  117. django_spire/knowledge/entry/version/urls/json_urls.py +1 -0
  118. django_spire/knowledge/entry/version/urls/page_urls.py +1 -0
  119. django_spire/knowledge/entry/version/urls/redirect_urls.py +1 -0
  120. django_spire/knowledge/entry/version/views/form_views.py +2 -0
  121. django_spire/knowledge/entry/version/views/json_views.py +2 -0
  122. django_spire/knowledge/entry/version/views/page_views.py +2 -0
  123. django_spire/knowledge/entry/version/views/redirect_views.py +2 -0
  124. django_spire/knowledge/exceptions.py +2 -0
  125. django_spire/knowledge/intelligence/bots/entry_search_llm_bot.py +5 -16
  126. django_spire/knowledge/intelligence/intel/collection_intel.py +3 -1
  127. django_spire/knowledge/intelligence/intel/entry_intel.py +3 -3
  128. django_spire/knowledge/intelligence/intel/message_intel.py +2 -0
  129. django_spire/knowledge/intelligence/maps/collection_map.py +9 -10
  130. django_spire/knowledge/intelligence/maps/entry_map.py +8 -9
  131. django_spire/knowledge/intelligence/workflows/knowledge_workflow.py +8 -6
  132. django_spire/knowledge/models.py +2 -0
  133. django_spire/knowledge/seeding/seed.py +2 -0
  134. django_spire/knowledge/templatetags/spire_knowledge_tags.py +3 -0
  135. django_spire/knowledge/urls/__init__.py +1 -0
  136. {django_spire-0.16.12.dist-info → django_spire-0.16.13.dist-info}/METADATA +5 -4
  137. {django_spire-0.16.12.dist-info → django_spire-0.16.13.dist-info}/RECORD +140 -140
  138. {django_spire-0.16.12.dist-info → django_spire-0.16.13.dist-info}/WHEEL +0 -0
  139. {django_spire-0.16.12.dist-info → django_spire-0.16.13.dist-info}/licenses/LICENSE.md +0 -0
  140. {django_spire-0.16.12.dist-info → django_spire-0.16.13.dist-info}/top_level.txt +0 -0
@@ -1,19 +1,22 @@
1
- from dandy.llm import BaseLlmBot, Prompt
1
+ from __future__ import annotations
2
2
 
3
+ from dandy import BaseIntel, Bot, Prompt
3
4
 
4
- class MarkdownFormatLlmBot(BaseLlmBot):
5
5
 
6
- @classmethod
7
- def process(
8
- cls,
9
- markdown_content: str
10
- ) -> str:
6
+ class MarkdownTextIntel(BaseIntel):
7
+ text: str
8
+
9
+
10
+ class MarkdownFormatLlmBot(Bot):
11
+ llm_intel_class = MarkdownTextIntel
12
+
13
+ def process(self, markdown_content: str) -> str:
11
14
  markdown_prompt = Prompt()
12
15
  markdown_prompt.text(
13
16
  'Can you improve the markdown formatting? Do NOT add or change any of the '
14
17
  'content.'
15
18
  )
16
- markdown_prompt.line_break()
17
19
  markdown_prompt.text(markdown_content)
18
20
 
19
- return cls.process_prompt_to_intel(prompt=markdown_prompt).text
21
+ result = self.llm.prompt_to_intel(prompt=markdown_prompt)
22
+ return result.text
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django_spire.knowledge.entry.version.converters.docx_converter import \
2
4
  DocxConverter
3
5
  from django_spire.knowledge.entry.version.converters.markdown_converter import \
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.db import models
2
4
  from django.utils.timezone import now
3
5
 
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django_spire.history.querysets import HistoryQuerySet
2
4
 
3
5
 
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import random
4
+
4
5
  from datetime import timedelta
5
6
 
6
7
  from django.utils.timezone import localtime
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from keyring.testing.util import random_string
2
4
 
3
5
  from django_spire.auth.user.tests.factories import create_user
@@ -1,4 +1,7 @@
1
+ from __future__ import annotations
2
+
1
3
  import time
4
+
2
5
  from unittest.mock import MagicMock, patch
3
6
 
4
7
  from django_spire.core.tests.test_cases import BaseTestCase
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.urls import reverse
2
4
 
3
5
  from django_spire.core.tests.test_cases import BaseTestCase
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.urls import reverse
2
4
 
3
5
  from django_spire.core.tests.test_cases import BaseTestCase
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.urls import reverse
2
4
 
3
5
  from django_spire.core.tests.test_cases import BaseTestCase
@@ -2,6 +2,7 @@ from django.urls import path
2
2
 
3
3
  from django_spire.knowledge.entry.version.views import form_views
4
4
 
5
+
5
6
  app_name = 'form'
6
7
 
7
8
  urlpatterns = [
@@ -2,6 +2,7 @@ from django.urls import path
2
2
 
3
3
  from django_spire.knowledge.entry.version.views import json_views
4
4
 
5
+
5
6
  app_name = 'json'
6
7
 
7
8
  urlpatterns = [
@@ -2,6 +2,7 @@ from django.urls import path
2
2
 
3
3
  from django_spire.knowledge.entry.version.views import page_views
4
4
 
5
+
5
6
  app_name = 'page'
6
7
 
7
8
  urlpatterns = [
@@ -2,6 +2,7 @@ from django.urls import path
2
2
 
3
3
  from django_spire.knowledge.entry.version.views import redirect_views
4
4
 
5
+
5
6
  app_name = 'redirect'
6
7
 
7
8
  urlpatterns = [
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import json
2
4
 
3
5
  from django.core.handlers.wsgi import WSGIRequest
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import json
2
4
 
3
5
  from django.core.handlers.wsgi import WSGIRequest
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.core.handlers.wsgi import WSGIRequest
2
4
  from django.shortcuts import get_object_or_404
3
5
  from django.template.response import TemplateResponse
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.core.handlers.wsgi import WSGIRequest
2
4
  from django.http import HttpResponseRedirect
3
5
  from django.shortcuts import get_object_or_404
@@ -1,2 +1,4 @@
1
+ from __future__ import annotations
2
+
1
3
  class KnowledgeBaseConversionException(Exception):
2
4
  pass
@@ -1,30 +1,19 @@
1
- from typing import Any
1
+ from __future__ import annotations
2
2
 
3
- from dandy.llm import BaseLlmBot, Prompt, DefaultLlmIntel
3
+ from dandy import Bot, Prompt
4
4
 
5
5
  from django_spire.knowledge.entry.models import Entry
6
6
 
7
7
 
8
- class EntrySearchLlmBot(BaseLlmBot):
8
+ class EntrySearchLlmBot(Bot):
9
9
  @classmethod
10
- def process(
11
- cls,
12
- user_input: str,
13
- entry: Entry
14
- ) -> str:
10
+ def process(cls, user_input: str, entry: Entry) -> str:
15
11
  entry_prompt = Prompt()
16
-
17
12
  entry_prompt.text('You are a helpful assistant that helps users find information about entries.')
18
-
19
13
  entry_prompt.text(f'User Input: {user_input}')
20
-
21
14
  entry_prompt.text(f'Entry: {entry.name}')
22
15
 
23
16
  for version_block in entry.current_version.blocks.all():
24
17
  entry_prompt.text(version_block.render_to_text())
25
18
 
26
- result_intel: DefaultLlmIntel = cls.process_prompt_to_intel(
27
- prompt=entry_prompt
28
- )
29
-
30
- return result_intel.text
19
+ return cls().llm.prompt_to_text(prompt=entry_prompt)
@@ -1,4 +1,6 @@
1
- from dandy.intel import BaseIntel
1
+ from __future__ import annotations
2
+
3
+ from dandy import BaseIntel
2
4
 
3
5
 
4
6
  class CollectionIntel(BaseIntel):
@@ -1,6 +1,6 @@
1
- from typing import List
1
+ from __future__ import annotations
2
2
 
3
- from dandy.intel import BaseIntel, BaseListIntel
3
+ from dandy import BaseIntel, BaseListIntel
4
4
 
5
5
  from django_spire.knowledge.intelligence.intel.collection_intel import CollectionIntel
6
6
 
@@ -11,4 +11,4 @@ class EntryIntel(BaseIntel):
11
11
 
12
12
 
13
13
  class EntriesIntel(BaseListIntel[EntryIntel]):
14
- entry_intel_list: List[EntryIntel]
14
+ entry_intel_list: list[EntryIntel]
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django_spire.ai.chat.message_intel import BaseMessageIntel
2
4
 
3
5
 
@@ -1,20 +1,19 @@
1
- from typing import Type
1
+ from __future__ import annotations
2
2
 
3
- from dandy.llm import BaseLlmMap
4
- from dandy.map import Map
3
+ from dandy import Decoder
5
4
 
6
5
  from django_spire.knowledge.collection.models import Collection
7
6
 
8
7
 
9
- def get_collection_map_class() -> Type[BaseLlmMap]:
10
- class CollectionMap(BaseLlmMap):
11
- map_keys_description = 'Knowledge Collection Titles'
12
- map = Map({
8
+ def get_collection_map_class() -> type[Decoder]:
9
+ class CollectionMap(Decoder):
10
+ mapping_keys_description = 'Knowledge Collection Titles'
11
+ mapping = {
13
12
  **{
14
13
  collection.name: collection
15
14
  for collection in Collection.objects.all().annotate_entry_count()
16
15
  },
17
- **{'No Matching Knowledge Collection Titles': None}
18
- })
16
+ 'No Matching Knowledge Collection Titles': None
17
+ }
19
18
 
20
- return CollectionMap
19
+ return CollectionMap
@@ -1,20 +1,19 @@
1
- from typing import Type
1
+ from __future__ import annotations
2
2
 
3
- from dandy.llm import BaseLlmMap
4
- from dandy.map import Map
3
+ from dandy import Decoder
5
4
 
6
5
  from django_spire.knowledge.collection.models import Collection
7
6
 
8
7
 
9
- def get_entry_map_class(collection: Collection) -> Type[BaseLlmMap]:
10
- class EntryMap(BaseLlmMap):
11
- map_keys_description = 'Knowledge Entries'
12
- map = Map({
8
+ def get_entry_map_class(collection: Collection) -> type[Decoder]:
9
+ class EntryMap(Decoder):
10
+ mapping_keys_description = 'Knowledge Entries'
11
+ mapping = {
13
12
  **{
14
13
  entry.name: entry
15
14
  for entry in collection.entries.all()
16
15
  },
17
- **{'No Matching Knowledge Entries': None}
18
- })
16
+ 'No Matching Knowledge Entries': None
17
+ }
19
18
 
20
19
  return EntryMap
@@ -1,18 +1,18 @@
1
- from dandy.workflow import BaseWorkflow
1
+ from __future__ import annotations
2
2
 
3
3
  from django_spire.knowledge.intelligence.bots.entry_search_llm_bot import EntrySearchLlmBot
4
4
  from django_spire.knowledge.intelligence.intel.collection_intel import CollectionIntel
5
5
  from django_spire.knowledge.intelligence.intel.entry_intel import EntriesIntel, EntryIntel
6
- from django_spire.knowledge.intelligence.maps.collection_map import get_collection_map_class
7
6
  from django_spire.knowledge.intelligence.intel.message_intel import KnowledgeMessageIntel
7
+ from django_spire.knowledge.intelligence.maps.collection_map import get_collection_map_class
8
8
  from django_spire.knowledge.intelligence.maps.entry_map import get_entry_map_class
9
9
 
10
10
 
11
- class KnowledgeWorkflow(BaseWorkflow):
11
+ class KnowledgeWorkflow:
12
12
  @classmethod
13
13
  def process(cls, user_input: str) -> KnowledgeMessageIntel:
14
14
  CollectionMap = get_collection_map_class()
15
- collections = CollectionMap.process(user_input)
15
+ collections = CollectionMap().process(user_input).values
16
16
 
17
17
  if collections[0] is None:
18
18
  return KnowledgeMessageIntel(
@@ -26,7 +26,7 @@ class KnowledgeWorkflow(BaseWorkflow):
26
26
  for collection in collections:
27
27
  if collection.entry_count > 0:
28
28
  EntryMap = get_entry_map_class(collection=collection)
29
- entries.extend(EntryMap.process(user_input))
29
+ entries.extend(EntryMap().process(user_input).values)
30
30
 
31
31
  entries = [entry for entry in entries if entry is not None]
32
32
 
@@ -38,10 +38,12 @@ class KnowledgeWorkflow(BaseWorkflow):
38
38
  )
39
39
  )
40
40
 
41
+ entry_search_bot = EntrySearchLlmBot()
42
+
41
43
  entries_intel = EntriesIntel(
42
44
  entry_intel_list=[
43
45
  EntryIntel(
44
- body=EntrySearchLlmBot.process(
46
+ body=entry_search_bot.process(
45
47
  user_input=user_input,
46
48
  entry=entry
47
49
  ),
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  # These imports are for the migrations to work as a single app "django_spire_knowledge"
2
4
 
3
5
  from django_spire.knowledge.entry import models
@@ -1 +1,3 @@
1
+ from __future__ import annotations
2
+
1
3
  from django_spire.knowledge.collection.seeding.seed import *
@@ -1,7 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  import re
2
4
 
3
5
  from django import template
4
6
 
7
+
5
8
  register = template.Library()
6
9
 
7
10
 
@@ -1,5 +1,6 @@
1
1
  from django.urls import include, path
2
2
 
3
+
3
4
  app_name = 'knowledge'
4
5
 
5
6
  urlpatterns = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-spire
3
- Version: 0.16.12
3
+ Version: 0.16.13
4
4
  Summary: A project for Django Spire
5
5
  Author-email: Brayden Carlson <braydenc@stratusadv.com>, Nathan Johnson <nathanj@stratusadv.com>
6
6
  License: Copyright (c) 2024 Stratus Advanced Technologies and Contributors.
@@ -45,10 +45,10 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
45
45
  Requires-Python: >=3.11
46
46
  Description-Content-Type: text/markdown
47
47
  License-File: LICENSE.md
48
- Requires-Dist: boto3==1.24.18
49
- Requires-Dist: botocore==1.27.18
48
+ Requires-Dist: boto3>=1.34.0
49
+ Requires-Dist: botocore>=1.34.0
50
50
  Requires-Dist: crispy-bootstrap5==2024.10
51
- Requires-Dist: dandy==0.20.0
51
+ Requires-Dist: dandy==1.1.0
52
52
  Requires-Dist: django>=5.1.8
53
53
  Requires-Dist: django-crispy-forms==2.3
54
54
  Requires-Dist: django-glue>=0.8.1
@@ -73,6 +73,7 @@ Requires-Dist: django-debug-toolbar; extra == "development"
73
73
  Requires-Dist: django-watchfiles; extra == "development"
74
74
  Requires-Dist: pip; extra == "development"
75
75
  Requires-Dist: pyinstrument; extra == "development"
76
+ Requires-Dist: pyrefly; extra == "development"
76
77
  Requires-Dist: pytest; extra == "development"
77
78
  Requires-Dist: setuptools; extra == "development"
78
79
  Requires-Dist: twine; extra == "development"