fmtr.tools 1.3.13__tar.gz → 1.3.15__tar.gz

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.

Potentially problematic release.


This version of fmtr.tools might be problematic. Click here for more details.

Files changed (91) hide show
  1. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/PKG-INFO +44 -44
  2. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/dns_tools/client.py +6 -2
  3. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/dns_tools/dm.py +25 -10
  4. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/dns_tools/proxy.py +13 -4
  5. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/dns_tools/server.py +40 -14
  6. fmtr_tools-1.3.15/fmtr/tools/version +1 -0
  7. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr.tools.egg-info/PKG-INFO +44 -44
  8. fmtr_tools-1.3.13/fmtr/tools/version +0 -1
  9. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/LICENSE +0 -0
  10. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/README.md +0 -0
  11. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/__init__.py +0 -0
  12. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/ai_tools/__init__.py +0 -0
  13. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/ai_tools/agentic_tools.py +0 -0
  14. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/ai_tools/inference_tools.py +0 -0
  15. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/api_tools.py +0 -0
  16. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/async_tools.py +0 -0
  17. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/augmentation_tools.py +0 -0
  18. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/caching_tools.py +0 -0
  19. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/constants.py +0 -0
  20. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/data_modelling_tools.py +0 -0
  21. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/dataclass_tools.py +0 -0
  22. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/datatype_tools.py +0 -0
  23. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/debugging_tools.py +0 -0
  24. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/dns_tools/__init__.py +0 -0
  25. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/docker_tools.py +0 -0
  26. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/entrypoints/__init__.py +0 -0
  27. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/entrypoints/cache_hfh.py +0 -0
  28. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/entrypoints/ep_test.py +0 -0
  29. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/entrypoints/install_yamlscript.py +0 -0
  30. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/entrypoints/remote_debug_test.py +0 -0
  31. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/entrypoints/shell_debug.py +0 -0
  32. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/environment_tools.py +0 -0
  33. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/function_tools.py +0 -0
  34. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/google_api_tools.py +0 -0
  35. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/hash_tools.py +0 -0
  36. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/hfh_tools.py +0 -0
  37. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/html_tools.py +0 -0
  38. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/http_tools.py +0 -0
  39. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/import_tools.py +0 -0
  40. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/inspection_tools.py +0 -0
  41. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/interface_tools.py +0 -0
  42. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/iterator_tools.py +0 -0
  43. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/json_fix_tools.py +0 -0
  44. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/json_tools.py +0 -0
  45. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/logging_tools.py +0 -0
  46. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/merging_tools.py +0 -0
  47. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/metric_tools.py +0 -0
  48. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/name_tools.py +0 -0
  49. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/netrc_tools.py +0 -0
  50. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/openai_tools.py +0 -0
  51. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/packaging_tools.py +0 -0
  52. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/parallel_tools.py +0 -0
  53. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/path_tools/__init__.py +0 -0
  54. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/path_tools/app_path_tools.py +0 -0
  55. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/path_tools/path_tools.py +0 -0
  56. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/path_tools/type_path_tools.py +0 -0
  57. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/pattern_tools.py +0 -0
  58. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/pdf_tools.py +0 -0
  59. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/platform_tools.py +0 -0
  60. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/process_tools.py +0 -0
  61. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/profiling_tools.py +0 -0
  62. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/random_tools.py +0 -0
  63. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/semantic_tools.py +0 -0
  64. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/settings_tools.py +0 -0
  65. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/setup_tools/__init__.py +0 -0
  66. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/setup_tools/setup_tools.py +0 -0
  67. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/spaces_tools.py +0 -0
  68. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/string_tools.py +0 -0
  69. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tabular_tools.py +0 -0
  70. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tests/__init__.py +0 -0
  71. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tests/conftest.py +0 -0
  72. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tests/helpers.py +0 -0
  73. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tests/test_datatype.py +0 -0
  74. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tests/test_environment.py +0 -0
  75. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tests/test_json.py +0 -0
  76. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tests/test_path.py +0 -0
  77. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tests/test_yaml.py +0 -0
  78. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tokenization_tools.py +0 -0
  79. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/tools.py +0 -0
  80. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/unicode_tools.py +0 -0
  81. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/version_tools/__init__.py +0 -0
  82. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/version_tools/version_tools.py +0 -0
  83. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr/tools/yaml_tools.py +0 -0
  84. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr.tools.egg-info/SOURCES.txt +0 -0
  85. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr.tools.egg-info/dependency_links.txt +0 -0
  86. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr.tools.egg-info/entry_points.txt +0 -0
  87. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr.tools.egg-info/requires.txt +43 -43
  88. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/fmtr.tools.egg-info/top_level.txt +0 -0
  89. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/pyproject.toml +0 -0
  90. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/setup.cfg +0 -0
  91. {fmtr_tools-1.3.13 → fmtr_tools-1.3.15}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmtr.tools
3
- Version: 1.3.13
3
+ Version: 1.3.15
4
4
  Summary: Collection of high-level tools to simplify everyday development tasks, with a focus on AI/ML
5
5
  Home-page: https://github.com/fmtr/fmtr.tools
6
6
  Author: Frontmatter
@@ -126,61 +126,61 @@ Requires-Dist: logfire[httpx]; extra == "http"
126
126
  Provides-Extra: setup
127
127
  Requires-Dist: setuptools; extra == "setup"
128
128
  Provides-Extra: all
129
- Requires-Dist: tokenizers; extra == "all"
130
- Requires-Dist: setuptools; extra == "all"
129
+ Requires-Dist: flet-video; extra == "all"
130
+ Requires-Dist: regex; extra == "all"
131
+ Requires-Dist: dnspython[doh]; extra == "all"
132
+ Requires-Dist: distributed; extra == "all"
133
+ Requires-Dist: tinynetrc; extra == "all"
131
134
  Requires-Dist: pandas; extra == "all"
132
- Requires-Dist: pytest-cov; extra == "all"
133
- Requires-Dist: httpx_retries; extra == "all"
134
- Requires-Dist: logfire; extra == "all"
135
+ Requires-Dist: contexttimer; extra == "all"
136
+ Requires-Dist: peft; extra == "all"
137
+ Requires-Dist: pydantic; extra == "all"
138
+ Requires-Dist: google-auth; extra == "all"
139
+ Requires-Dist: tokenizers; extra == "all"
140
+ Requires-Dist: diskcache; extra == "all"
141
+ Requires-Dist: cachetools; extra == "all"
142
+ Requires-Dist: pymupdf; extra == "all"
135
143
  Requires-Dist: bokeh; extra == "all"
136
- Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
144
+ Requires-Dist: tabulate; extra == "all"
145
+ Requires-Dist: ollama; extra == "all"
146
+ Requires-Dist: Unidecode; extra == "all"
147
+ Requires-Dist: logfire; extra == "all"
148
+ Requires-Dist: sre_yield; extra == "all"
149
+ Requires-Dist: pyyaml; extra == "all"
150
+ Requires-Dist: deepmerge; extra == "all"
151
+ Requires-Dist: huggingface_hub; extra == "all"
152
+ Requires-Dist: openai; extra == "all"
137
153
  Requires-Dist: sentence_transformers; extra == "all"
138
- Requires-Dist: html2text; extra == "all"
154
+ Requires-Dist: openpyxl; extra == "all"
155
+ Requires-Dist: httpx_retries; extra == "all"
139
156
  Requires-Dist: flet-webview; extra == "all"
140
- Requires-Dist: transformers[sentencepiece]; extra == "all"
141
- Requires-Dist: pyyaml; extra == "all"
157
+ Requires-Dist: pytest-cov; extra == "all"
158
+ Requires-Dist: torchvision; extra == "all"
159
+ Requires-Dist: torchaudio; extra == "all"
142
160
  Requires-Dist: faker; extra == "all"
143
- Requires-Dist: fastapi; extra == "all"
144
- Requires-Dist: Unidecode; extra == "all"
145
- Requires-Dist: pymupdf; extra == "all"
146
- Requires-Dist: appdirs; extra == "all"
147
- Requires-Dist: sre_yield; extra == "all"
148
- Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
149
- Requires-Dist: peft; extra == "all"
150
- Requires-Dist: flet-video; extra == "all"
151
- Requires-Dist: diskcache; extra == "all"
152
- Requires-Dist: yamlscript; extra == "all"
153
- Requires-Dist: pymupdf4llm; extra == "all"
154
- Requires-Dist: filetype; extra == "all"
155
- Requires-Dist: ollama; extra == "all"
156
- Requires-Dist: google-auth; extra == "all"
157
161
  Requires-Dist: logfire[httpx]; extra == "all"
158
- Requires-Dist: uvicorn[standard]; extra == "all"
159
- Requires-Dist: tinynetrc; extra == "all"
160
- Requires-Dist: dnspython[doh]; extra == "all"
161
- Requires-Dist: google-auth-httplib2; extra == "all"
162
- Requires-Dist: pydantic; extra == "all"
162
+ Requires-Dist: flet[all]; extra == "all"
163
163
  Requires-Dist: google-api-python-client; extra == "all"
164
- Requires-Dist: docker; extra == "all"
165
- Requires-Dist: httpx; extra == "all"
166
- Requires-Dist: tabulate; extra == "all"
167
- Requires-Dist: huggingface_hub; extra == "all"
168
- Requires-Dist: regex; extra == "all"
169
- Requires-Dist: openpyxl; extra == "all"
170
- Requires-Dist: dask[bag]; extra == "all"
171
- Requires-Dist: distributed; extra == "all"
172
- Requires-Dist: openai; extra == "all"
173
- Requires-Dist: deepmerge; extra == "all"
174
164
  Requires-Dist: json_repair; extra == "all"
175
165
  Requires-Dist: google-auth-oauthlib; extra == "all"
176
- Requires-Dist: contexttimer; extra == "all"
166
+ Requires-Dist: fastapi; extra == "all"
167
+ Requires-Dist: yamlscript; extra == "all"
168
+ Requires-Dist: setuptools; extra == "all"
177
169
  Requires-Dist: semver; extra == "all"
170
+ Requires-Dist: pymupdf4llm; extra == "all"
171
+ Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
172
+ Requires-Dist: appdirs; extra == "all"
173
+ Requires-Dist: google-auth-httplib2; extra == "all"
178
174
  Requires-Dist: pydantic-settings; extra == "all"
179
- Requires-Dist: flet[all]; extra == "all"
180
- Requires-Dist: cachetools; extra == "all"
175
+ Requires-Dist: uvicorn[standard]; extra == "all"
176
+ Requires-Dist: httpx; extra == "all"
177
+ Requires-Dist: docker; extra == "all"
178
+ Requires-Dist: transformers[sentencepiece]; extra == "all"
179
+ Requires-Dist: dask[bag]; extra == "all"
180
+ Requires-Dist: filetype; extra == "all"
181
181
  Requires-Dist: logfire[fastapi]; extra == "all"
182
- Requires-Dist: torchaudio; extra == "all"
183
- Requires-Dist: torchvision; extra == "all"
182
+ Requires-Dist: html2text; extra == "all"
183
+ Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
184
184
  Dynamic: author
185
185
  Dynamic: author-email
186
186
  Dynamic: description
@@ -3,6 +3,7 @@ from dataclasses import dataclass
3
3
  from dns import query
4
4
  from functools import cached_property
5
5
  from httpx_retries import Retry, RetryTransport
6
+ from typing import Optional
6
7
 
7
8
  from fmtr.tools import http_tools as http
8
9
  from fmtr.tools.dns_tools.dm import Exchange, Response
@@ -38,14 +39,17 @@ class Plain:
38
39
  """
39
40
  host: str
40
41
  port: int = 53
42
+ ttl_min: Optional[int] = None
41
43
 
42
44
  def resolve(self, exchange: Exchange):
43
45
 
44
46
  with logger.span(f'UDP {self.host}:{self.port}'):
45
47
  response_plain = query.udp(q=exchange.query_last, where=self.host, port=self.port)
46
48
  response = Response.from_message(response_plain)
49
+ for answer in response.message.answer:
50
+ answer.ttl = max(answer.ttl, self.ttl_min or answer.ttl)
47
51
 
48
- exchange.response.message.answer += response.message.answer
52
+ exchange.response = response
49
53
 
50
54
 
51
55
  @dataclass
@@ -86,7 +90,7 @@ class HTTP:
86
90
  response_doh = self.CLIENT.post(url, headers=headers, content=exchange.query_last.to_wire())
87
91
  response_doh.raise_for_status()
88
92
  response = Response.from_http(response_doh)
89
- exchange.response.message.answer += response.message.answer
93
+ exchange.response = response
90
94
 
91
95
  except Exception as exception:
92
96
  exchange.response.message.set_rcode(dnspython.rcode.SERVFAIL)
@@ -1,11 +1,12 @@
1
1
  import dns
2
2
  import httpx
3
- from dataclasses import dataclass
3
+ from dataclasses import dataclass, field
4
4
  from dns import rcode as dnsrcode
5
+ from dns import reversename
5
6
  from dns.message import Message, QueryMessage
6
7
  from dns.rrset import RRset
7
8
  from functools import cached_property
8
- from typing import Self, Optional
9
+ from typing import Self, Optional, List
9
10
 
10
11
  from fmtr.tools.string_tools import join
11
12
 
@@ -36,7 +37,7 @@ class Response(BaseDNSData):
36
37
  """
37
38
 
38
39
  http: Optional[httpx.Response] = None
39
- is_complete: bool = False
40
+ blocked_by: Optional[str] = None
40
41
 
41
42
  @classmethod
42
43
  def from_http(cls, response: httpx.Response) -> Self:
@@ -142,14 +143,17 @@ class Exchange:
142
143
 
143
144
  request: Request
144
145
  response: Optional[Response] = None
146
+ answers_pre: List[RRset] = field(default_factory=list)
147
+ is_internal: bool = False
148
+ client_name: Optional[str] = None
149
+ is_complete: bool = False
145
150
 
146
151
 
147
152
  @classmethod
148
- def from_wire(cls, wire: bytes, ip: str, port: int) -> Self:
153
+ def from_wire(cls, wire: bytes, **kwargs) -> Self:
149
154
  request = Request(wire)
150
155
  response = Response.from_message(request.get_response_template())
151
-
152
- return cls(request=request, response=response, ip=ip, port=port)
156
+ return cls(request=request, response=response, **kwargs)
153
157
 
154
158
  @cached_property
155
159
  def client(self):
@@ -162,8 +166,8 @@ class Exchange:
162
166
  Contrive an RRset representing the latest/current question. This can be the original question - or a hybrid one if we've injected our own answers into the exchange.
163
167
 
164
168
  """
165
- if self.response.answer:
166
- rrset = self.response.answer
169
+ if self.answers_pre:
170
+ rrset = self.answers_pre[-1]
167
171
  ty = self.request.type
168
172
  ttl = self.request.question.ttl
169
173
  rdclass = self.request.question.rdclass
@@ -174,7 +178,6 @@ class Exchange:
174
178
  ttl=ttl,
175
179
  rdtype=ty,
176
180
  rdclass=rdclass,
177
-
178
181
  )
179
182
 
180
183
  return rrset_contrived
@@ -190,7 +193,7 @@ class Exchange:
190
193
  """
191
194
 
192
195
  question_last = self.question_last
193
- query = dns.message.make_query(qname=question_last.name, rdclass=question_last.rdclass, rdtype=question_last.rdtype)
196
+ query = dns.message.make_query(qname=question_last.name, rdclass=question_last.rdclass, rdtype=question_last.rdtype, id=self.request.message.id)
194
197
  return query
195
198
 
196
199
  @property
@@ -202,3 +205,15 @@ class Exchange:
202
205
  """
203
206
  data = tuple(self.request.question.to_text().split())
204
207
  return data
208
+
209
+ @cached_property
210
+ def reverse(self) -> Self:
211
+ """
212
+
213
+ Create an Exchange for a reverse lookup of this Exchange's client IP.
214
+
215
+ """
216
+ name = reversename.from_address(self.ip)
217
+ query = dns.message.make_query(name, dns.rdatatype.PTR)
218
+ exchange = self.__class__.from_wire(query.to_wire(), ip=self.ip, port=self.port, is_internal=True)
219
+ return exchange
@@ -31,6 +31,14 @@ class Proxy(server.Plain):
31
31
  """
32
32
  return
33
33
 
34
+ def finalize(self, exchange: Exchange):
35
+ """
36
+
37
+ Finalize a still open exchange.
38
+
39
+ """
40
+ exchange.is_complete = True
41
+
34
42
  def resolve(self, exchange: Exchange) -> Exchange:
35
43
  """
36
44
 
@@ -38,20 +46,21 @@ class Proxy(server.Plain):
38
46
  Subclasses can override the relevant processing methods to implement custom behaviour.
39
47
 
40
48
  """
41
-
42
49
  with logger.span(f'Processing question...'):
43
50
  self.process_question(exchange)
44
- if exchange.response.is_complete:
51
+ if exchange.is_complete:
45
52
  return exchange
46
53
 
47
54
  with logger.span(f'Making upstream request...'):
48
55
  self.client.resolve(exchange)
49
- if exchange.response.is_complete:
56
+ if exchange.is_complete:
50
57
  return exchange
51
58
 
52
59
  with logger.span(f'Processing upstream response...'):
53
60
  self.process_upstream(exchange)
54
- if exchange.response.is_complete:
61
+ if exchange.is_complete:
55
62
  return exchange
56
63
 
64
+ self.finalize(exchange)
65
+
57
66
  return exchange
@@ -66,35 +66,61 @@ class Plain:
66
66
  logger.info(f'Request found in cache.')
67
67
  exchange.response = self.cache[exchange.key]
68
68
  exchange.response.message.id = exchange.request.message.id
69
- exchange.response.is_complete = True
69
+ exchange.is_complete = True
70
70
 
71
- def handle(self, exchange: Exchange):
71
+ def get_span(self, exchange: Exchange):
72
72
  """
73
73
 
74
- Check validity of request, presence in cache and resolve.
74
+ Get handling span
75
75
 
76
76
  """
77
77
  request = exchange.request
78
+ span = logger.span(
79
+ f'Handling request {exchange.client_name=} {request.message.id=} {request.type_text} {request.name_text} {request.question=}...'
80
+ )
81
+ return span
78
82
 
79
- if not request.is_valid:
80
- raise ValueError(f'Only one question per request is supported. Got {len(request.question)} questions.')
83
+ def log_response(self, exchange: Exchange):
84
+ """
81
85
 
82
- span = logger.span(
83
- f'Handling request {request.message.id=} {request.type_text} {request.name_text} {request.question=} {exchange.ip=} {exchange.port=}...'
86
+ Log when resolution complete
87
+
88
+ """
89
+ request = exchange.request
90
+ response = exchange.response
91
+
92
+ logger.info(
93
+ f'Resolution complete {exchange.client_name=} {request.message.id=} {request.type_text} {request.name_text} {request.question=} {exchange.is_complete=} {response.rcode=} {response.rcode_text=} {response.answer=} {response.blocked_by=}...'
84
94
  )
85
- with span:
86
95
 
96
+
97
+
98
+ def handle(self, exchange: Exchange):
99
+ """
100
+
101
+ Check validity of request, reverse lookup client address, check presence in cache and resolve.
102
+
103
+ """
104
+
105
+ if not exchange.request.is_valid:
106
+ raise ValueError(f'Only one question per request is supported. Got {len(exchange.request.question)} questions.')
107
+
108
+ if not exchange.is_internal:
109
+ self.handle(exchange.reverse)
110
+ client_name = exchange.reverse.question_last.name.to_text()
111
+ if not exchange.reverse.response.answer:
112
+ logger.warning(f'Client name could not be resolved {client_name=}.')
113
+ exchange.client_name = client_name
114
+
115
+ with self.get_span(exchange):
87
116
  with logger.span(f'Checking cache...'):
88
117
  self.check_cache(exchange)
89
118
 
90
- if not exchange.response.is_complete:
119
+ if not exchange.is_complete:
91
120
  exchange = self.resolve(exchange)
92
- exchange.response.is_complete = True
121
+ exchange.is_complete = True
93
122
 
94
123
  self.cache[exchange.key] = exchange.response
95
- logger.info(f'Resolution complete {request.message.id=} {exchange.response.rcode_text=} {exchange.response.answer=}')
96
-
97
- attribs = dict(rcode=exchange.response.rcode, rcode_text=exchange.response.rcode_text)
98
- span.set_attributes(attribs)
124
+ self.log_response(exchange)
99
125
 
100
126
  return exchange
@@ -0,0 +1 @@
1
+ 1.3.15
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmtr.tools
3
- Version: 1.3.13
3
+ Version: 1.3.15
4
4
  Summary: Collection of high-level tools to simplify everyday development tasks, with a focus on AI/ML
5
5
  Home-page: https://github.com/fmtr/fmtr.tools
6
6
  Author: Frontmatter
@@ -126,61 +126,61 @@ Requires-Dist: logfire[httpx]; extra == "http"
126
126
  Provides-Extra: setup
127
127
  Requires-Dist: setuptools; extra == "setup"
128
128
  Provides-Extra: all
129
- Requires-Dist: tokenizers; extra == "all"
130
- Requires-Dist: setuptools; extra == "all"
129
+ Requires-Dist: flet-video; extra == "all"
130
+ Requires-Dist: regex; extra == "all"
131
+ Requires-Dist: dnspython[doh]; extra == "all"
132
+ Requires-Dist: distributed; extra == "all"
133
+ Requires-Dist: tinynetrc; extra == "all"
131
134
  Requires-Dist: pandas; extra == "all"
132
- Requires-Dist: pytest-cov; extra == "all"
133
- Requires-Dist: httpx_retries; extra == "all"
134
- Requires-Dist: logfire; extra == "all"
135
+ Requires-Dist: contexttimer; extra == "all"
136
+ Requires-Dist: peft; extra == "all"
137
+ Requires-Dist: pydantic; extra == "all"
138
+ Requires-Dist: google-auth; extra == "all"
139
+ Requires-Dist: tokenizers; extra == "all"
140
+ Requires-Dist: diskcache; extra == "all"
141
+ Requires-Dist: cachetools; extra == "all"
142
+ Requires-Dist: pymupdf; extra == "all"
135
143
  Requires-Dist: bokeh; extra == "all"
136
- Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
144
+ Requires-Dist: tabulate; extra == "all"
145
+ Requires-Dist: ollama; extra == "all"
146
+ Requires-Dist: Unidecode; extra == "all"
147
+ Requires-Dist: logfire; extra == "all"
148
+ Requires-Dist: sre_yield; extra == "all"
149
+ Requires-Dist: pyyaml; extra == "all"
150
+ Requires-Dist: deepmerge; extra == "all"
151
+ Requires-Dist: huggingface_hub; extra == "all"
152
+ Requires-Dist: openai; extra == "all"
137
153
  Requires-Dist: sentence_transformers; extra == "all"
138
- Requires-Dist: html2text; extra == "all"
154
+ Requires-Dist: openpyxl; extra == "all"
155
+ Requires-Dist: httpx_retries; extra == "all"
139
156
  Requires-Dist: flet-webview; extra == "all"
140
- Requires-Dist: transformers[sentencepiece]; extra == "all"
141
- Requires-Dist: pyyaml; extra == "all"
157
+ Requires-Dist: pytest-cov; extra == "all"
158
+ Requires-Dist: torchvision; extra == "all"
159
+ Requires-Dist: torchaudio; extra == "all"
142
160
  Requires-Dist: faker; extra == "all"
143
- Requires-Dist: fastapi; extra == "all"
144
- Requires-Dist: Unidecode; extra == "all"
145
- Requires-Dist: pymupdf; extra == "all"
146
- Requires-Dist: appdirs; extra == "all"
147
- Requires-Dist: sre_yield; extra == "all"
148
- Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
149
- Requires-Dist: peft; extra == "all"
150
- Requires-Dist: flet-video; extra == "all"
151
- Requires-Dist: diskcache; extra == "all"
152
- Requires-Dist: yamlscript; extra == "all"
153
- Requires-Dist: pymupdf4llm; extra == "all"
154
- Requires-Dist: filetype; extra == "all"
155
- Requires-Dist: ollama; extra == "all"
156
- Requires-Dist: google-auth; extra == "all"
157
161
  Requires-Dist: logfire[httpx]; extra == "all"
158
- Requires-Dist: uvicorn[standard]; extra == "all"
159
- Requires-Dist: tinynetrc; extra == "all"
160
- Requires-Dist: dnspython[doh]; extra == "all"
161
- Requires-Dist: google-auth-httplib2; extra == "all"
162
- Requires-Dist: pydantic; extra == "all"
162
+ Requires-Dist: flet[all]; extra == "all"
163
163
  Requires-Dist: google-api-python-client; extra == "all"
164
- Requires-Dist: docker; extra == "all"
165
- Requires-Dist: httpx; extra == "all"
166
- Requires-Dist: tabulate; extra == "all"
167
- Requires-Dist: huggingface_hub; extra == "all"
168
- Requires-Dist: regex; extra == "all"
169
- Requires-Dist: openpyxl; extra == "all"
170
- Requires-Dist: dask[bag]; extra == "all"
171
- Requires-Dist: distributed; extra == "all"
172
- Requires-Dist: openai; extra == "all"
173
- Requires-Dist: deepmerge; extra == "all"
174
164
  Requires-Dist: json_repair; extra == "all"
175
165
  Requires-Dist: google-auth-oauthlib; extra == "all"
176
- Requires-Dist: contexttimer; extra == "all"
166
+ Requires-Dist: fastapi; extra == "all"
167
+ Requires-Dist: yamlscript; extra == "all"
168
+ Requires-Dist: setuptools; extra == "all"
177
169
  Requires-Dist: semver; extra == "all"
170
+ Requires-Dist: pymupdf4llm; extra == "all"
171
+ Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
172
+ Requires-Dist: appdirs; extra == "all"
173
+ Requires-Dist: google-auth-httplib2; extra == "all"
178
174
  Requires-Dist: pydantic-settings; extra == "all"
179
- Requires-Dist: flet[all]; extra == "all"
180
- Requires-Dist: cachetools; extra == "all"
175
+ Requires-Dist: uvicorn[standard]; extra == "all"
176
+ Requires-Dist: httpx; extra == "all"
177
+ Requires-Dist: docker; extra == "all"
178
+ Requires-Dist: transformers[sentencepiece]; extra == "all"
179
+ Requires-Dist: dask[bag]; extra == "all"
180
+ Requires-Dist: filetype; extra == "all"
181
181
  Requires-Dist: logfire[fastapi]; extra == "all"
182
- Requires-Dist: torchaudio; extra == "all"
183
- Requires-Dist: torchvision; extra == "all"
182
+ Requires-Dist: html2text; extra == "all"
183
+ Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
184
184
  Dynamic: author
185
185
  Dynamic: author-email
186
186
  Dynamic: description
@@ -1 +0,0 @@
1
- 1.3.13
File without changes
File without changes
@@ -14,61 +14,61 @@ pydantic-ai[logfire,openai]
14
14
  ollama
15
15
 
16
16
  [all]
17
- tokenizers
18
- setuptools
17
+ flet-video
18
+ regex
19
+ dnspython[doh]
20
+ distributed
21
+ tinynetrc
19
22
  pandas
20
- pytest-cov
21
- httpx_retries
22
- logfire
23
+ contexttimer
24
+ peft
25
+ pydantic
26
+ google-auth
27
+ tokenizers
28
+ diskcache
29
+ cachetools
30
+ pymupdf
23
31
  bokeh
24
- pydevd-pycharm~=251.25410.159
32
+ tabulate
33
+ ollama
34
+ Unidecode
35
+ logfire
36
+ sre_yield
37
+ pyyaml
38
+ deepmerge
39
+ huggingface_hub
40
+ openai
25
41
  sentence_transformers
26
- html2text
42
+ openpyxl
43
+ httpx_retries
27
44
  flet-webview
28
- transformers[sentencepiece]
29
- pyyaml
45
+ pytest-cov
46
+ torchvision
47
+ torchaudio
30
48
  faker
31
- fastapi
32
- Unidecode
33
- pymupdf
34
- appdirs
35
- sre_yield
36
- pydantic-ai[logfire,openai]
37
- peft
38
- flet-video
39
- diskcache
40
- yamlscript
41
- pymupdf4llm
42
- filetype
43
- ollama
44
- google-auth
45
49
  logfire[httpx]
46
- uvicorn[standard]
47
- tinynetrc
48
- dnspython[doh]
49
- google-auth-httplib2
50
- pydantic
50
+ flet[all]
51
51
  google-api-python-client
52
- docker
53
- httpx
54
- tabulate
55
- huggingface_hub
56
- regex
57
- openpyxl
58
- dask[bag]
59
- distributed
60
- openai
61
- deepmerge
62
52
  json_repair
63
53
  google-auth-oauthlib
64
- contexttimer
54
+ fastapi
55
+ yamlscript
56
+ setuptools
65
57
  semver
58
+ pymupdf4llm
59
+ pydevd-pycharm~=251.25410.159
60
+ appdirs
61
+ google-auth-httplib2
66
62
  pydantic-settings
67
- flet[all]
68
- cachetools
63
+ uvicorn[standard]
64
+ httpx
65
+ docker
66
+ transformers[sentencepiece]
67
+ dask[bag]
68
+ filetype
69
69
  logfire[fastapi]
70
- torchaudio
71
- torchvision
70
+ html2text
71
+ pydantic-ai[logfire,openai]
72
72
 
73
73
  [api]
74
74
  fastapi
File without changes
File without changes
File without changes