imp-git 0.0.26__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.
- imp/__init__.py +7 -0
- imp/__main__.py +3 -0
- imp/ai.py +130 -0
- imp/commands/__init__.py +0 -0
- imp/commands/amend.py +68 -0
- imp/commands/branch.py +72 -0
- imp/commands/clean.py +47 -0
- imp/commands/commit.py +67 -0
- imp/commands/config.py +62 -0
- imp/commands/doctor.py +87 -0
- imp/commands/done.py +98 -0
- imp/commands/fix.py +78 -0
- imp/commands/help.py +103 -0
- imp/commands/log.py +25 -0
- imp/commands/pr.py +125 -0
- imp/commands/push.py +42 -0
- imp/commands/release.py +273 -0
- imp/commands/resolve.py +161 -0
- imp/commands/revert.py +83 -0
- imp/commands/review.py +76 -0
- imp/commands/ship.py +131 -0
- imp/commands/split.py +176 -0
- imp/commands/status.py +96 -0
- imp/commands/sync.py +64 -0
- imp/commands/undo.py +45 -0
- imp/config.py +51 -0
- imp/console.py +168 -0
- imp/git.py +428 -0
- imp/main.py +74 -0
- imp/prompts.py +168 -0
- imp/theme.py +14 -0
- imp/validate.py +28 -0
- imp/version.py +67 -0
- imp_git-0.0.26.dist-info/METADATA +226 -0
- imp_git-0.0.26.dist-info/RECORD +38 -0
- imp_git-0.0.26.dist-info/WHEEL +4 -0
- imp_git-0.0.26.dist-info/entry_points.txt +2 -0
- imp_git-0.0.26.dist-info/licenses/LICENSE +21 -0
imp/version.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def bump (current: str, level: str) -> str:
|
|
5
|
+
match = re.match (r"^(\d+)\.(\d+)\.(\d+)$", current)
|
|
6
|
+
if not match:
|
|
7
|
+
return level
|
|
8
|
+
|
|
9
|
+
major = int (match.group (1))
|
|
10
|
+
minor = int (match.group (2))
|
|
11
|
+
patch = int (match.group (3))
|
|
12
|
+
|
|
13
|
+
if level == "major":
|
|
14
|
+
return f"{major + 1}.0.0"
|
|
15
|
+
elif level == "minor":
|
|
16
|
+
return f"{major}.{minor + 1}.0"
|
|
17
|
+
elif level == "patch":
|
|
18
|
+
return f"{major}.{minor}.{patch + 1}"
|
|
19
|
+
|
|
20
|
+
return level
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def changelog_from_commits (subjects: str) -> str:
|
|
24
|
+
added = []
|
|
25
|
+
fixed = []
|
|
26
|
+
changed = []
|
|
27
|
+
|
|
28
|
+
pattern = re.compile (
|
|
29
|
+
r"^(feat|fix|refactor|build|chore|docs|test|style|perf|ci)"
|
|
30
|
+
r"(\(.+\))?!?: (.+)$"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
for line in subjects.splitlines ():
|
|
34
|
+
line = line.strip ()
|
|
35
|
+
if not line:
|
|
36
|
+
continue
|
|
37
|
+
|
|
38
|
+
if re.match (r"^[0-9a-f]+ ", line):
|
|
39
|
+
line = line.split (" ", 1) [1]
|
|
40
|
+
|
|
41
|
+
match = pattern.match (line)
|
|
42
|
+
if match:
|
|
43
|
+
kind = match.group (1)
|
|
44
|
+
desc = match.group (3)
|
|
45
|
+
else:
|
|
46
|
+
desc = line [0].upper () + line [1:] if len (line) > 1 else line
|
|
47
|
+
changed.append (f"- {desc}")
|
|
48
|
+
continue
|
|
49
|
+
|
|
50
|
+
desc = desc [0].upper () + desc [1:] if len (desc) > 1 else desc
|
|
51
|
+
|
|
52
|
+
if kind == "feat":
|
|
53
|
+
added.append (f"- {desc}")
|
|
54
|
+
elif kind == "fix":
|
|
55
|
+
fixed.append (f"- {desc}")
|
|
56
|
+
else:
|
|
57
|
+
changed.append (f"- {desc}")
|
|
58
|
+
|
|
59
|
+
sections = []
|
|
60
|
+
if added:
|
|
61
|
+
sections.append ("### Added\n" + "\n".join (added))
|
|
62
|
+
if changed:
|
|
63
|
+
sections.append ("### Changed\n" + "\n".join (changed))
|
|
64
|
+
if fixed:
|
|
65
|
+
sections.append ("### Fixed\n" + "\n".join (fixed))
|
|
66
|
+
|
|
67
|
+
return "\n\n".join (sections)
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: imp-git
|
|
3
|
+
Version: 0.0.26
|
|
4
|
+
Summary: AI-powered git workflow CLI
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Requires-Dist: questionary>=2.0.0
|
|
9
|
+
Requires-Dist: rich>=13.0.0
|
|
10
|
+
Requires-Dist: typer>=0.15.0
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<img src="logo.png" alt="imp" width="200">
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
AI-powered git workflow.<br>
|
|
22
|
+
Commit, branch, review, and release without writing commit messages, branch names, or PR descriptions.
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<a href="#install">Install</a> ·
|
|
27
|
+
<a href="#quick-start">Quick Start</a> ·
|
|
28
|
+
<a href="#commands">Commands</a> ·
|
|
29
|
+
<a href="#configuration">Configuration</a> ·
|
|
30
|
+
<a href="#license">License</a>
|
|
31
|
+
</p>
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
imp commit -a # stages everything, generates message, commits
|
|
37
|
+
imp branch "auth" # creates feat/user-auth
|
|
38
|
+
imp review # AI code review of your changes
|
|
39
|
+
imp release # squash, changelog, tag, push
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Why
|
|
43
|
+
|
|
44
|
+
AI agents can run git for you, but they improvise every time. Imp is opinionated: same format, same workflow, same result, every time.
|
|
45
|
+
|
|
46
|
+
- **Consistent commits** across your whole team, validated against [Conventional Commits](https://www.conventionalcommits.org/) before anything touches git
|
|
47
|
+
- **One-command releases** that squash, changelog, tag, and push with automatic rollback on failure
|
|
48
|
+
- **Fast and deterministic.** One command, not a conversation. No reasoning, no retries, no surprises.
|
|
49
|
+
- **AI writes the words, Imp controls the workflow.** What gets staged, how it's validated, when it's safe to push.
|
|
50
|
+
- **Works offline** with local models via Ollama. No API key required.
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
uv tool install git+https://github.com/anders458/imp.git
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or with pip:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install git+https://github.com/anders458/imp.git
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then set up your AI provider and verify:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
imp config
|
|
68
|
+
imp doctor
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Make some changes, then commit with an AI message
|
|
75
|
+
imp commit -a
|
|
76
|
+
# -> "feat: add rate limiting to API endpoints"
|
|
77
|
+
# -> Use this message? [Yes / Edit / No]
|
|
78
|
+
|
|
79
|
+
# Branch from a description
|
|
80
|
+
imp branch "add user authentication"
|
|
81
|
+
# -> Suggested: feat/user-auth
|
|
82
|
+
# -> Create branch? [Yes / No]
|
|
83
|
+
|
|
84
|
+
# Branch from a GitHub issue
|
|
85
|
+
imp fix 42
|
|
86
|
+
# -> Fetches issue, suggests fix/login-redirect-42
|
|
87
|
+
|
|
88
|
+
# Ship a release
|
|
89
|
+
imp release
|
|
90
|
+
# -> Version bump: patch / minor / major
|
|
91
|
+
# -> Generates changelog, squashes, tags, pushes
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Commands
|
|
95
|
+
|
|
96
|
+
### Daily Workflow
|
|
97
|
+
|
|
98
|
+
| Command | Description |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `imp commit [-a]` | Generate commit message from diff. `-a` stages all. |
|
|
101
|
+
| `imp amend` | Rewrite last commit message from the full diff. |
|
|
102
|
+
| `imp undo [N]` | Undo last N commits, keep changes staged. |
|
|
103
|
+
| `imp revert [hash]` | Safely revert a pushed commit. |
|
|
104
|
+
| `imp push` | Push commits to origin. Sets upstream on first push. |
|
|
105
|
+
| `imp sync` | Pull, rebase, push in one step. |
|
|
106
|
+
| `imp resolve` | AI-assisted merge conflict resolution. |
|
|
107
|
+
|
|
108
|
+
### Branching
|
|
109
|
+
|
|
110
|
+
| Command | Description |
|
|
111
|
+
|---|---|
|
|
112
|
+
| `imp branch <desc>` | Create branch from plain English description. |
|
|
113
|
+
| `imp branch` | Interactive branch switcher. |
|
|
114
|
+
| `imp fix <issue>` | Create branch from GitHub issue number. |
|
|
115
|
+
| `imp pr` | Create pull request with AI title and body. |
|
|
116
|
+
| `imp done [target]` | Merge feature branch, clean up local and remote. |
|
|
117
|
+
|
|
118
|
+
### Analysis
|
|
119
|
+
|
|
120
|
+
| Command | Description |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `imp review` | AI code review of staged or unstaged changes. |
|
|
123
|
+
| `imp split` | Group dirty files into logical commits via AI. |
|
|
124
|
+
| `imp status` | Repo overview: branch, changes, sync state. |
|
|
125
|
+
| `imp log [-n N]` | Pretty commit graph. |
|
|
126
|
+
|
|
127
|
+
### Release
|
|
128
|
+
|
|
129
|
+
| Command | Description |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `imp release` | Squash commits, generate changelog, tag, push, create GitHub release. |
|
|
132
|
+
| `imp ship [level]` | Commit all + release in one shot, no prompts. Default: patch. |
|
|
133
|
+
|
|
134
|
+
### Setup
|
|
135
|
+
|
|
136
|
+
| Command | Description |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `imp config` | Interactive AI provider and model setup. |
|
|
139
|
+
| `imp doctor` | Verify tools, config, and AI connection. |
|
|
140
|
+
| `imp clean` | Delete merged branches (local and remote). |
|
|
141
|
+
| `imp help` | Show workflow guide and commit format reference. |
|
|
142
|
+
|
|
143
|
+
Any AI command accepts `--whisper` / `-w` to hint the AI without overriding its rules:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
imp commit -a -w "use IMP-42 as ticket"
|
|
147
|
+
imp review -w "focus on error handling"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Workflows
|
|
151
|
+
|
|
152
|
+
| Flow | Steps |
|
|
153
|
+
|---|---|
|
|
154
|
+
| **Solo** | `commit -a` → `push` → `release` |
|
|
155
|
+
| **Feature branch** | `branch` → `commit -a` → `pr` → `done` |
|
|
156
|
+
| **Hotfix** | `fix 42` → `commit -a` → `pr` → `done` |
|
|
157
|
+
| **Merge conflict** | `sync` or `done` → `resolve` → continue |
|
|
158
|
+
|
|
159
|
+
## Commit Format
|
|
160
|
+
|
|
161
|
+
Imp generates [Conventional Commits](https://www.conventionalcommits.org/) messages, validated before use.
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
type: message feat, fix, refactor, build, chore,
|
|
165
|
+
type(scope): message docs, test, style, perf, ci
|
|
166
|
+
type!: message (breaking change)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
All lowercase after the colon (except ticket IDs). Imperative mood. Max 72 chars, no period. Tickets after the colon: `fix: IMP-42 resolve timeout`. Scopes optional: `refactor(auth): simplify flow`.
|
|
170
|
+
|
|
171
|
+
## Configuration
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
imp config
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Interactive menu to set your AI provider and models. Stored in `~/.config/imp/config.json`.
|
|
178
|
+
|
|
179
|
+
| Setting | Default | Description |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| `provider` | `claude` | AI provider: `claude` or `ollama` |
|
|
182
|
+
| `model:fast` | `haiku` | Model for quick tasks (commit, branch) |
|
|
183
|
+
| `model:smart` | `sonnet` | Model for complex tasks (review, PR, split) |
|
|
184
|
+
|
|
185
|
+
Environment variables (`IMP_AI_PROVIDER`, `IMP_AI_MODEL_FAST`, `IMP_AI_MODEL_SMART`) override the config file when set, useful for CI.
|
|
186
|
+
|
|
187
|
+
## Requirements
|
|
188
|
+
|
|
189
|
+
- Python 3.10+
|
|
190
|
+
- git
|
|
191
|
+
- [gh](https://cli.github.com) (optional, for `imp fix`, `imp pr`, `imp release`)
|
|
192
|
+
|
|
193
|
+
### Claude Code (default)
|
|
194
|
+
|
|
195
|
+
Imp uses [Claude Code](https://docs.anthropic.com/en/docs/claude-code) as its default AI provider. You need an active Claude Code subscription.
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
curl -fsSL https://claude.ai/install.sh | bash
|
|
199
|
+
claude # authenticate
|
|
200
|
+
imp doctor # verify
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Ollama (local, free)
|
|
204
|
+
|
|
205
|
+
For fully offline usage with no API key:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Install from https://ollama.com, then:
|
|
209
|
+
ollama pull llama3.2
|
|
210
|
+
imp config # select ollama and your models
|
|
211
|
+
imp doctor # verify
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Development
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
git clone https://github.com/anders458/imp.git
|
|
218
|
+
cd imp
|
|
219
|
+
pip install -e ".[dev]"
|
|
220
|
+
pytest -v
|
|
221
|
+
ruff check src/ tests/
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
imp/__init__.py,sha256=KlzduDtYVFgyKGsfoee61vItyxxVCOigfLdp1jOziAQ,183
|
|
2
|
+
imp/__main__.py,sha256=IfCDGyo33ICz8EQFYcRclIXIGnWA1ovZeqL78HwpFFU,33
|
|
3
|
+
imp/ai.py,sha256=n8h9skDftkuU7b7Zu8XZb0EeXEZAy3N645z3NIaRMcI,3153
|
|
4
|
+
imp/config.py,sha256=LjlJvqHIM_WetYNIg5OWgXzLkurRQ---dqwrIbgXED0,1039
|
|
5
|
+
imp/console.py,sha256=1Jf0qcS-z1ofw7ku9v83eH66kTk8NwE3rba0D7mqgAg,3416
|
|
6
|
+
imp/git.py,sha256=7g5d-DEBoBf4tazj_wrGbH_vVxhiMYKM67HEPXApFZg,10526
|
|
7
|
+
imp/main.py,sha256=josHHVJuyNNpdnx6aZrQ7Kf2Jawai2V5NX_zgw3-DKw,1831
|
|
8
|
+
imp/prompts.py,sha256=U59wwPOeH0Pd_HW3uViD4ht6sX83T4VTf2s4nSwjwEg,4049
|
|
9
|
+
imp/theme.py,sha256=p8hzLwLGAbBzMjeTsEoDC7NMEsx4-kik_q8jXzduAB0,258
|
|
10
|
+
imp/validate.py,sha256=_CckqM8_PfYTEjNQ15RG8s5X3ReohMHzIcXm7JK6TcU,615
|
|
11
|
+
imp/version.py,sha256=acFP6afDw8Mg_9N90tNKUGAAT7-FAj2b_9x4X8CSHJ0,1641
|
|
12
|
+
imp/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
imp/commands/amend.py,sha256=gOSQ5nIUmhz8lERpJk3k7j1ZLykK0bcqHYL6X-Jgplg,1800
|
|
14
|
+
imp/commands/branch.py,sha256=XUqoleL0jV2ennIFD5bq9Ojsknlxi0sKh2p9liFEbj8,1946
|
|
15
|
+
imp/commands/clean.py,sha256=BSWI9Ne42QLbsbD0I2696ZerJov66G0GnYNanc5D1-Y,1115
|
|
16
|
+
imp/commands/commit.py,sha256=Tt12gjoTlulX5Ij5-ecg_8YG-laGDntuY1YGV9heiS0,1923
|
|
17
|
+
imp/commands/config.py,sha256=QLCZV2OpBAlHE__2LABzZRJS9k3PSJzsco9yjQKTPTc,1528
|
|
18
|
+
imp/commands/doctor.py,sha256=cAUWqJS0Ey38RbLnZP0_J0pT11znpk4grOFoamNcFMY,2565
|
|
19
|
+
imp/commands/done.py,sha256=KzdN_yrSVg84nFM8gnFwZa76N3Uo5gkozy-zmn8GC8c,2847
|
|
20
|
+
imp/commands/fix.py,sha256=J81lin2dyQrrLCzWJh5NyVaxRC9TrpQ7IoJAXw_XQJI,2292
|
|
21
|
+
imp/commands/help.py,sha256=aihRGygn4Z6HpQSv4aOSm1c3d1z3MNFV1FhZ1kdgycg,5634
|
|
22
|
+
imp/commands/log.py,sha256=WZ7mDYKSz3WkxF5u4xiitw358sg_lbWO5YvXP2kVinE,608
|
|
23
|
+
imp/commands/pr.py,sha256=UDRmrBXibAs1I2mt1_Q3_39PzK_ds5mgW5TOzx8Z1t0,3247
|
|
24
|
+
imp/commands/push.py,sha256=ilPCvPFERa4Nrb4QeNETtrmDsRL9O_9tXK4FwFDT_Oo,880
|
|
25
|
+
imp/commands/release.py,sha256=ydZ4SCfpwapc3_J8tjroIDtomuDVZHAWVIKXhrBD9_o,7399
|
|
26
|
+
imp/commands/resolve.py,sha256=Srz4AqeRImi9mmCzXs0D08rqHsgjRzJf3WpC1E8CgB4,4100
|
|
27
|
+
imp/commands/revert.py,sha256=0vE_C1lp61iIuqkc_7rLKZ8BuRV3-E6V6jHNMIBUyFE,2231
|
|
28
|
+
imp/commands/review.py,sha256=n6FEmkEOaxKUoPy_6tGNOV-wN12qAPQ_WjEUHQQupjg,1961
|
|
29
|
+
imp/commands/ship.py,sha256=LTvpLcmZM8n1bE1p8X91HaThtq6SBFNFhnzxM6emSoM,3645
|
|
30
|
+
imp/commands/split.py,sha256=IpZnseqwEHaVf31JrDru_LAMYC-JBH_ruC0-M9bGPMg,5113
|
|
31
|
+
imp/commands/status.py,sha256=vjxYJelyjJYZS_m2A7NzVVAeCNg445aiPt9G5EhW16Q,2523
|
|
32
|
+
imp/commands/sync.py,sha256=lVM4rf8cNrFghQjlqkFXTH7bqfvQF-vE6nYOT8jAZkI,1590
|
|
33
|
+
imp/commands/undo.py,sha256=13EGJ_2Z-Z3eUJeNP_fChxX5TBfGxBpdqn_qXdZSd1k,1191
|
|
34
|
+
imp_git-0.0.26.dist-info/METADATA,sha256=c17PL_eykGGnzU0qG6MiXoP_1osFU8vMgZxfUCS0nu0,6552
|
|
35
|
+
imp_git-0.0.26.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
36
|
+
imp_git-0.0.26.dist-info/entry_points.txt,sha256=CKG1G2oEc_kjxbGmmpFidavJQFY_cCYu_ffph8Y1cjs,37
|
|
37
|
+
imp_git-0.0.26.dist-info/licenses/LICENSE,sha256=TpH8U304cPIvQ2DIEAwIyU0cEZ8kvYpOmzJxtDsTjnY,1063
|
|
38
|
+
imp_git-0.0.26.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anders
|
|
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.
|