TypeDAL 4.4.2__tar.gz → 4.4.3__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.
Files changed (74) hide show
  1. {typedal-4.4.2 → typedal-4.4.3}/.crush/crush.db-shm +0 -0
  2. typedal-4.4.3/.crush/crush.db-wal +0 -0
  3. {typedal-4.4.2 → typedal-4.4.3}/.crush/logs/crush.log +9 -0
  4. {typedal-4.4.2 → typedal-4.4.3}/CHANGELOG.md +6 -0
  5. {typedal-4.4.2 → typedal-4.4.3}/PKG-INFO +3 -2
  6. {typedal-4.4.2 → typedal-4.4.3}/mkdocs.yml +2 -1
  7. {typedal-4.4.2 → typedal-4.4.3}/pyproject.toml +2 -1
  8. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/__about__.py +1 -1
  9. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/config.py +2 -84
  10. typedal-4.4.3/tasks.py +54 -0
  11. typedal-4.4.2/.crush/crush.db-wal +0 -0
  12. {typedal-4.4.2 → typedal-4.4.3}/.crush/.gitignore +0 -0
  13. {typedal-4.4.2 → typedal-4.4.3}/.crush/init +0 -0
  14. {typedal-4.4.2 → typedal-4.4.3}/.github/workflows/su6.yml +0 -0
  15. {typedal-4.4.2 → typedal-4.4.3}/.gitignore +0 -0
  16. {typedal-4.4.2 → typedal-4.4.3}/.readthedocs.yml +0 -0
  17. {typedal-4.4.2 → typedal-4.4.3}/README.md +0 -0
  18. {typedal-4.4.2 → typedal-4.4.3}/coverage.svg +0 -0
  19. {typedal-4.4.2 → typedal-4.4.3}/docs/1_getting_started.md +0 -0
  20. {typedal-4.4.2 → typedal-4.4.3}/docs/2_defining_tables.md +0 -0
  21. {typedal-4.4.2 → typedal-4.4.3}/docs/3_building_queries.md +0 -0
  22. {typedal-4.4.2 → typedal-4.4.3}/docs/4_relationships.md +0 -0
  23. {typedal-4.4.2 → typedal-4.4.3}/docs/5_py4web.md +0 -0
  24. {typedal-4.4.2 → typedal-4.4.3}/docs/6_migrations.md +0 -0
  25. {typedal-4.4.2 → typedal-4.4.3}/docs/7_configuration.md +0 -0
  26. {typedal-4.4.2 → typedal-4.4.3}/docs/8_mixins.md +0 -0
  27. {typedal-4.4.2 → typedal-4.4.3}/docs/9_memoization.md +0 -0
  28. {typedal-4.4.2 → typedal-4.4.3}/docs/css/code_blocks.css +0 -0
  29. {typedal-4.4.2 → typedal-4.4.3}/docs/index.md +0 -0
  30. {typedal-4.4.2 → typedal-4.4.3}/docs/requirements.txt +0 -0
  31. {typedal-4.4.2 → typedal-4.4.3}/example_new.py +0 -0
  32. {typedal-4.4.2 → typedal-4.4.3}/example_old.py +0 -0
  33. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/__init__.py +0 -0
  34. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/caching.py +0 -0
  35. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/cli.py +0 -0
  36. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/constants.py +0 -0
  37. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/core.py +0 -0
  38. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/define.py +0 -0
  39. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/fields.py +0 -0
  40. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/for_py4web.py +0 -0
  41. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/for_web2py.py +0 -0
  42. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/helpers.py +0 -0
  43. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/mixins.py +0 -0
  44. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/py.typed +0 -0
  45. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/query_builder.py +0 -0
  46. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/relationships.py +0 -0
  47. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/rows.py +0 -0
  48. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/serializers/as_json.py +0 -0
  49. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/tables.py +0 -0
  50. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/types.py +0 -0
  51. {typedal-4.4.2 → typedal-4.4.3}/src/typedal/web2py_py4web_shared.py +0 -0
  52. {typedal-4.4.2 → typedal-4.4.3}/tests/__init__.py +0 -0
  53. {typedal-4.4.2 → typedal-4.4.3}/tests/configs/simple.toml +0 -0
  54. {typedal-4.4.2 → typedal-4.4.3}/tests/configs/valid.env +0 -0
  55. {typedal-4.4.2 → typedal-4.4.3}/tests/configs/valid.toml +0 -0
  56. {typedal-4.4.2 → typedal-4.4.3}/tests/py314_tests.py +0 -0
  57. {typedal-4.4.2 → typedal-4.4.3}/tests/test_cli.py +0 -0
  58. {typedal-4.4.2 → typedal-4.4.3}/tests/test_config.py +0 -0
  59. {typedal-4.4.2 → typedal-4.4.3}/tests/test_docs_examples.py +0 -0
  60. {typedal-4.4.2 → typedal-4.4.3}/tests/test_helpers.py +0 -0
  61. {typedal-4.4.2 → typedal-4.4.3}/tests/test_json.py +0 -0
  62. {typedal-4.4.2 → typedal-4.4.3}/tests/test_main.py +0 -0
  63. {typedal-4.4.2 → typedal-4.4.3}/tests/test_mixins.py +0 -0
  64. {typedal-4.4.2 → typedal-4.4.3}/tests/test_mypy.py +0 -0
  65. {typedal-4.4.2 → typedal-4.4.3}/tests/test_orm.py +0 -0
  66. {typedal-4.4.2 → typedal-4.4.3}/tests/test_py4web.py +0 -0
  67. {typedal-4.4.2 → typedal-4.4.3}/tests/test_query_builder.py +0 -0
  68. {typedal-4.4.2 → typedal-4.4.3}/tests/test_relationships.py +0 -0
  69. {typedal-4.4.2 → typedal-4.4.3}/tests/test_row.py +0 -0
  70. {typedal-4.4.2 → typedal-4.4.3}/tests/test_stats.py +0 -0
  71. {typedal-4.4.2 → typedal-4.4.3}/tests/test_table.py +0 -0
  72. {typedal-4.4.2 → typedal-4.4.3}/tests/test_web2py.py +0 -0
  73. {typedal-4.4.2 → typedal-4.4.3}/tests/test_xx_others.py +0 -0
  74. {typedal-4.4.2 → typedal-4.4.3}/tests/timings.py +0 -0
Binary file
@@ -23,3 +23,12 @@
23
23
  {"time":"2026-01-26T17:11:34.786142525+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.(*App).createAndStartLSPClient","file":"github.com/charmbracelet/crush/internal/app/lsp.go","line":76},"msg":"LSP client initialized","name":"python"}
24
24
  {"time":"2026-01-26T17:11:43.042930337+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
25
25
  {"time":"2026-01-26T17:11:44.911909276+01:00","level":"WARN","source":{"function":"github.com/charmbracelet/crush/internal/agent/tools.init.func1","file":"github.com/charmbracelet/crush/internal/agent/tools/rg.go","line":18},"msg":"Ripgrep (rg) not found in $PATH. Some grep features might be limited or slower."}
26
+ {"time":"2026-01-26T18:10:19.727802782+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/config.(*catwalkSync).Get.func1","file":"github.com/charmbracelet/crush/internal/config/catwalk.go","line":55},"msg":"Fetching providers from Catwalk"}
27
+ {"time":"2026-01-26T18:10:19.926137244+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/config.(*catwalkSync).Get.func1","file":"github.com/charmbracelet/crush/internal/config/catwalk.go","line":63},"msg":"Catwalk providers not modified"}
28
+ {"time":"2026-01-26T18:10:19.926245207+01:00","level":"WARN","source":{"function":"github.com/charmbracelet/crush/internal/config.(*Config).configureProviders","file":"github.com/charmbracelet/crush/internal/config/load.go","line":259},"msg":"Skipping provider due to missing API key","provider":"anthropic"}
29
+ {"time":"2026-01-26T18:10:19.927808467+01:00","level":"INFO","msg":"goose: no migrations to run. current version: 20250812000000"}
30
+ {"time":"2026-01-26T18:10:19.927858435+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.(*App).initLSPClients","file":"github.com/charmbracelet/crush/internal/app/lsp.go","line":21},"msg":"LSP clients initialization started in background"}
31
+ {"time":"2026-01-26T18:10:19.928006013+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.New.func1","file":"github.com/charmbracelet/crush/internal/app/app.go","line":110},"msg":"Initializing MCP clients"}
32
+ {"time":"2026-01-26T18:10:20.546676356+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.(*App).createAndStartLSPClient","file":"github.com/charmbracelet/crush/internal/app/lsp.go","line":76},"msg":"LSP client initialized","name":"python"}
33
+ {"time":"2026-01-26T18:11:07.640056766+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
34
+ {"time":"2026-01-26T18:11:11.201161834+01:00","level":"WARN","source":{"function":"github.com/charmbracelet/crush/internal/agent/tools.init.func1","file":"github.com/charmbracelet/crush/internal/agent/tools/rg.go","line":18},"msg":"Ripgrep (rg) not found in $PATH. Some grep features might be limited or slower."}
@@ -2,6 +2,12 @@
2
2
 
3
3
  <!--next-version-placeholder-->
4
4
 
5
+ ## v4.4.3 (2026-02-11)
6
+
7
+ ### Fix
8
+
9
+ * Move env shell-style expansion to configuraptor, improved functionality using expandvars instead of custom implementation ([`8b41b91`](https://github.com/trialandsuccess/TypeDAL/commit/8b41b91d55c8893d5ce15c2decf6daa855fa230b))
10
+
5
11
  ## v4.4.2 (2026-01-26)
6
12
 
7
13
  ### Fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TypeDAL
3
- Version: 4.4.2
3
+ Version: 4.4.3
4
4
  Summary: Typing support for PyDAL
5
5
  Project-URL: Documentation, https://typedal.readthedocs.io/
6
6
  Project-URL: Issues, https://github.com/trialandsuccess/TypeDAL/issues
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
16
16
  Classifier: Programming Language :: Python :: Implementation :: PyPy
17
17
  Requires-Python: >=3.11
18
18
  Requires-Dist: configurable-json<2
19
- Requires-Dist: configuraptor<2,>=1.27.1
19
+ Requires-Dist: configuraptor<3,>=2.0.1
20
20
  Requires-Dist: dill<1
21
21
  Requires-Dist: legacy-cgi; python_version >= '3.13'
22
22
  Requires-Dist: pydal>=20251012.3
@@ -32,6 +32,7 @@ Requires-Dist: tomlkit; extra == 'all'
32
32
  Requires-Dist: typer<0.19,>=0.18; extra == 'all'
33
33
  Provides-Extra: dev
34
34
  Requires-Dist: contextlib-chdir; extra == 'dev'
35
+ Requires-Dist: ewok; extra == 'dev'
35
36
  Requires-Dist: hatch; extra == 'dev'
36
37
  Requires-Dist: mkdocs; extra == 'dev'
37
38
  Requires-Dist: mkdocs-dracula-theme; extra == 'dev'
@@ -6,10 +6,11 @@ nav:
6
6
  - 2. Defining Tables: 2_defining_tables.md
7
7
  - 3. Building Queries: 3_building_queries.md
8
8
  - 4. Relationships: 4_relationships.md
9
- - 5. py4web: 5_py4web.md
9
+ - 5. py4web and web2py: 5_py4web.md
10
10
  - 6. Migrations: 6_migrations.md
11
11
  - 7. Configuration: 7_configuration.md
12
12
  - 8. Mixins: 8_mixins.md
13
+ - 9. Function Memoization: 9_memoization.md
13
14
  extra:
14
15
  version:
15
16
  default: stable
@@ -29,7 +29,7 @@ classifiers = [
29
29
  dependencies = [
30
30
  "pydal >= 20251012.3", # core
31
31
  "dill < 1", # caching
32
- "configuraptor >= 1.27.1, < 2", # config
32
+ "configuraptor >= 2.0.1, < 3", # config
33
33
  "Configurable-JSON < 2", # json dumping
34
34
  "python-slugify < 9",
35
35
  "legacy-cgi; python_version >= '3.13'",
@@ -63,6 +63,7 @@ all = [
63
63
  dev = [
64
64
  # build:
65
65
  "hatch",
66
+ "ewok",
66
67
  # test:
67
68
  "su6[all]>=1.9.0",
68
69
  "python-semantic-release < 8",
@@ -5,4 +5,4 @@ This file contains the Version info for this package.
5
5
  # SPDX-FileCopyrightText: 2023-present Robin van der Noord <robinvandernoord@gmail.com>
6
6
  #
7
7
  # SPDX-License-Identifier: MIT
8
- __version__ = "4.4.2"
8
+ __version__ = "4.4.3"
@@ -3,10 +3,8 @@ TypeDAL can be configured by a combination of pyproject.toml (static), env (dyna
3
3
  """
4
4
 
5
5
  import os
6
- import re
7
6
  import typing as t
8
7
  import warnings
9
- from collections import defaultdict
10
8
  from pathlib import Path
11
9
 
12
10
  import tomli
@@ -16,6 +14,8 @@ from dotenv import dotenv_values, find_dotenv
16
14
 
17
15
  from .types import AnyDict
18
16
 
17
+ from configuraptor.helpers import expand_env_vars_into_toml_values
18
+
19
19
  if t.TYPE_CHECKING:
20
20
  from edwh_migrate import Config as MigrateConfig
21
21
  from pydal2sql.typer_support import Config as P2SConfig
@@ -244,88 +244,6 @@ def transform(data: AnyDict, prop: str) -> bool:
244
244
  return False
245
245
 
246
246
 
247
- def expand_posix_vars(posix_expr: str, context: dict[str, str]) -> str:
248
- """
249
- Replace case-insensitive POSIX and Docker Compose-like environment variables in a string with their values.
250
-
251
- Args:
252
- posix_expr (str): The input string containing case-insensitive POSIX or Docker Compose-like variables.
253
- context (dict): A dictionary containing variable names and their respective values.
254
-
255
- Returns:
256
- str: The string with replaced variable values.
257
-
258
- See Also:
259
- https://stackoverflow.com/questions/386934/how-to-evaluate-environment-variables-into-a-string-in-python
260
- and ChatGPT
261
- """
262
- env = defaultdict(lambda: "")
263
- for key, value in context.items():
264
- env[key.lower()] = value
265
-
266
- # Regular expression to match "${VAR:default}" pattern
267
- pattern = r"\$\{([^}]+)\}"
268
-
269
- def replace_var(match: re.Match[t.Any]) -> str:
270
- var_with_default = match.group(1)
271
- var_name, default_value = var_with_default.split(":") if ":" in var_with_default else (var_with_default, "")
272
- return env.get(var_name.lower(), default_value)
273
-
274
- return re.sub(pattern, replace_var, posix_expr)
275
-
276
-
277
- def expand_env_vars_into_toml_values(toml: AnyDict, env: AnyDict) -> None:
278
- """
279
- Recursively expands POSIX/Docker Compose-like environment variables in a TOML dictionary.
280
-
281
- This function traverses a TOML dictionary and expands POSIX/Docker Compose-like
282
- environment variables (${VAR:default}) using values provided in the 'env' dictionary.
283
- It performs in-place modification of the 'toml' dictionary.
284
-
285
- Args:
286
- toml (dict): A TOML dictionary with string values possibly containing environment variables.
287
- env (dict): A dictionary containing environment variable names and their respective values.
288
-
289
- Returns:
290
- None: The function modifies the 'toml' dictionary in place.
291
-
292
- Notes:
293
- The function recursively traverses the 'toml' dictionary. If a value is a string or a list of strings,
294
- it attempts to substitute any environment variables found within those strings using the 'env' dictionary.
295
-
296
- Example:
297
- toml_data = {
298
- 'key1': 'This has ${ENV_VAR:default}',
299
- 'key2': ['String with ${ANOTHER_VAR}', 'Another ${YET_ANOTHER_VAR}']
300
- }
301
- environment = {
302
- 'ENV_VAR': 'replaced_value',
303
- 'ANOTHER_VAR': 'value_1',
304
- 'YET_ANOTHER_VAR': 'value_2'
305
- }
306
-
307
- expand_env_vars_into_toml_values(toml_data, environment)
308
- # 'toml_data' will be modified in place:
309
- # {
310
- # 'key1': 'This has replaced_value',
311
- # 'key2': ['String with value_1', 'Another value_2']
312
- # }
313
- """
314
- if not toml or not env:
315
- return
316
-
317
- for key, var in toml.items():
318
- if isinstance(var, dict):
319
- expand_env_vars_into_toml_values(var, env)
320
- elif isinstance(var, list):
321
- toml[key] = [expand_posix_vars(_, env) for _ in var if isinstance(_, str)]
322
- elif isinstance(var, str):
323
- toml[key] = expand_posix_vars(var, env)
324
- else:
325
- # nothing to substitute
326
- continue
327
-
328
-
329
247
  def load_config(
330
248
  connection_name: t.Optional[str] = None,
331
249
  _use_pyproject: bool | str | None = True,
typedal-4.4.3/tasks.py ADDED
@@ -0,0 +1,54 @@
1
+ """Task automation using ewok (invoke-compatible)."""
2
+
3
+ import re
4
+ from pathlib import Path
5
+
6
+ from ewok import Context, task
7
+
8
+ # Compiled regex pattern for replacing the nav section in mkdocs.yml
9
+ NAV_SECTION_PATTERN = re.compile(r"nav:.*?(?=\n[a-z_]+:|$)", re.DOTALL)
10
+
11
+
12
+ def extract_title(md_file: Path) -> str:
13
+ """Extract the title from a markdown file's first heading."""
14
+ first_line = md_file.read_text(encoding="utf-8").split("\n", 1)[0].strip()
15
+ # Remove the leading # and any extra whitespace
16
+ return first_line.lstrip("#").strip()
17
+
18
+
19
+ def generate_nav_entries() -> list[str]:
20
+ """Generate nav entries from numbered markdown files in docs/."""
21
+ docs_dir = Path(__file__).parent / "docs"
22
+
23
+ # Find all numbered chapter files (supports 1-N digits)
24
+ chapters = [f for f in docs_dir.glob("*_*.md") if f.stem.split("_", 1)[0].isdigit()]
25
+
26
+ return [
27
+ f" - {extract_title(chapter)}: {chapter.name}"
28
+ for chapter in sorted(
29
+ chapters,
30
+ key=lambda f: int(f.stem.split("_", 1)[0]),
31
+ )
32
+ ]
33
+
34
+
35
+ @task
36
+ def update_docs_nav(ctx: Context) -> None:
37
+ """Update mkdocs.yml nav section from actual markdown files to prevent sync issues."""
38
+ mkdocs_file = Path(__file__).parent / "mkdocs.yml"
39
+
40
+ content = mkdocs_file.read_text(encoding="utf-8")
41
+
42
+ # Generate new nav entries
43
+ nav_entries = generate_nav_entries()
44
+ new_nav_section = "nav:\n" + "\n".join(nav_entries)
45
+
46
+ # Replace the nav section
47
+ updated_content = NAV_SECTION_PATTERN.sub(new_nav_section, content)
48
+
49
+ mkdocs_file.write_text(updated_content, encoding="utf-8")
50
+
51
+ print(f"✓ Updated mkdocs.yml with {len(nav_entries)} chapters")
52
+ print("\nGenerated nav:")
53
+ for entry in nav_entries:
54
+ print(entry)
Binary file
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes