diffron 0.1.4__tar.gz → 0.1.6__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.
- {diffron-0.1.4/diffron.egg-info → diffron-0.1.6}/PKG-INFO +2 -2
- {diffron-0.1.4 → diffron-0.1.6}/README.md +1 -1
- {diffron-0.1.4 → diffron-0.1.6}/diffron/lemonade.py +4 -1
- {diffron-0.1.4 → diffron-0.1.6/diffron.egg-info}/PKG-INFO +2 -2
- {diffron-0.1.4 → diffron-0.1.6}/diffron.egg-info/SOURCES.txt +0 -3
- {diffron-0.1.4 → diffron-0.1.6}/diffron.egg-info/top_level.txt +0 -2
- {diffron-0.1.4 → diffron-0.1.6}/pyproject.toml +1 -1
- diffron-0.1.4/docs/LEMONADE_PORT_VERIFICATION_FIX.md +0 -105
- diffron-0.1.4/docs/LEMONADE_UNRESPONSIVE_FIX.md +0 -100
- diffron-0.1.4/docs/MODEL_NAME_CASE_FIX.md +0 -88
- {diffron-0.1.4 → diffron-0.1.6}/CHANGELOG.md +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/LICENSE +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/MANIFEST.in +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/__init__.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/__init__.pyi +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/__main__.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/cli.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/cli.pyi +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/client.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/client.pyi +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/commit_gen.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/commit_gen.pyi +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/git_hooks.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/git_hooks.pyi +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/hooks/aipr.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/hooks/prepare-commit-msg +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/hooks/prepare-commit-msg-global.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/hooks/prepare-commit-msg.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/lemonade.pyi +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/models.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/models.pyi +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/pr_gen.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/pr_gen.pyi +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/py.typed +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/utils.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron/utils.pyi +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron.egg-info/dependency_links.txt +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron.egg-info/entry_points.txt +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/diffron.egg-info/requires.txt +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/docs/HOOKS.md +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/docs/SETUP.md +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/docs/USAGE.md +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/hooks/aipr.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/hooks/prepare-commit-msg-global.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/hooks/prepare-commit-msg.py +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/requirements.txt +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/setup.cfg +0 -0
- {diffron-0.1.4 → diffron-0.1.6}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diffron
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Git commit message and PR description generator using Lemonade
|
|
5
5
|
Home-page: https://github.com/diffron/diffron
|
|
6
6
|
Author: Diffron Contributors
|
|
@@ -47,7 +47,7 @@ Git commit message and PR description generator using AMD Lemonade via lemonade-
|
|
|
47
47
|
|
|
48
48
|
**Diffron is a production-ready reference implementation of the lemonade-python-sdk — submitted to the AMD Lemonade Developer Challenge 2026.**
|
|
49
49
|
|
|
50
|
-

|
|
51
51
|

|
|
52
52
|

|
|
53
53
|

|
|
@@ -4,7 +4,7 @@ Git commit message and PR description generator using AMD Lemonade via lemonade-
|
|
|
4
4
|
|
|
5
5
|
**Diffron is a production-ready reference implementation of the lemonade-python-sdk — submitted to the AMD Lemonade Developer Challenge 2026.**
|
|
6
6
|
|
|
7
|
-

|
|
8
8
|

|
|
9
9
|

|
|
10
10
|

|
|
@@ -229,7 +229,10 @@ class LemonadeClient:
|
|
|
229
229
|
)
|
|
230
230
|
if new_port and new_port != self._port:
|
|
231
231
|
self._port = new_port
|
|
232
|
-
|
|
232
|
+
self.port = new_port # Update the port attribute
|
|
233
|
+
# Rebuild the base_url with the new port and the same host
|
|
234
|
+
self.base_url = f"http://{self.host}:{new_port}"
|
|
235
|
+
# Reinitialize client with new base_url
|
|
233
236
|
self._init_client()
|
|
234
237
|
except Exception:
|
|
235
238
|
# Silently continue on reload failure
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diffron
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Git commit message and PR description generator using Lemonade
|
|
5
5
|
Home-page: https://github.com/diffron/diffron
|
|
6
6
|
Author: Diffron Contributors
|
|
@@ -47,7 +47,7 @@ Git commit message and PR description generator using AMD Lemonade via lemonade-
|
|
|
47
47
|
|
|
48
48
|
**Diffron is a production-ready reference implementation of the lemonade-python-sdk — submitted to the AMD Lemonade Developer Challenge 2026.**
|
|
49
49
|
|
|
50
|
-

|
|
51
51
|

|
|
52
52
|

|
|
53
53
|

|
|
@@ -36,9 +36,6 @@ diffron/hooks/prepare-commit-msg
|
|
|
36
36
|
diffron/hooks/prepare-commit-msg-global.py
|
|
37
37
|
diffron/hooks/prepare-commit-msg.py
|
|
38
38
|
docs/HOOKS.md
|
|
39
|
-
docs/LEMONADE_PORT_VERIFICATION_FIX.md
|
|
40
|
-
docs/LEMONADE_UNRESPONSIVE_FIX.md
|
|
41
|
-
docs/MODEL_NAME_CASE_FIX.md
|
|
42
39
|
docs/SETUP.md
|
|
43
40
|
docs/USAGE.md
|
|
44
41
|
hooks/aipr.py
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
# Lemonade Port Verification Fix
|
|
2
|
-
|
|
3
|
-
## Problem
|
|
4
|
-
|
|
5
|
-
Diffron incorrectly connected to **port 8000** (running Axo Biomarker Analyzer) instead of **port 8020** (running Lemonade), causing:
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
Error code: 404 - {'detail': 'Not Found'}
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
### Root Cause
|
|
12
|
-
|
|
13
|
-
The `detect_lemonade_port()` function in `diffron/lemonade.py` only checked if a **port was open** (`is_port_open`), not whether it was actually a **Lemonade server**.
|
|
14
|
-
|
|
15
|
-
When port 8000 responded (Axo Biomarker web app), Diffron mistakenly identified it as Lemonade and sent API requests to the wrong service.
|
|
16
|
-
|
|
17
|
-
| Port | Service | Response |
|
|
18
|
-
|------|---------|----------|
|
|
19
|
-
| 8000 | Axo Biomarker Analyzer | HTML web page |
|
|
20
|
-
| 8020 | **Lemonade** (correct) | `{"data": [...]}` API |
|
|
21
|
-
|
|
22
|
-
## Solution
|
|
23
|
-
|
|
24
|
-
### Use lemonade-python-sdk's `verify_lemonade_server`
|
|
25
|
-
|
|
26
|
-
The **lemonade-python-sdk** provides `verify_lemonade_server(port, host)` which:
|
|
27
|
-
|
|
28
|
-
1. Queries the native Lemonade API endpoint `/api/v1/models`
|
|
29
|
-
2. Validates the response format (`{"data": [...]}` or list)
|
|
30
|
-
3. Distinguishes Lemonade from other services (Ollama, web apps, etc.)
|
|
31
|
-
|
|
32
|
-
### Changes
|
|
33
|
-
|
|
34
|
-
**1. Added `lemonade-sdk` dependency**
|
|
35
|
-
|
|
36
|
-
Updated `requirements.txt`:
|
|
37
|
-
```txt
|
|
38
|
-
lemonade-sdk>=0.1.0
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
**2. Updated `detect_lemonade_port()`**
|
|
42
|
-
|
|
43
|
-
`diffron/lemonade.py` now:
|
|
44
|
-
|
|
45
|
-
- Imports `verify_lemonade_server` and `find_available_lemonade_port` from `lemonade_sdk.port_scanner`
|
|
46
|
-
- **Verifies** each open port is actually Lemonade before returning it
|
|
47
|
-
- Falls back to legacy `is_port_open` behavior if SDK is not installed
|
|
48
|
-
|
|
49
|
-
```python
|
|
50
|
-
# Import from lemonade-python-sdk for proper Lemonade verification
|
|
51
|
-
try:
|
|
52
|
-
from lemonade_sdk.port_scanner import verify_lemonade_server, find_available_lemonade_port
|
|
53
|
-
HAS_LEMONADE_SDK = True
|
|
54
|
-
except ImportError:
|
|
55
|
-
HAS_LEMONADE_SDK = False
|
|
56
|
-
|
|
57
|
-
def detect_lemonade_port(...) -> Optional[int]:
|
|
58
|
-
# ... existing env var checks ...
|
|
59
|
-
|
|
60
|
-
# Try SDK's find_available_lemonade_port first
|
|
61
|
-
if HAS_LEMONADE_SDK:
|
|
62
|
-
found = find_available_lemonade_port(hostname, scan_ports)
|
|
63
|
-
if found:
|
|
64
|
-
return found
|
|
65
|
-
|
|
66
|
-
# Fallback: manual scan with SDK verification
|
|
67
|
-
for port in ports_to_scan:
|
|
68
|
-
if is_port_open(hostname, port):
|
|
69
|
-
if HAS_LEMONADE_SDK:
|
|
70
|
-
if verify_lemonade_server(port, hostname): # ← Key fix!
|
|
71
|
-
return port
|
|
72
|
-
else:
|
|
73
|
-
return port # Legacy: no verification
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**3. Added graceful fallback**
|
|
77
|
-
|
|
78
|
-
If `lemonade-sdk` is not installed, Diffron falls back to the original `is_port_open` behavior (first open port wins), maintaining backward compatibility.
|
|
79
|
-
|
|
80
|
-
## Testing
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
# Before fix: returned 8000 (Axo Biomarker)
|
|
84
|
-
# After fix: returns 8020 (Lemonade)
|
|
85
|
-
python -c "from diffron.lemonade import detect_lemonade_port; print(detect_lemonade_port())"
|
|
86
|
-
# Output: 8020
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Impact
|
|
90
|
-
|
|
91
|
-
- **Fixes 404 errors** when other services run on ports 8000/8080
|
|
92
|
-
- **No breaking changes** - existing setups continue to work
|
|
93
|
-
- **Better diagnostics** - clear separation between Lemonade and non-Lemonade services
|
|
94
|
-
|
|
95
|
-
## Files Changed
|
|
96
|
-
|
|
97
|
-
| File | Change |
|
|
98
|
-
|------|--------|
|
|
99
|
-
| `diffron/lemonade.py` | Use `verify_lemonade_server` for port detection |
|
|
100
|
-
| `requirements.txt` | Add `lemonade-sdk>=0.1.0` dependency |
|
|
101
|
-
|
|
102
|
-
## Version
|
|
103
|
-
|
|
104
|
-
- **Fixed in**: 0.1.3
|
|
105
|
-
- **Date**: 2026-04-13
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# Lemonade Model Unresponsive Fix
|
|
2
|
-
|
|
3
|
-
## Problem
|
|
4
|
-
|
|
5
|
-
Das Lemonade-Modell wurde manchmal unresponsive, was zu einem Fehler in Diffron führte:
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
Diffron error: 'NoneType' object is not subscriptable
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Dies trat auf, wenn die Antwort des Modells `None` war oder `response.choices` leer war, was beim Zugriff auf `response.choices[0].message.content` zu einem Fehler führte.
|
|
12
|
-
|
|
13
|
-
## Lösung
|
|
14
|
-
|
|
15
|
-
In [`diffron/lemonade.py`](../diffron/lemonade.py:170) wurde eine Retry-Logik mit automatischem Entladen und Neuladen des Modells implementiert.
|
|
16
|
-
|
|
17
|
-
### Änderungen in `LemonadeClient.chat_completion()`
|
|
18
|
-
|
|
19
|
-
```python
|
|
20
|
-
max_retries = 3
|
|
21
|
-
for attempt in range(1, max_retries + 1):
|
|
22
|
-
try:
|
|
23
|
-
response = self.client.chat.completions.create(...)
|
|
24
|
-
# Handle None response (model unresponsive)
|
|
25
|
-
if response is None or not response.choices:
|
|
26
|
-
if attempt < max_retries:
|
|
27
|
-
self._reload_model()
|
|
28
|
-
continue
|
|
29
|
-
raise RuntimeError("Lemonade model returned no response")
|
|
30
|
-
return response.choices[0].message.content
|
|
31
|
-
except Exception as e:
|
|
32
|
-
if attempt < max_retries:
|
|
33
|
-
self._reload_model()
|
|
34
|
-
continue
|
|
35
|
-
raise RuntimeError(
|
|
36
|
-
f"Lemonade model failed after {max_retries} attempts: {e}"
|
|
37
|
-
)
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### Neue Methoden
|
|
41
|
-
|
|
42
|
-
#### `_reload_model()`
|
|
43
|
-
|
|
44
|
-
Entlädt und lädt das Lemonade-Modell neu, wenn es unresponsive ist:
|
|
45
|
-
|
|
46
|
-
```python
|
|
47
|
-
def _reload_model(self) -> None:
|
|
48
|
-
"""Unload and reload the Lemonade model when unresponsive."""
|
|
49
|
-
try:
|
|
50
|
-
if HAS_LEMONADE_SDK:
|
|
51
|
-
new_port = find_available_lemonade_port(
|
|
52
|
-
hostname=self.host or DEFAULT_HOST,
|
|
53
|
-
ports=DEFAULT_PORTS
|
|
54
|
-
)
|
|
55
|
-
if new_port and new_port != self._port:
|
|
56
|
-
self._port = new_port
|
|
57
|
-
self._init_client()
|
|
58
|
-
except Exception:
|
|
59
|
-
pass
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
#### `_init_client()`
|
|
63
|
-
|
|
64
|
-
Initialisiert den OpenAI-Client neu mit der aktuellen Konfiguration:
|
|
65
|
-
|
|
66
|
-
```python
|
|
67
|
-
def _init_client(self) -> None:
|
|
68
|
-
"""Reinitialize the OpenAI client with current configuration."""
|
|
69
|
-
self.client = OpenAI(
|
|
70
|
-
base_url=f"{self.base_url}/api/v1",
|
|
71
|
-
api_key=self.api_key
|
|
72
|
-
)
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Ablauf bei Unresponsiveness
|
|
76
|
-
|
|
77
|
-
1. **Erster Versuch**: Modell antwortet nicht → `_reload_model()` aufgerufen
|
|
78
|
-
2. **Zweiter Versuch**: Modell antwortet immer noch nicht → `_reload_model()` erneut aufgerufen
|
|
79
|
-
3. **Dritter Versuch**: Erfolgt mit neu geladenem Modell
|
|
80
|
-
4. **Falls alle Versuche fehlschlagen**: `RuntimeError` mit detaillierter Fehlermeldung
|
|
81
|
-
|
|
82
|
-
## Voraussetzungen
|
|
83
|
-
|
|
84
|
-
Die automatische Wiederherstellung erfordert das `lemonade-python-sdk`:
|
|
85
|
-
|
|
86
|
-
```python
|
|
87
|
-
try:
|
|
88
|
-
from lemonade_sdk.port_scanner import verify_lemonade_server
|
|
89
|
-
from lemonade_sdk.port_scanner import find_available_lemonade_port
|
|
90
|
-
HAS_LEMONADE_SDK = True
|
|
91
|
-
except ImportError:
|
|
92
|
-
HAS_LEMONADE_SDK = False
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Ohne das SDK wird weiterhin versucht, einen offenen Port zu finden, aber die automatische Wiederherstellung ist eingeschränkt.
|
|
96
|
-
|
|
97
|
-
## Siehe auch
|
|
98
|
-
|
|
99
|
-
- [LEMONADE_PORT_VERIFICATION_FIX.md](LEMONADE_PORT_VERIFICATION_FIX.md) - Port-Erkennungsfix
|
|
100
|
-
- [MODEL_NAME_CASE_FIX.md](MODEL_NAME_CASE_FIX.md) - Modellnamen-Fallfix
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# Model Name Case Sensitivity Fix
|
|
2
|
-
|
|
3
|
-
## Problem
|
|
4
|
-
|
|
5
|
-
Diffron returned a **404 Not Found** error from the Lemonade server when using the `Qwen3.5-0.8B-GGUF` model.
|
|
6
|
-
|
|
7
|
-
### Root Cause
|
|
8
|
-
|
|
9
|
-
The Lemonade server is **case-sensitive** when matching model names. Diffron's curated model configuration used the wrong casing:
|
|
10
|
-
|
|
11
|
-
| Location | Model Name (Before) | Model Name (Expected) |
|
|
12
|
-
|----------|---------------------|------------------------|
|
|
13
|
-
| `diffron/models.py` | `qwen3.5-0.8b-gguf` | `Qwen3.5-0.8B-GGUF` |
|
|
14
|
-
|
|
15
|
-
This caused the OpenAI SDK to send a request with the wrong model identifier, resulting in:
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
Error code: 404 - {'detail': 'Not Found'}
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Solution
|
|
22
|
-
|
|
23
|
-
### 1. Corrected Model Name
|
|
24
|
-
|
|
25
|
-
Updated the canonical model name in `diffron/models.py`:
|
|
26
|
-
|
|
27
|
-
```python
|
|
28
|
-
# Before
|
|
29
|
-
ModelConfig(name="qwen3.5-0.8b-gguf", ...)
|
|
30
|
-
|
|
31
|
-
# After
|
|
32
|
-
ModelConfig(name="Qwen3.5-0.8B-GGUF", ...)
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### 2. Case-Insensitive Model Lookup
|
|
36
|
-
|
|
37
|
-
Enhanced `get_model_config()` to accept case-insensitive input while always returning the **canonical name**:
|
|
38
|
-
|
|
39
|
-
```python
|
|
40
|
-
def get_model_config(model_name: str) -> Optional[ModelConfig]:
|
|
41
|
-
# Exact match first
|
|
42
|
-
for model in AVAILABLE_MODELS:
|
|
43
|
-
if model.name == model_name:
|
|
44
|
-
return model
|
|
45
|
-
# Case-insensitive fallback
|
|
46
|
-
for model in AVAILABLE_MODEOLS:
|
|
47
|
-
if model.name.lower() == model_name.lower():
|
|
48
|
-
return model
|
|
49
|
-
return None
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
This allows users to type `qwen3.5-0.8b-gguf`, `QWEN3.5-0.8B-GGUF`, etc., but Diffron always sends the correct name to the server.
|
|
53
|
-
|
|
54
|
-
### 3. CLI Canonical Name Enforcement
|
|
55
|
-
|
|
56
|
-
The `setup_model_cli()` now stores the **canonical name** from the config, not the user's raw input:
|
|
57
|
-
|
|
58
|
-
```python
|
|
59
|
-
# Always uses config.name (canonical) instead of args.model (user input)
|
|
60
|
-
os.environ["DIFFRON_MODEL"] = config.name
|
|
61
|
-
subprocess.run(["setx", "DIFFRON_MODEL", config.name], check=True)
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Testing
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
# All of these now work correctly:
|
|
68
|
-
diffron-setup-model --model Qwen3.5-0.8B-GGUF # exact
|
|
69
|
-
diffron-setup-model --model qwen3.5-0.8b-gguf # lowercase (fallback)
|
|
70
|
-
diffron-setup-model --model QWEN3.5-0.8B-GGUF # uppercase (fallback)
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Impact
|
|
74
|
-
|
|
75
|
-
- **No breaking changes** - existing `DIFFRON_MODEL` values with wrong casing are now resolved correctly
|
|
76
|
-
- **Improved UX** - users don't need to memorize exact casing
|
|
77
|
-
- **Server compatibility** - correct model name is always sent to Lemonade
|
|
78
|
-
|
|
79
|
-
## Files Changed
|
|
80
|
-
|
|
81
|
-
| File | Change |
|
|
82
|
-
|------|--------|
|
|
83
|
-
| `diffron/models.py` | Fixed `Qwen3.5-0.8B-GGUF` name, added case-insensitive lookup |
|
|
84
|
-
|
|
85
|
-
## Version
|
|
86
|
-
|
|
87
|
-
- **Fixed in**: 0.1.3
|
|
88
|
-
- **Date**: 2026-04-13
|
|
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
|