taipanstack 0.1.0__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.
- taipanstack/__init__.py +53 -0
- taipanstack/config/__init__.py +25 -0
- taipanstack/config/generators.py +357 -0
- taipanstack/config/models.py +316 -0
- taipanstack/config/version_config.py +227 -0
- taipanstack/core/__init__.py +47 -0
- taipanstack/core/compat.py +329 -0
- taipanstack/core/optimizations.py +392 -0
- taipanstack/core/result.py +199 -0
- taipanstack/security/__init__.py +55 -0
- taipanstack/security/decorators.py +369 -0
- taipanstack/security/guards.py +362 -0
- taipanstack/security/sanitizers.py +321 -0
- taipanstack/security/validators.py +342 -0
- taipanstack/utils/__init__.py +24 -0
- taipanstack/utils/circuit_breaker.py +268 -0
- taipanstack/utils/filesystem.py +417 -0
- taipanstack/utils/logging.py +328 -0
- taipanstack/utils/metrics.py +272 -0
- taipanstack/utils/retry.py +300 -0
- taipanstack/utils/subprocess.py +344 -0
- taipanstack-0.1.0.dist-info/METADATA +350 -0
- taipanstack-0.1.0.dist-info/RECORD +25 -0
- taipanstack-0.1.0.dist-info/WHEEL +4 -0
- taipanstack-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: taipanstack
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: TaipanStack - Modular, secure, and scalable Python stack for robust development
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: security,devops,python,taipanstack,bootstrapper,quality
|
|
8
|
+
Author: gabrielima7
|
|
9
|
+
Author-email: gabrielima.alu.lmb@gmail.com
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Classifier: Topic :: Security
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Provides-Extra: runtime
|
|
23
|
+
Requires-Dist: email-validator (>=2.0.0)
|
|
24
|
+
Requires-Dist: orjson (>=3.9.0)
|
|
25
|
+
Requires-Dist: pydantic (>=2.0)
|
|
26
|
+
Requires-Dist: pydantic-settings (>=2.0.0)
|
|
27
|
+
Requires-Dist: result (>=0.17.0)
|
|
28
|
+
Requires-Dist: structlog (>=23.0.0) ; extra == "runtime"
|
|
29
|
+
Requires-Dist: uvloop (>=0.19.0) ; (sys_platform != "win32") and (extra == "runtime")
|
|
30
|
+
Project-URL: Changelog, https://github.com/gabrielima7/TaipanStack/blob/main/CHANGELOG.md
|
|
31
|
+
Project-URL: Documentation, https://github.com/gabrielima7/TaipanStack#readme
|
|
32
|
+
Project-URL: Homepage, https://github.com/gabrielima7/TaipanStack
|
|
33
|
+
Project-URL: Issues, https://github.com/gabrielima7/TaipanStack/issues
|
|
34
|
+
Project-URL: Repository, https://github.com/gabrielima7/TaipanStack
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
<div align="center">
|
|
38
|
+
|
|
39
|
+
# 🐍 TaipanStack
|
|
40
|
+
|
|
41
|
+
### **The Modern Python Foundation**
|
|
42
|
+
|
|
43
|
+
*Launch secure, high-performance Python applications in seconds.*
|
|
44
|
+
|
|
45
|
+
[](https://github.com/gabrielima7/TaipanStack/actions/workflows/ci.yml)
|
|
46
|
+
[](https://www.python.org/)
|
|
47
|
+
[](https://github.com/gabrielima7/TaipanStack)
|
|
48
|
+
[](https://github.com/astral-sh/ruff)
|
|
49
|
+
[](http://mypy-lang.org/)
|
|
50
|
+
[](LICENSE)
|
|
51
|
+
[](SECURITY.md)
|
|
52
|
+
[](https://pypi.org/project/taipanstack/)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
[**Features**](#-features) • [**Quick Start**](#-quick-start) • [**Architecture**](#-architecture) • [**DevSecOps**](#-devsecops) • [**API**](#-api-highlights) • [**Contributing**](#-contributing)
|
|
57
|
+
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## ✨ Why TaipanStack?
|
|
63
|
+
|
|
64
|
+
> **"Write less, build better."**
|
|
65
|
+
|
|
66
|
+
TaipanStack is a battle-tested foundation for production-grade Python projects that combines **security**, **performance**, and **developer experience** into a single, cohesive toolkit.
|
|
67
|
+
|
|
68
|
+
<table>
|
|
69
|
+
<tr>
|
|
70
|
+
<td width="50%">
|
|
71
|
+
|
|
72
|
+
### 🛡️ Security First
|
|
73
|
+
- Path traversal protection
|
|
74
|
+
- Command injection guards
|
|
75
|
+
- Input sanitizers & validators
|
|
76
|
+
- Secret detection integration
|
|
77
|
+
|
|
78
|
+
</td>
|
|
79
|
+
<td width="50%">
|
|
80
|
+
|
|
81
|
+
### ⚡ High Performance
|
|
82
|
+
- `uvloop` async event loop
|
|
83
|
+
- `orjson` fast JSON serialization
|
|
84
|
+
- `Pydantic v2` validation
|
|
85
|
+
- Optimized for production
|
|
86
|
+
|
|
87
|
+
</td>
|
|
88
|
+
</tr>
|
|
89
|
+
<tr>
|
|
90
|
+
<td width="50%">
|
|
91
|
+
|
|
92
|
+
### 🎯 Rust-Style Error Handling
|
|
93
|
+
- `Ok`/`Err` Result types
|
|
94
|
+
- Explicit error propagation
|
|
95
|
+
- Pattern matching support
|
|
96
|
+
- No silent failures
|
|
97
|
+
|
|
98
|
+
</td>
|
|
99
|
+
<td width="50%">
|
|
100
|
+
|
|
101
|
+
### 🔧 Developer Experience
|
|
102
|
+
- Pre-configured quality tools
|
|
103
|
+
- Comprehensive test suite
|
|
104
|
+
- Architecture enforcement
|
|
105
|
+
- Zero-config setup
|
|
106
|
+
|
|
107
|
+
</td>
|
|
108
|
+
</tr>
|
|
109
|
+
</table>
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 🚀 Quick Start
|
|
114
|
+
|
|
115
|
+
### Prerequisites
|
|
116
|
+
|
|
117
|
+
- **Python 3.11+** (supports 3.11, 3.12, 3.13, 3.14)
|
|
118
|
+
- **Poetry** ([install guide](https://python-poetry.org/docs/#installation))
|
|
119
|
+
|
|
120
|
+
### Installation
|
|
121
|
+
|
|
122
|
+
#### From PyPI
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pip install taipanstack
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### From Source
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Clone the repository
|
|
132
|
+
git clone https://github.com/gabrielima7/TaipanStack.git
|
|
133
|
+
cd TaipanStack
|
|
134
|
+
|
|
135
|
+
# Install dependencies
|
|
136
|
+
poetry install --with dev
|
|
137
|
+
|
|
138
|
+
# Run quality checks
|
|
139
|
+
make all
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Verify Installation
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Run tests with coverage (97%+ coverage)
|
|
146
|
+
make test
|
|
147
|
+
|
|
148
|
+
# Check architecture contracts
|
|
149
|
+
make lint-imports
|
|
150
|
+
|
|
151
|
+
# Run security scans
|
|
152
|
+
make security
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 📐 Architecture
|
|
158
|
+
|
|
159
|
+
TaipanStack follows a clean, layered architecture with strict dependency rules enforced by **Import Linter**.
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
┌─────────────────────────────────────┐
|
|
163
|
+
│ Application │
|
|
164
|
+
│ (src/app/main.py) │
|
|
165
|
+
└─────────────────┬───────────────────┘
|
|
166
|
+
│
|
|
167
|
+
┌───────────────────────────┼───────────────────────────┐
|
|
168
|
+
▼ ▼ ▼
|
|
169
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
170
|
+
│ Security │ │ Config │ │ Utils │
|
|
171
|
+
│ guards, saniti- │ │ models, │ │ logging, retry │
|
|
172
|
+
│ zers, validators│ │ generators │ │ metrics, fs │
|
|
173
|
+
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
|
|
174
|
+
│ │ │
|
|
175
|
+
└─────────────────────────┼─────────────────────────┘
|
|
176
|
+
▼
|
|
177
|
+
┌─────────────────────────────────────┐
|
|
178
|
+
│ Core │
|
|
179
|
+
│ Result types, base patterns │
|
|
180
|
+
└─────────────────────────────────────┘
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Project Structure
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
TaipanStack/
|
|
187
|
+
├── src/
|
|
188
|
+
│ ├── app/ # Application entry point
|
|
189
|
+
│ └── taipanstack/
|
|
190
|
+
│ ├── core/ # 🎯 Result types, functional patterns
|
|
191
|
+
│ ├── config/ # ⚙️ Configuration models & generators
|
|
192
|
+
│ ├── security/ # 🛡️ Guards, sanitizers, validators
|
|
193
|
+
│ └── utils/ # 🔧 Logging, metrics, retry, filesystem
|
|
194
|
+
├── tests/ # ✅ Comprehensive test suite (97%+ coverage)
|
|
195
|
+
├── pyapp/ # 📦 Standalone executable builder
|
|
196
|
+
├── .github/ # 🔄 CI/CD workflows
|
|
197
|
+
└── pyproject.toml # 📋 Modern dependency management
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 🔐 DevSecOps
|
|
203
|
+
|
|
204
|
+
TaipanStack integrates security and quality at every level:
|
|
205
|
+
|
|
206
|
+
| Category | Tools | Purpose |
|
|
207
|
+
|----------|-------|---------|
|
|
208
|
+
| **SAST** | Bandit, Semgrep | Static Application Security Testing |
|
|
209
|
+
| **SCA** | Safety | Dependency vulnerability scanning |
|
|
210
|
+
| **Types** | Mypy (strict) | Compile-time type checking |
|
|
211
|
+
| **Lint** | Ruff | Lightning-fast linting & formatting |
|
|
212
|
+
| **Arch** | Import Linter | Dependency rule enforcement |
|
|
213
|
+
| **Test** | Pytest, Hypothesis | Property-based testing |
|
|
214
|
+
|
|
215
|
+
### CI Pipeline
|
|
216
|
+
|
|
217
|
+
```yaml
|
|
218
|
+
# Runs on every push/PR
|
|
219
|
+
✓ Test Matrix → Python 3.11-3.14 × (Ubuntu, macOS, Windows)
|
|
220
|
+
✓ Linux Distros → Ubuntu, Debian, Fedora, openSUSE, Arch, Alpine
|
|
221
|
+
✓ Code Quality → Ruff check & format
|
|
222
|
+
✓ Type Check → Mypy strict mode
|
|
223
|
+
✓ Security → Bandit + Semgrep
|
|
224
|
+
✓ Architecture → Import Linter contracts
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## 📚 API Highlights
|
|
230
|
+
|
|
231
|
+
### Result Types (Rust-Style Error Handling)
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
from taipanstack.core.result import Result, Ok, Err, safe
|
|
235
|
+
|
|
236
|
+
@safe
|
|
237
|
+
def divide(a: int, b: int) -> float:
|
|
238
|
+
return a / b
|
|
239
|
+
|
|
240
|
+
# Explicit error handling with pattern matching
|
|
241
|
+
match divide(10, 0):
|
|
242
|
+
case Ok(value):
|
|
243
|
+
print(f"Result: {value}")
|
|
244
|
+
case Err(error):
|
|
245
|
+
print(f"Error: {error}")
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Security Guards
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
from taipanstack.security.guards import guard_path_traversal, guard_command_injection
|
|
252
|
+
|
|
253
|
+
# Prevent path traversal attacks
|
|
254
|
+
safe_path = guard_path_traversal(user_input, base_dir="/app/data")
|
|
255
|
+
|
|
256
|
+
# Prevent command injection
|
|
257
|
+
safe_cmd = guard_command_injection(
|
|
258
|
+
["git", "clone", repo_url],
|
|
259
|
+
allowed_commands=["git"]
|
|
260
|
+
)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Retry with Exponential Backoff
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
from taipanstack.utils.retry import retry
|
|
267
|
+
|
|
268
|
+
@retry(max_attempts=3, on=(ConnectionError, TimeoutError))
|
|
269
|
+
async def fetch_data(url: str) -> dict:
|
|
270
|
+
return await http_client.get(url)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Circuit Breaker
|
|
274
|
+
|
|
275
|
+
```python
|
|
276
|
+
from taipanstack.utils.circuit_breaker import circuit_breaker
|
|
277
|
+
|
|
278
|
+
@circuit_breaker(failure_threshold=5, timeout=30)
|
|
279
|
+
def call_external_service() -> Response:
|
|
280
|
+
return service.call()
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## 🛠️ Tech Stack
|
|
286
|
+
|
|
287
|
+
<table>
|
|
288
|
+
<tr>
|
|
289
|
+
<th>Runtime</th>
|
|
290
|
+
<th>Quality</th>
|
|
291
|
+
<th>DevOps</th>
|
|
292
|
+
</tr>
|
|
293
|
+
<tr>
|
|
294
|
+
<td>
|
|
295
|
+
|
|
296
|
+
- Pydantic v2
|
|
297
|
+
- Orjson
|
|
298
|
+
- Uvloop
|
|
299
|
+
- Structlog
|
|
300
|
+
- Result
|
|
301
|
+
|
|
302
|
+
</td>
|
|
303
|
+
<td>
|
|
304
|
+
|
|
305
|
+
- Ruff
|
|
306
|
+
- Mypy
|
|
307
|
+
- Bandit
|
|
308
|
+
- Pytest
|
|
309
|
+
- Hypothesis
|
|
310
|
+
|
|
311
|
+
</td>
|
|
312
|
+
<td>
|
|
313
|
+
|
|
314
|
+
- GitHub Actions
|
|
315
|
+
- Dependabot
|
|
316
|
+
- Pre-commit
|
|
317
|
+
- Poetry
|
|
318
|
+
- Import Linter
|
|
319
|
+
|
|
320
|
+
</td>
|
|
321
|
+
</tr>
|
|
322
|
+
</table>
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## 🤝 Contributing
|
|
327
|
+
|
|
328
|
+
Contributions are welcome! Please check our [Contributing Guide](CONTRIBUTING.md) for details on:
|
|
329
|
+
|
|
330
|
+
- 🐛 Bug reports
|
|
331
|
+
- ✨ Feature requests
|
|
332
|
+
- 📝 Documentation improvements
|
|
333
|
+
- 🔧 Pull requests
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 📝 License
|
|
338
|
+
|
|
339
|
+
This project is open-sourced under the [MIT License](LICENSE).
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
<div align="center">
|
|
344
|
+
|
|
345
|
+
**Made with ❤️ for the Python community**
|
|
346
|
+
|
|
347
|
+
[⬆ Back to Top](#-taipanstack)
|
|
348
|
+
|
|
349
|
+
</div>
|
|
350
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
taipanstack/__init__.py,sha256=ETuNbotufherwmkWIabePDWB5RdKy2cj998yJmrkp38,1250
|
|
2
|
+
taipanstack/config/__init__.py,sha256=-uKsphIMmqO4bJOkZnIrQyzPV4l2B_maDMpPr9g-wIk,562
|
|
3
|
+
taipanstack/config/generators.py,sha256=p69iwYwSl4i1i4lG5qBnbyRaWzBLrX0yCPujh4TeXsY,8292
|
|
4
|
+
taipanstack/config/models.py,sha256=Qh3XfsLvztXnSju-CALKVS_WWClz0Yb9Qk5P-04nKkM,9217
|
|
5
|
+
taipanstack/config/version_config.py,sha256=oaA7JMFxHACxfkNgft_NdpbNujGfMLGqXPZ9k2g5PzQ,7778
|
|
6
|
+
taipanstack/core/__init__.py,sha256=FEFC0Tw2fxKr6scSi1rS6UskryY7Q06Kum8GavSxnf4,964
|
|
7
|
+
taipanstack/core/compat.py,sha256=Dwnb9k9WVD33gWiKofpHArFcvlmHUfl8Z6T2lUPaPS8,10157
|
|
8
|
+
taipanstack/core/optimizations.py,sha256=rPcxavFwxelp8XEEoGfbUZpWmDpEYBWY6kBCbXZkzic,11511
|
|
9
|
+
taipanstack/core/result.py,sha256=4_2pSduLKTbmw5_HGPMmrzWoZkCOCh20CvMqraEgtlI,4758
|
|
10
|
+
taipanstack/security/__init__.py,sha256=FGsS2zyI3QWCekTtaZn3hog0TUeGClLqPo1qcEEMwTo,1191
|
|
11
|
+
taipanstack/security/decorators.py,sha256=c3xpjwCpGZNIpGwCF-9vPFShAz6AzoVuhMTd49mKYVo,11024
|
|
12
|
+
taipanstack/security/guards.py,sha256=JsTNBv-pG1LZ5XL9ApUXz02pCe2lSygRdz6NmMOVK4A,10115
|
|
13
|
+
taipanstack/security/sanitizers.py,sha256=Njjvoi-fURcJ-yAW7AO3SmlZCVXEzsRg7-O8ACbgSFQ,8302
|
|
14
|
+
taipanstack/security/validators.py,sha256=E3jRhV23Hn9YgVcqqYshOX_WA4NwW_bdLap3v1PbSSA,8808
|
|
15
|
+
taipanstack/utils/__init__.py,sha256=JECong87iIPWppyONVTxphJ340A0wUdjwzIuiiHeY_g,607
|
|
16
|
+
taipanstack/utils/circuit_breaker.py,sha256=4sWXHmDfhOU3vWfJo3-RVtVPMwybEkezAR4-S-C1b6Q,8699
|
|
17
|
+
taipanstack/utils/filesystem.py,sha256=vjl7cFWDoTf5XZNoxCHpaGe72pY0Lulo_NsaWfA621A,10792
|
|
18
|
+
taipanstack/utils/logging.py,sha256=8-N_xgYfl1tgM93rYjtJLyT0OPYFDONJW-EnHRLp2so,8966
|
|
19
|
+
taipanstack/utils/metrics.py,sha256=ZjyTePtHJ-Sj7FuSsebODDQG1fi7knmOcCicHQ5vNMw,7851
|
|
20
|
+
taipanstack/utils/retry.py,sha256=gW7K0KLD8KH1Dz8lEwDgdSp_sDRstw9dfrA7nGFB8sU,8697
|
|
21
|
+
taipanstack/utils/subprocess.py,sha256=Ll0Mo2La2JOZvG60LgkU8uCcmH9NqEBrHWzY9NCi2Og,8765
|
|
22
|
+
taipanstack-0.1.0.dist-info/METADATA,sha256=hXSsVO_tHOwXleBqIxmky9WqktUOvRPm2BlsD-CXKNA,10280
|
|
23
|
+
taipanstack-0.1.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
24
|
+
taipanstack-0.1.0.dist-info/licenses/LICENSE,sha256=O3qm8VBmhhebtRAD3T8W4QBxgLLGEEI6vl4faNCi9ws,1069
|
|
25
|
+
taipanstack-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Gabriel Lima
|
|
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.
|