philips-airctrl 1.0.0__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.
- philips_airctrl-1.0.0/.github/workflows/publish.yml +36 -0
- philips_airctrl-1.0.0/.gitignore +157 -0
- philips_airctrl-1.0.0/.pre-commit-config.yaml +38 -0
- philips_airctrl-1.0.0/CHANGELOG.md +121 -0
- philips_airctrl-1.0.0/CLAUDE.md +62 -0
- philips_airctrl-1.0.0/LICENSE +21 -0
- philips_airctrl-1.0.0/PKG-INFO +358 -0
- philips_airctrl-1.0.0/README.md +315 -0
- philips_airctrl-1.0.0/examples/example.py +19 -0
- philips_airctrl-1.0.0/pyproject.toml +151 -0
- philips_airctrl-1.0.0/src/philips_airctrl/__init__.py +4 -0
- philips_airctrl-1.0.0/src/philips_airctrl/__main__.py +4 -0
- philips_airctrl-1.0.0/src/philips_airctrl/_version.py +3 -0
- philips_airctrl-1.0.0/src/philips_airctrl/cli.py +337 -0
- philips_airctrl-1.0.0/src/philips_airctrl/coap/__init__.py +1 -0
- philips_airctrl-1.0.0/src/philips_airctrl/coap/client.py +167 -0
- philips_airctrl-1.0.0/src/philips_airctrl/coap/encryption.py +69 -0
- philips_airctrl-1.0.0/src/philips_airctrl/device_info.py +719 -0
- philips_airctrl-1.0.0/src/philips_airctrl/discovery.py +154 -0
- philips_airctrl-1.0.0/src/philips_airctrl/models.py +119 -0
- philips_airctrl-1.0.0/src/philips_airctrl/setup_wizard.py +315 -0
- philips_airctrl-1.0.0/tests/__init__.py +0 -0
- philips_airctrl-1.0.0/tests/test_cli.py +580 -0
- philips_airctrl-1.0.0/tests/test_client.py +409 -0
- philips_airctrl-1.0.0/tests/test_device_info.py +318 -0
- philips_airctrl-1.0.0/tests/test_discovery.py +265 -0
- philips_airctrl-1.0.0/tests/test_encryption.py +107 -0
- philips_airctrl-1.0.0/tests/test_models.py +159 -0
- philips_airctrl-1.0.0/tests/test_package.py +30 -0
- philips_airctrl-1.0.0/tests/test_setup_wizard.py +365 -0
- philips_airctrl-1.0.0/uv.lock +852 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
name: Publish to PyPI
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment: release
|
|
15
|
+
permissions:
|
|
16
|
+
id-token: write # Required for trusted publishing
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout repository
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up Python 3.11
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.11"
|
|
26
|
+
|
|
27
|
+
- name: Install build tools
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
pip install build
|
|
31
|
+
|
|
32
|
+
- name: Build package
|
|
33
|
+
run: python -m build
|
|
34
|
+
|
|
35
|
+
- name: Publish to PyPI
|
|
36
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
pip-wheel-metadata/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
MANIFEST
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
# Usually these files are written by a python script from a template
|
|
32
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
33
|
+
*.manifest
|
|
34
|
+
*.spec
|
|
35
|
+
|
|
36
|
+
# Installer logs
|
|
37
|
+
pip-log.txt
|
|
38
|
+
pip-delete-this-directory.txt
|
|
39
|
+
|
|
40
|
+
# Unit test / coverage reports
|
|
41
|
+
htmlcov/
|
|
42
|
+
.tox/
|
|
43
|
+
.nox/
|
|
44
|
+
.coverage
|
|
45
|
+
.coverage.*
|
|
46
|
+
.cache
|
|
47
|
+
nosetests.xml
|
|
48
|
+
coverage.xml
|
|
49
|
+
*.cover
|
|
50
|
+
*.py,cover
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
target/
|
|
76
|
+
|
|
77
|
+
# Jupyter Notebook
|
|
78
|
+
.ipynb_checkpoints
|
|
79
|
+
|
|
80
|
+
# IPython
|
|
81
|
+
profile_default/
|
|
82
|
+
ipython_config.py
|
|
83
|
+
|
|
84
|
+
# pyenv
|
|
85
|
+
.python-version
|
|
86
|
+
|
|
87
|
+
# pipenv
|
|
88
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
89
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
90
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
91
|
+
# install all needed dependencies.
|
|
92
|
+
#Pipfile.lock
|
|
93
|
+
|
|
94
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
95
|
+
__pypackages__/
|
|
96
|
+
|
|
97
|
+
# Celery stuff
|
|
98
|
+
celerybeat-schedule
|
|
99
|
+
celerybeat.pid
|
|
100
|
+
|
|
101
|
+
# SageMath parsed files
|
|
102
|
+
*.sage.py
|
|
103
|
+
|
|
104
|
+
# Environments
|
|
105
|
+
.env
|
|
106
|
+
.venv
|
|
107
|
+
env/
|
|
108
|
+
venv/
|
|
109
|
+
ENV/
|
|
110
|
+
env.bak/
|
|
111
|
+
venv.bak/
|
|
112
|
+
|
|
113
|
+
# Spyder project settings
|
|
114
|
+
.spyderproject
|
|
115
|
+
.spyproject
|
|
116
|
+
|
|
117
|
+
# Rope project settings
|
|
118
|
+
.ropeproject
|
|
119
|
+
|
|
120
|
+
# mkdocs documentation
|
|
121
|
+
/site
|
|
122
|
+
|
|
123
|
+
# mypy
|
|
124
|
+
.mypy_cache/
|
|
125
|
+
.dmypy.json
|
|
126
|
+
dmypy.json
|
|
127
|
+
|
|
128
|
+
# Pyre type checker
|
|
129
|
+
.pyre/
|
|
130
|
+
|
|
131
|
+
# IDE files
|
|
132
|
+
.vscode/
|
|
133
|
+
.idea/
|
|
134
|
+
*.swp
|
|
135
|
+
*.swo
|
|
136
|
+
*~
|
|
137
|
+
|
|
138
|
+
# macOS
|
|
139
|
+
.DS_Store
|
|
140
|
+
.AppleDouble
|
|
141
|
+
.LSOverride
|
|
142
|
+
|
|
143
|
+
# Windows
|
|
144
|
+
Thumbs.db
|
|
145
|
+
ehthumbs.db
|
|
146
|
+
Desktop.ini
|
|
147
|
+
|
|
148
|
+
# Home Assistant setup wizard output
|
|
149
|
+
philips_airpurifier_config/
|
|
150
|
+
|
|
151
|
+
# Temporary files
|
|
152
|
+
*.tmp
|
|
153
|
+
*.temp
|
|
154
|
+
|
|
155
|
+
# Local configuration files
|
|
156
|
+
config.local.*
|
|
157
|
+
.env.local
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v5.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: check-toml
|
|
9
|
+
- id: check-json
|
|
10
|
+
- id: check-added-large-files
|
|
11
|
+
- id: check-merge-conflict
|
|
12
|
+
- id: debug-statements
|
|
13
|
+
|
|
14
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
15
|
+
rev: v0.8.6
|
|
16
|
+
hooks:
|
|
17
|
+
- id: ruff
|
|
18
|
+
args: [--fix]
|
|
19
|
+
- id: ruff-format
|
|
20
|
+
|
|
21
|
+
- repo: https://github.com/PyCQA/bandit
|
|
22
|
+
rev: 1.8.3
|
|
23
|
+
hooks:
|
|
24
|
+
- id: bandit
|
|
25
|
+
args: ["-c", "pyproject.toml", "-r", "src"]
|
|
26
|
+
additional_dependencies: ["bandit[toml]"]
|
|
27
|
+
|
|
28
|
+
ci:
|
|
29
|
+
autofix_commit_msg: |
|
|
30
|
+
[pre-commit.ci] auto fixes from pre-commit.com hooks
|
|
31
|
+
|
|
32
|
+
for more information, see https://pre-commit.ci
|
|
33
|
+
autofix_prs: true
|
|
34
|
+
autoupdate_branch: ''
|
|
35
|
+
autoupdate_commit_msg: '[pre-commit.ci] pre-commit autoupdate'
|
|
36
|
+
autoupdate_schedule: weekly
|
|
37
|
+
skip: []
|
|
38
|
+
submodules: false
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Changelog - philips-airctrl (Enhanced Home Assistant Fork)
|
|
2
|
+
|
|
3
|
+
All notable changes to this enhanced fork will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
> **Note**: This is an enhanced fork of the original aioairctrl package with significant additional features for Home Assistant integration. Version numbers start from 0.3.0 to distinguish from the original package.
|
|
9
|
+
|
|
10
|
+
## [0.3.0] - 2025-01-27 - **Major Home Assistant Integration Release**
|
|
11
|
+
|
|
12
|
+
### Added - **🏠 Home Assistant Integration Features**
|
|
13
|
+
- **🔍 Automatic Device Discovery** - Network scanning for Philips air purifiers
|
|
14
|
+
- **📊 Comprehensive Device Analysis** - Extract 70+ data points with capability detection
|
|
15
|
+
- **🧙♂️ Interactive Setup Wizard** - User-friendly guided setup for non-technical users
|
|
16
|
+
- **📁 Multiple Export Formats** - JSON and YAML output for easy integration
|
|
17
|
+
- **🏠 Home Assistant Configuration Generation** - Ready-to-use HA configs
|
|
18
|
+
- **📋 Device Information Export** - Complete device analysis for integration development
|
|
19
|
+
- **🤝 Community Contribution Workflow** - Easy device info sharing for ha-philips-airpurifier project
|
|
20
|
+
|
|
21
|
+
### Added - **🛠️ Development & Quality Improvements**
|
|
22
|
+
- Comprehensive test suite with 75%+ coverage
|
|
23
|
+
- Type hints throughout the codebase
|
|
24
|
+
- Modern pyproject.toml configuration
|
|
25
|
+
- Pre-commit hooks configuration
|
|
26
|
+
- GitHub Actions CI/CD pipeline
|
|
27
|
+
- Detailed README with usage examples
|
|
28
|
+
- Development documentation
|
|
29
|
+
- Code quality tools (Black, Flake8, MyPy)
|
|
30
|
+
|
|
31
|
+
### Changed - **🔄 Fork & Package Changes**
|
|
32
|
+
- **BREAKING**: Package renamed to `philips-airctrl` to distinguish from original
|
|
33
|
+
- **BREAKING**: No longer available on PyPI - must install from source
|
|
34
|
+
- **BREAKING**: CLI argument structure updated for new commands
|
|
35
|
+
- **BREAKING**: Migrated from setup.py to pyproject.toml
|
|
36
|
+
- Updated Python version requirement to 3.8+
|
|
37
|
+
- Enhanced CLI argument parsing for better testability
|
|
38
|
+
- Modernized code formatting with Black
|
|
39
|
+
- Updated project metadata and maintainer information
|
|
40
|
+
|
|
41
|
+
### Changed - **🛠️ Technical Improvements**
|
|
42
|
+
- Improved error handling in client code
|
|
43
|
+
- Fixed encryption key overflow handling
|
|
44
|
+
- Enhanced async/await patterns throughout codebase
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
- Fixed bare except clause in client.py
|
|
48
|
+
- Fixed f-string without placeholders
|
|
49
|
+
- Fixed module imports organization
|
|
50
|
+
- Fixed encryption context key incrementation overflow
|
|
51
|
+
- Improved async/await patterns in tests
|
|
52
|
+
|
|
53
|
+
### Security
|
|
54
|
+
- Updated dependencies to latest versions
|
|
55
|
+
- Added security scanning configuration
|
|
56
|
+
- Improved error handling to prevent information leakage
|
|
57
|
+
|
|
58
|
+
### Development
|
|
59
|
+
- Added comprehensive test suite for all modules
|
|
60
|
+
- Set up automated testing with pytest
|
|
61
|
+
- Added code coverage reporting
|
|
62
|
+
- Implemented pre-commit hooks for code quality
|
|
63
|
+
- Added development environment setup documentation
|
|
64
|
+
|
|
65
|
+
## [0.2.5] - Previous Release
|
|
66
|
+
|
|
67
|
+
### Features
|
|
68
|
+
- Basic CoAP client functionality
|
|
69
|
+
- Encrypted communication with Philips air purifiers
|
|
70
|
+
- Command-line interface
|
|
71
|
+
- Status monitoring and control
|
|
72
|
+
- Device observation capabilities
|
|
73
|
+
|
|
74
|
+
### Known Issues
|
|
75
|
+
- Limited test coverage
|
|
76
|
+
- No type hints
|
|
77
|
+
- Basic error handling
|
|
78
|
+
- Manual dependency management
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Development Notes
|
|
83
|
+
|
|
84
|
+
### Version 0.2.6 Improvements Summary
|
|
85
|
+
|
|
86
|
+
This release represents a major modernization and quality improvement of the philips-airctrl library:
|
|
87
|
+
|
|
88
|
+
1. **Testing Infrastructure**: Added comprehensive test suite covering encryption, client functionality, and CLI operations with proper async mocking.
|
|
89
|
+
|
|
90
|
+
2. **Code Quality**: Implemented modern Python development practices including type hints, code formatting, and linting.
|
|
91
|
+
|
|
92
|
+
3. **Project Structure**: Migrated to modern pyproject.toml configuration and removed deprecated setup.py.
|
|
93
|
+
|
|
94
|
+
4. **Documentation**: Significantly enhanced README with detailed usage examples, API reference, and development guidelines.
|
|
95
|
+
|
|
96
|
+
5. **Development Workflow**: Added pre-commit hooks, CI/CD pipeline, and automated quality checks.
|
|
97
|
+
|
|
98
|
+
6. **Maintainability**: Improved error handling, fixed code quality issues, and added proper async patterns.
|
|
99
|
+
|
|
100
|
+
### Migration Guide from 0.2.5 to 0.2.6
|
|
101
|
+
|
|
102
|
+
The API remains backward compatible, but there are some development-related changes:
|
|
103
|
+
|
|
104
|
+
- **Python Version**: Now requires Python 3.8+ (was 3.6+)
|
|
105
|
+
- **Installation**: No changes to installation process
|
|
106
|
+
- **API**: All existing API calls remain the same
|
|
107
|
+
- **CLI**: All existing CLI commands work unchanged
|
|
108
|
+
|
|
109
|
+
For developers:
|
|
110
|
+
- Use `pip install -e ".[dev]"` for development dependencies
|
|
111
|
+
- Run tests with `pytest` instead of manual testing
|
|
112
|
+
- Use `black` for code formatting
|
|
113
|
+
- Use `pre-commit` for automated quality checks
|
|
114
|
+
|
|
115
|
+
### Future Roadmap
|
|
116
|
+
|
|
117
|
+
- Add support for more Philips air purifier models
|
|
118
|
+
- Implement device discovery functionality
|
|
119
|
+
- Add configuration file support
|
|
120
|
+
- Enhance error messages and user feedback
|
|
121
|
+
- Add integration with home automation systems
|
|
@@ -0,0 +1,62 @@
|
|
|
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 Overview
|
|
6
|
+
|
|
7
|
+
Async Python library and CLI for controlling Philips air purifiers over encrypted CoAP. Provides network discovery, device data extraction, and an interactive Home Assistant setup wizard.
|
|
8
|
+
|
|
9
|
+
## Development Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Setup
|
|
13
|
+
uv sync --extra dev # Install all dependencies including dev
|
|
14
|
+
|
|
15
|
+
# Testing (100% coverage required — enforced via fail_under = 100)
|
|
16
|
+
uv run pytest # Run full suite with coverage
|
|
17
|
+
uv run pytest tests/test_cli.py # Run a single test file
|
|
18
|
+
uv run pytest tests/test_cli.py::TestParseArgs::test_status # Run a single test
|
|
19
|
+
uv run pytest -k "test_discover" # Run tests matching a pattern
|
|
20
|
+
uv run pytest -m "not slow" # Skip slow tests
|
|
21
|
+
|
|
22
|
+
# Linting & Formatting
|
|
23
|
+
uv run ruff check src/ tests/ # Lint
|
|
24
|
+
uv run ruff check --fix src/ tests/ # Lint with auto-fix
|
|
25
|
+
uv run ruff format src/ tests/ # Format
|
|
26
|
+
uv run mypy # Type check (strict mode)
|
|
27
|
+
|
|
28
|
+
# Security
|
|
29
|
+
uv run bandit -c pyproject.toml -r src/
|
|
30
|
+
|
|
31
|
+
# Pre-commit
|
|
32
|
+
uv run pre-commit run --all-files
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Architecture
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
src/philips_airctrl/
|
|
39
|
+
├── __main__.py # CLI entry point → calls cli.main()
|
|
40
|
+
├── cli.py # Argument parsing and command dispatch (argparse)
|
|
41
|
+
├── coap/
|
|
42
|
+
│ ├── client.py # Async CoAP client (Client class) — device communication
|
|
43
|
+
│ └── encryption.py # AES-CBC encryption/decryption for CoAP payloads
|
|
44
|
+
├── discovery.py # Network scanning for Philips devices (DeviceDiscovery)
|
|
45
|
+
├── device_info.py # Device capability analysis and reporting (DeviceInfoExtractor)
|
|
46
|
+
├── models.py # All Pydantic v2 data models (DeviceInfo, DeviceReport, HAConfig, etc.)
|
|
47
|
+
├── setup_wizard.py # Interactive CLI wizard using click (SetupWizard)
|
|
48
|
+
└── _version.py # Single source of truth for package version
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Data flow:** CLI → Discovery/Client → Encryption → Device. Models are shared across all modules.
|
|
52
|
+
|
|
53
|
+
## Key Conventions
|
|
54
|
+
|
|
55
|
+
- **Python >=3.11** with src/ layout, built with hatchling
|
|
56
|
+
- **Pydantic v2** for all data models — use `model_validate()`, not `parse_obj()`
|
|
57
|
+
- **Async/await** throughout — tests use `asyncio_mode = "auto"` (no manual decorator needed)
|
|
58
|
+
- **Line length**: 100 characters (ruff)
|
|
59
|
+
- **Ruff rules**: E, W, F, I, N, UP, B, SIM, TCH, RUF, S (bandit security checks)
|
|
60
|
+
- **mypy strict**: `disallow_untyped_defs=true` — all functions need type annotations
|
|
61
|
+
- **Test style**: pytest class-based organization with `unittest.mock` (AsyncMock for async)
|
|
62
|
+
- **Version**: Edit `src/philips_airctrl/_version.py` — hatch reads it dynamically
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 betaboon
|
|
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.
|