pjx 0.0.1__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 (144) hide show
  1. pjx-0.0.1/.github/workflows/ci.yml +86 -0
  2. pjx-0.0.1/.github/workflows/release.yml +33 -0
  3. pjx-0.0.1/.gitignore +18 -0
  4. pjx-0.0.1/.python-version +1 -0
  5. pjx-0.0.1/.rumdl.toml +76 -0
  6. pjx-0.0.1/CLAUDE.md +106 -0
  7. pjx-0.0.1/LICENSE +21 -0
  8. pjx-0.0.1/PKG-INFO +430 -0
  9. pjx-0.0.1/README.md +393 -0
  10. pjx-0.0.1/docs/SECURITY.md +198 -0
  11. pjx-0.0.1/docs/dev/IDEA.md +1926 -0
  12. pjx-0.0.1/docs/dev/PLAN.md +830 -0
  13. pjx-0.0.1/docs/dev/SPEC.md +1673 -0
  14. pjx-0.0.1/docs/wiki/CLI-Reference.md +616 -0
  15. pjx-0.0.1/docs/wiki/CSS-and-Assets.md +449 -0
  16. pjx-0.0.1/docs/wiki/Compilation-Reference.md +562 -0
  17. pjx-0.0.1/docs/wiki/Component-Syntax.md +572 -0
  18. pjx-0.0.1/docs/wiki/Configuration-Reference.md +406 -0
  19. pjx-0.0.1/docs/wiki/Control-Flow.md +697 -0
  20. pjx-0.0.1/docs/wiki/Deployment.md +737 -0
  21. pjx-0.0.1/docs/wiki/FastAPI-Integration.md +558 -0
  22. pjx-0.0.1/docs/wiki/File-Based-Routing.md +512 -0
  23. pjx-0.0.1/docs/wiki/HTMX-Integration.md +1060 -0
  24. pjx-0.0.1/docs/wiki/Home.md +157 -0
  25. pjx-0.0.1/docs/wiki/Imports-and-Composition.md +406 -0
  26. pjx-0.0.1/docs/wiki/Installation.md +346 -0
  27. pjx-0.0.1/docs/wiki/Layout-Components.md +877 -0
  28. pjx-0.0.1/docs/wiki/Layouts-and-Inheritance.md +697 -0
  29. pjx-0.0.1/docs/wiki/Loading-States.md +589 -0
  30. pjx-0.0.1/docs/wiki/Middleware.md +510 -0
  31. pjx-0.0.1/docs/wiki/Project-Structure.md +516 -0
  32. pjx-0.0.1/docs/wiki/Props-and-Validation.md +601 -0
  33. pjx-0.0.1/docs/wiki/Quick-Start.md +575 -0
  34. pjx-0.0.1/docs/wiki/SSE-and-Realtime.md +707 -0
  35. pjx-0.0.1/docs/wiki/Security.md +653 -0
  36. pjx-0.0.1/docs/wiki/Slots.md +382 -0
  37. pjx-0.0.1/docs/wiki/State-and-Reactivity.md +919 -0
  38. pjx-0.0.1/docs/wiki/Template-Engines.md +559 -0
  39. pjx-0.0.1/docs/wiki/Troubleshooting.md +514 -0
  40. pjx-0.0.1/docs/wiki/_Footer.md +1 -0
  41. pjx-0.0.1/docs/wiki/_Sidebar.md +50 -0
  42. pjx-0.0.1/examples/demo/README.md +0 -0
  43. pjx-0.0.1/examples/demo/app/__init__.py +0 -0
  44. pjx-0.0.1/examples/demo/app/api/__init__.py +1 -0
  45. pjx-0.0.1/examples/demo/app/api/v1/__init__.py +5 -0
  46. pjx-0.0.1/examples/demo/app/api/v1/endpoints.py +22 -0
  47. pjx-0.0.1/examples/demo/app/core/__init__.py +1 -0
  48. pjx-0.0.1/examples/demo/app/core/config.py +13 -0
  49. pjx-0.0.1/examples/demo/app/main.py +147 -0
  50. pjx-0.0.1/examples/demo/app/middleware/__init__.py +9 -0
  51. pjx-0.0.1/examples/demo/app/middleware/security.py +51 -0
  52. pjx-0.0.1/examples/demo/app/models/__init__.py +5 -0
  53. pjx-0.0.1/examples/demo/app/models/schemas.py +19 -0
  54. pjx-0.0.1/examples/demo/app/pages/__init__.py +19 -0
  55. pjx-0.0.1/examples/demo/app/pages/routes.py +209 -0
  56. pjx-0.0.1/examples/demo/app/services/__init__.py +21 -0
  57. pjx-0.0.1/examples/demo/app/services/data.py +62 -0
  58. pjx-0.0.1/examples/demo/app/static/css/base.css +57 -0
  59. pjx-0.0.1/examples/demo/app/static/css/components.css +112 -0
  60. pjx-0.0.1/examples/demo/app/static/css/pjx-layout.css +32 -0
  61. pjx-0.0.1/examples/demo/app/static/images/alice.svg +1 -0
  62. pjx-0.0.1/examples/demo/app/static/images/bob.svg +1 -0
  63. pjx-0.0.1/examples/demo/app/static/images/charlie.svg +1 -0
  64. pjx-0.0.1/examples/demo/app/static/images/favicon.svg +4 -0
  65. pjx-0.0.1/examples/demo/app/static/js/app.js +27 -0
  66. pjx-0.0.1/examples/demo/app/templates/components/Clock.jinja +17 -0
  67. pjx-0.0.1/examples/demo/app/templates/components/Counter.jinja +10 -0
  68. pjx-0.0.1/examples/demo/app/templates/components/Navbar.jinja +13 -0
  69. pjx-0.0.1/examples/demo/app/templates/components/SearchBox.jinja +19 -0
  70. pjx-0.0.1/examples/demo/app/templates/components/SearchResult.jinja +15 -0
  71. pjx-0.0.1/examples/demo/app/templates/components/SearchResults.jinja +22 -0
  72. pjx-0.0.1/examples/demo/app/templates/components/ServerCounter.jinja +24 -0
  73. pjx-0.0.1/examples/demo/app/templates/components/Toast.jinja +10 -0
  74. pjx-0.0.1/examples/demo/app/templates/components/TodoItem.jinja +31 -0
  75. pjx-0.0.1/examples/demo/app/templates/components/TodoList.jinja +21 -0
  76. pjx-0.0.1/examples/demo/app/templates/components/TodoStats.jinja +15 -0
  77. pjx-0.0.1/examples/demo/app/templates/components/UserCard.jinja +18 -0
  78. pjx-0.0.1/examples/demo/app/templates/layouts/Base.jinja +84 -0
  79. pjx-0.0.1/examples/demo/app/templates/layouts/Basecoat.jinja +65 -0
  80. pjx-0.0.1/examples/demo/app/templates/pages/ClockDemo.jinja +15 -0
  81. pjx-0.0.1/examples/demo/app/templates/pages/ComponentsDemo.jinja +571 -0
  82. pjx-0.0.1/examples/demo/app/templates/pages/CounterDemo.jinja +23 -0
  83. pjx-0.0.1/examples/demo/app/templates/pages/Dashboard.jinja +29 -0
  84. pjx-0.0.1/examples/demo/app/templates/pages/Login.jinja +37 -0
  85. pjx-0.0.1/examples/demo/app/templates/pages/Protected.jinja +22 -0
  86. pjx-0.0.1/examples/demo/app/templates/pages/SearchDemo.jinja +20 -0
  87. pjx-0.0.1/examples/demo/app/templates/pages/TodoDemo.jinja +41 -0
  88. pjx-0.0.1/examples/demo/app/templates/ui/AspectRatio.jinja +12 -0
  89. pjx-0.0.1/examples/demo/app/templates/ui/Center.jinja +11 -0
  90. pjx-0.0.1/examples/demo/app/templates/ui/Container.jinja +12 -0
  91. pjx-0.0.1/examples/demo/app/templates/ui/Divider.jinja +7 -0
  92. pjx-0.0.1/examples/demo/app/templates/ui/Grid.jinja +14 -0
  93. pjx-0.0.1/examples/demo/app/templates/ui/HStack.jinja +14 -0
  94. pjx-0.0.1/examples/demo/app/templates/ui/Hide.jinja +13 -0
  95. pjx-0.0.1/examples/demo/app/templates/ui/Spacer.jinja +7 -0
  96. pjx-0.0.1/examples/demo/app/templates/ui/VStack.jinja +14 -0
  97. pjx-0.0.1/examples/demo/app/templates/ui/Wrap.jinja +12 -0
  98. pjx-0.0.1/examples/demo/package-lock.json +18 -0
  99. pjx-0.0.1/examples/demo/package.json +5 -0
  100. pjx-0.0.1/examples/demo/pjx.toml +23 -0
  101. pjx-0.0.1/examples/demo/pyproject.toml +7 -0
  102. pjx-0.0.1/pyproject.toml +122 -0
  103. pjx-0.0.1/skills/pjx/SKILL.md +891 -0
  104. pjx-0.0.1/src/pjx/__init__.py +38 -0
  105. pjx-0.0.1/src/pjx/__main__.py +5 -0
  106. pjx-0.0.1/src/pjx/assets.py +116 -0
  107. pjx-0.0.1/src/pjx/ast_nodes.py +355 -0
  108. pjx-0.0.1/src/pjx/checker.py +82 -0
  109. pjx-0.0.1/src/pjx/cli/__init__.py +24 -0
  110. pjx-0.0.1/src/pjx/cli/build.py +143 -0
  111. pjx-0.0.1/src/pjx/cli/dev.py +130 -0
  112. pjx-0.0.1/src/pjx/cli/init.py +615 -0
  113. pjx-0.0.1/src/pjx/cli/packages.py +85 -0
  114. pjx-0.0.1/src/pjx/compiler.py +619 -0
  115. pjx-0.0.1/src/pjx/config.py +109 -0
  116. pjx-0.0.1/src/pjx/css.py +129 -0
  117. pjx-0.0.1/src/pjx/engine.py +129 -0
  118. pjx-0.0.1/src/pjx/errors.py +65 -0
  119. pjx-0.0.1/src/pjx/handler.py +115 -0
  120. pjx-0.0.1/src/pjx/health.py +36 -0
  121. pjx-0.0.1/src/pjx/integration.py +710 -0
  122. pjx-0.0.1/src/pjx/layout.py +45 -0
  123. pjx-0.0.1/src/pjx/lexer.py +246 -0
  124. pjx-0.0.1/src/pjx/log.py +55 -0
  125. pjx-0.0.1/src/pjx/middleware/__init__.py +5 -0
  126. pjx-0.0.1/src/pjx/middleware/csrf.py +174 -0
  127. pjx-0.0.1/src/pjx/parser.py +971 -0
  128. pjx-0.0.1/src/pjx/props.py +202 -0
  129. pjx-0.0.1/src/pjx/registry.py +181 -0
  130. pjx-0.0.1/src/pjx/router.py +406 -0
  131. pjx-0.0.1/src/pjx/slots.py +44 -0
  132. pjx-0.0.1/src/pjx/sse.py +166 -0
  133. pjx-0.0.1/src/pjx/static/pjx-layout.css +32 -0
  134. pjx-0.0.1/src/pjx/ui/layouts/AspectRatio.jinja +12 -0
  135. pjx-0.0.1/src/pjx/ui/layouts/Center.jinja +11 -0
  136. pjx-0.0.1/src/pjx/ui/layouts/Container.jinja +12 -0
  137. pjx-0.0.1/src/pjx/ui/layouts/Divider.jinja +7 -0
  138. pjx-0.0.1/src/pjx/ui/layouts/Grid.jinja +14 -0
  139. pjx-0.0.1/src/pjx/ui/layouts/HStack.jinja +14 -0
  140. pjx-0.0.1/src/pjx/ui/layouts/Hide.jinja +13 -0
  141. pjx-0.0.1/src/pjx/ui/layouts/Spacer.jinja +7 -0
  142. pjx-0.0.1/src/pjx/ui/layouts/VStack.jinja +14 -0
  143. pjx-0.0.1/src/pjx/ui/layouts/Wrap.jinja +12 -0
  144. pjx-0.0.1/uv.lock +1021 -0
@@ -0,0 +1,86 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master, dev]
6
+ pull_request:
7
+ branches: [main, master]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v6
17
+
18
+ - name: Set up Python
19
+ run: uv python install 3.13
20
+
21
+ - name: Install dependencies
22
+ run: uv sync --group dev --group test
23
+
24
+ - name: Format check
25
+ run: uv run ruff format --check --output-format github .
26
+
27
+ - name: Lint
28
+ run: uv run ruff check --output-format github .
29
+
30
+ typecheck:
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+
35
+ - name: Install uv
36
+ uses: astral-sh/setup-uv@v6
37
+
38
+ - name: Set up Python
39
+ run: uv python install 3.13
40
+
41
+ - name: Install dependencies
42
+ run: uv sync --group dev --group test
43
+
44
+ - name: Type check
45
+ run: uv run ty check --output-format github src/
46
+
47
+ test:
48
+ runs-on: ubuntu-latest
49
+ strategy:
50
+ matrix:
51
+ python-version: ["3.13", "3.14"]
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+
55
+ - name: Install uv
56
+ uses: astral-sh/setup-uv@v6
57
+
58
+ - name: Set up Python ${{ matrix.python-version }}
59
+ run: uv python install ${{ matrix.python-version }}
60
+
61
+ - name: Install dependencies
62
+ run: uv sync --group test
63
+
64
+ - name: Run tests
65
+ run: uv run pytest -v --ignore=tests/benchmark --tb=short
66
+
67
+ build:
68
+ runs-on: ubuntu-latest
69
+ needs: [lint, typecheck, test]
70
+ steps:
71
+ - uses: actions/checkout@v4
72
+
73
+ - name: Install uv
74
+ uses: astral-sh/setup-uv@v6
75
+
76
+ - name: Set up Python
77
+ run: uv python install 3.13
78
+
79
+ - name: Build package
80
+ run: uv build
81
+
82
+ - name: Upload artifacts
83
+ uses: actions/upload-artifact@v4
84
+ with:
85
+ name: dist
86
+ path: dist/
@@ -0,0 +1,33 @@
1
+ name: Release
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ id-token: write
9
+
10
+ jobs:
11
+ publish:
12
+ runs-on: ubuntu-latest
13
+ environment: pypi
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v6
19
+
20
+ - name: Set up Python
21
+ run: uv python install 3.13
22
+
23
+ - name: Install dependencies
24
+ run: uv sync --group test
25
+
26
+ - name: Run tests
27
+ run: uv run pytest -v --ignore=tests/benchmark --tb=short
28
+
29
+ - name: Build package
30
+ run: uv build
31
+
32
+ - name: Publish to PyPI
33
+ uses: pypa/gh-action-pypi-publish@release/v1
pjx-0.0.1/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+ .pytest_cache/
12
+ .env
13
+ .ruff_cache/
14
+ .rumdl_cache/
15
+ .benchmarks
16
+
17
+ node_modules/
18
+ **/static/vendor/
@@ -0,0 +1 @@
1
+ 3.14
pjx-0.0.1/.rumdl.toml ADDED
@@ -0,0 +1,76 @@
1
+ # rumdl configuration file
2
+
3
+ # Inherit settings from another config file (relative to this file's directory)
4
+ # extends = "../base.rumdl.toml"
5
+
6
+ # Global configuration options
7
+ [global]
8
+ # List of rules to disable (uncomment and modify as needed)
9
+ # disable = ["MD013", "MD033"]
10
+
11
+ # List of rules to enable exclusively (replaces defaults; only these rules will run)
12
+ # enable = ["MD001", "MD003", "MD004"]
13
+
14
+ # Additional rules to enable on top of defaults (additive, does not replace)
15
+ # Use this to activate opt-in rules like MD060, MD063, MD072, MD073, MD074
16
+ # extend-enable = ["MD060", "MD063"]
17
+
18
+ # Additional rules to disable on top of the disable list (additive)
19
+ # extend-disable = ["MD041"]
20
+
21
+ # List of file/directory patterns to include for linting (if provided, only these will be linted)
22
+ # include = [
23
+ # "docs/*.md",
24
+ # "src/**/*.md",
25
+ # "README.md"
26
+ # ]
27
+
28
+ # List of file/directory patterns to exclude from linting
29
+ exclude = [
30
+ # Common directories to exclude
31
+ ".git",
32
+ ".github",
33
+ "node_modules",
34
+ "vendor",
35
+ "dist",
36
+ "build",
37
+
38
+ # Specific files or patterns
39
+ "CHANGELOG.md",
40
+ "LICENSE.md",
41
+ ]
42
+
43
+ # Respect .gitignore files when scanning directories (default: true)
44
+ respect-gitignore = true
45
+
46
+ # Markdown flavor/dialect (uncomment to enable)
47
+ # Options: standard (default), gfm, commonmark, mkdocs, mdx, quarto
48
+ # flavor = "mkdocs"
49
+
50
+ # Rule-specific configurations (uncomment and modify as needed)
51
+
52
+ # [MD003]
53
+ # style = "atx" # Heading style (atx, atx_closed, setext)
54
+
55
+ # [MD004]
56
+ # style = "asterisk" # Unordered list style (asterisk, plus, dash, consistent)
57
+
58
+ # [MD007]
59
+ # indent = 4 # Unordered list indentation
60
+
61
+ # [MD013]
62
+ # line-length = 100 # Line length
63
+ # code-blocks = false # Exclude code blocks from line length check
64
+ # tables = false # Exclude tables from line length check
65
+ # headings = true # Include headings in line length check
66
+
67
+ # [MD044]
68
+ # names = ["rumdl", "Markdown", "GitHub"] # Proper names that should be capitalized correctly
69
+ # code-blocks = false # Check code blocks for proper names (default: false, skips code blocks)
70
+
71
+ [MD013]
72
+ line-length = 0
73
+
74
+ [MD060]
75
+ enabled = true
76
+ style = "aligned"
pjx-0.0.1/CLAUDE.md ADDED
@@ -0,0 +1,106 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project
6
+
7
+ PJX is a Python DSL for reactive `.jinja` components, inspired by JSX, Svelte
8
+ and SolidJS. It compiles a declarative component syntax (props, state, slots,
9
+ imports, control flow) down to Jinja2 + HTMX + Alpine.js. The full DSL
10
+ specification lives in `docs/dev/IDEA.md`, technical spec in `docs/dev/SPEC.md`.
11
+
12
+ ## Stack
13
+
14
+ - **Language**: Python 3.14+
15
+ - **Package manager**: uv
16
+ - **Linter/Formatter**: ruff
17
+ - **Type checker**: ty
18
+ - **Test runner**: pytest
19
+ - **Markdown lint**: rumdl
20
+ - **Runtime deps**: FastAPI, Jinja2, minijinja, Pydantic, Rich, Typer, Uvicorn
21
+
22
+ ## Quick Commands
23
+
24
+ ```bash
25
+ rtk uv sync # Install deps from lockfile
26
+ rtk uv run task format # Format (ruff)
27
+ rtk uv run task lint # Lint + autofix (ruff)
28
+ rtk uv run task check # Format + lint + markdown lint
29
+ rtk uv run task typecheck # Type check (ty)
30
+ rtk uv run task test # Run all tests
31
+ rtk uv run task cov # Tests with coverage report
32
+ rtk uv run task ci # Full CI: check + typecheck + test
33
+ rtk uv run pytest tests/test_foo.py::test_bar -v # Single test
34
+ ```
35
+
36
+ ## Validation (run in order, fail fast)
37
+
38
+ ```bash
39
+ rtk uv run task ci
40
+ ```
41
+
42
+ Or manually:
43
+
44
+ ```bash
45
+ rtk uv run task check
46
+ rtk uv run task typecheck
47
+ rtk uv run task test
48
+ ```
49
+
50
+ ## Skills
51
+
52
+ On-demand knowledge modules in `.agents/skills/`. Load the relevant skill
53
+ when working in its domain.
54
+
55
+ | Skill | When to use |
56
+ | ------------------- | ------------------------------------------------- |
57
+ | `python/SKILL.md` | Python code, conventions, async, uv toolchain |
58
+ | `fastapi/SKILL.md` | FastAPI routes, dependencies, middleware |
59
+ | `jx/SKILL.md` | Jinja server-rendered components (JX patterns) |
60
+ | `frontend/SKILL.md` | JS/CSS tooling, Tailwind, Alpine.js, HTMX |
61
+ | `commit/SKILL.md` | Small logical commits with conventional messages |
62
+ | `refactor/SKILL.md` | Code audit, clean code, SOLID, security review |
63
+
64
+ Each skill has a `references/` folder with detailed submodules. Load on demand.
65
+
66
+ ## Conventions
67
+
68
+ - Use `pathlib` over `os.path`
69
+ - f-strings only
70
+ - `snake_case` functions/variables, `PascalCase` classes, `UPPER_SNAKE` constants
71
+ - Type all public functions
72
+ - Use `Annotated` style for FastAPI parameters and dependencies
73
+ - `logging` for app logs, `rich` for CLI output — never `print`
74
+ - Pydantic `BaseModel` for validation, `dataclass` for plain data
75
+ - IO at edges only — services and domain must be pure
76
+ - Prefer `uv` over direct `pip` workflows
77
+ - Never commit code that fails `ruff check`
78
+
79
+ ## Code Quality
80
+
81
+ - **Clean Code**: small single-responsibility functions, descriptive names
82
+ that make comments unnecessary, no dead or duplicated code
83
+ - **Pythonic**: use language idioms (comprehensions, context managers,
84
+ itertools, `enumerate`, unpacking) — avoid C-style loops
85
+ - **SOLID**: each module/class has a single reason to change (SRP), depend
86
+ on abstractions not concrete implementations (DIP), prefer composition
87
+ over inheritance
88
+ - **Type safety**: type hints on all public functions and models; use
89
+ `Protocol` / `ABC` for contracts between layers
90
+
91
+ ## Tests
92
+
93
+ - All new or changed code must include tests
94
+ - Keep coverage high — cover happy path, edge cases, and expected errors
95
+ - Unit tests for pure logic, integration tests for IO and endpoints
96
+ - Descriptive test names: `test_<unit>_<scenario>_<expected>`
97
+ - Use fixtures and parametrize to avoid repetition
98
+
99
+ ## Documentation
100
+
101
+ - Update docstrings (Google style) on all public functions/classes created
102
+ or modified
103
+ - Keep `README.md` up to date when installation, usage, or architecture changes
104
+ - Add usage examples in `examples/` for each public feature — short
105
+ self-contained scripts that demonstrate real API usage
106
+ - Update `docs/dev/IDEA.md` if the implementation diverges from the spec
pjx-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fabio Souza
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.