psiutils 0.2.12__tar.gz → 0.2.14__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.
- {psiutils-0.2.12 → psiutils-0.2.14}/PKG-INFO +7 -3
- {psiutils-0.2.12 → psiutils-0.2.14}/pyproject.toml +7 -3
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/_about_frame.py +3 -1
- psiutils-0.2.14/src/psiutils/_version.py +1 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/buttons.py +5 -3
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/constants.py +5 -2
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/messagebox.py +12 -10
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/text.py +20 -48
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/utilities.py +15 -3
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/widgets.py +4 -0
- psiutils-0.2.12/src/psiutils/_version.py +0 -1
- {psiutils-0.2.12 → psiutils-0.2.14}/README.md +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/__init__.py +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/_logger.py +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/_notify.py +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/drag_manager.py +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/errors.py +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icecream_init.py +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/build.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/cancel.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/check.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/clear.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/code.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/compare.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/copy_clipboard.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/copy_docs.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/delete.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/diff.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/done.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/edit.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/gear.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/new.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/next.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/open.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/pause.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/preferences.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/previous.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/process.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/redo.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/refresh.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/rename.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/report.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/reset.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/revert.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/save.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/script.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/search.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/send.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/start.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/update.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/upgrade.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/icons/windows.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/images/icon-error.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/images/icon-info.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/images/icon-query.png +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/known_paths.py +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/menus.py +0 -0
- {psiutils-0.2.12 → psiutils-0.2.14}/src/psiutils/treeview.py +0 -0
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: psiutils
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.14
|
|
4
4
|
Summary: Various TKinter utilities.
|
|
5
5
|
Author: Jeff
|
|
6
6
|
Author-email: Jeff <<jeffwatkins2000@gmail.com>>
|
|
7
|
+
Requires-Dist: appdirs>=1.4.4
|
|
7
8
|
Requires-Dist: iniconfig>=2.1.0
|
|
8
9
|
Requires-Dist: markdown>=3.8.2
|
|
9
10
|
Requires-Dist: packaging>=25.0
|
|
10
11
|
Requires-Dist: pillow>=11.3.0
|
|
11
12
|
Requires-Dist: pluggy>=1.6.0
|
|
12
|
-
Requires-Dist: psi-toml>=0.0.
|
|
13
|
-
Requires-Dist: psiconfig>=0.0.
|
|
13
|
+
Requires-Dist: psi-toml>=0.0.12
|
|
14
|
+
Requires-Dist: psiconfig>=0.0.14
|
|
15
|
+
Requires-Dist: pycairo>=1.28.0
|
|
14
16
|
Requires-Dist: pygments>=2.19.2
|
|
17
|
+
Requires-Dist: pygobject>=3.54.2
|
|
18
|
+
Requires-Dist: structlog>=25.4.0
|
|
15
19
|
Requires-Dist: tkinterweb>=4.4.4
|
|
16
20
|
Requires-Dist: tkinterweb-tkhtml>=1.1.1
|
|
17
21
|
Requires-Dist: tomli>=2.2.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "psiutils"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.14"
|
|
4
4
|
description = "Various TKinter utilities."
|
|
5
5
|
authors = [{name = "Jeff", "email" = "<jeffwatkins2000@gmail.com>"}]
|
|
6
6
|
requires-python = '>= 3.10, < 3.13'
|
|
@@ -9,14 +9,18 @@ readme = "README.md"
|
|
|
9
9
|
include = ["HISTORY.md", "src/psiutils/icons/*.png"]
|
|
10
10
|
|
|
11
11
|
dependencies = [
|
|
12
|
+
"appdirs>=1.4.4",
|
|
12
13
|
"iniconfig>=2.1.0",
|
|
13
14
|
"markdown>=3.8.2",
|
|
14
15
|
"packaging>=25.0",
|
|
15
16
|
"pillow>=11.3.0",
|
|
16
17
|
"pluggy>=1.6.0",
|
|
17
|
-
"psi-toml>=0.0.
|
|
18
|
-
"psiconfig>=0.0.
|
|
18
|
+
"psi-toml>=0.0.12",
|
|
19
|
+
"psiconfig>=0.0.14",
|
|
20
|
+
"pycairo>=1.28.0",
|
|
19
21
|
"pygments>=2.19.2",
|
|
22
|
+
"pygobject>=3.54.2",
|
|
23
|
+
"structlog>=25.4.0",
|
|
20
24
|
"tkinterweb>=4.4.4",
|
|
21
25
|
"tkinterweb-tkhtml>=1.1.1",
|
|
22
26
|
"tomli>=2.2.1",
|
|
@@ -8,7 +8,9 @@ import markdown
|
|
|
8
8
|
from psiutils.constants import PAD, Pad
|
|
9
9
|
from psiutils.utilities import window_resize
|
|
10
10
|
|
|
11
|
-
from psiutils import
|
|
11
|
+
from psiutils.text import Text
|
|
12
|
+
|
|
13
|
+
txt = Text()
|
|
12
14
|
|
|
13
15
|
DEFAULT_GEOMETRY = '400x200'
|
|
14
16
|
HISTORY_GEOMETRY = '800x750'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.2.14'
|
|
@@ -4,10 +4,12 @@ from tkinter import ttk
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from PIL import Image, ImageTk
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
from psiutils.text import Text
|
|
8
8
|
|
|
9
|
-
from .constants import PAD, Pad
|
|
10
|
-
from .widgets import enter_widget, clickable_widget, HAND
|
|
9
|
+
from psiutils.constants import PAD, Pad
|
|
10
|
+
from psiutils.widgets import enter_widget, clickable_widget, HAND
|
|
11
|
+
|
|
12
|
+
txt = Text()
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class IconButton(ttk.Frame):
|
|
@@ -74,6 +74,7 @@ class Mode(Enum):
|
|
|
74
74
|
EDIT = auto()
|
|
75
75
|
DELETE = auto()
|
|
76
76
|
|
|
77
|
+
|
|
77
78
|
class Status(Enum):
|
|
78
79
|
YES = True
|
|
79
80
|
NO = False
|
|
@@ -81,5 +82,7 @@ class Status(Enum):
|
|
|
81
82
|
NULL = 0
|
|
82
83
|
EXIT = 1
|
|
83
84
|
OK = 2
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
SUCCESS = 3
|
|
86
|
+
UPDATED = 4
|
|
87
|
+
ERROR = 5
|
|
88
|
+
WARNING = 6
|
|
@@ -5,9 +5,11 @@ from tkinter import font
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from PIL import ImageTk, Image
|
|
7
7
|
|
|
8
|
-
from psiutils.constants import PAD
|
|
8
|
+
from psiutils.constants import PAD, Status
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
from psiutils.text import Text
|
|
11
|
+
|
|
12
|
+
txt = Text()
|
|
11
13
|
|
|
12
14
|
icons = {
|
|
13
15
|
'info': 'icon-info.png',
|
|
@@ -113,29 +115,29 @@ class MessageBox():
|
|
|
113
115
|
def _get_buttons(self, frame: ttk.Frame) -> dict[str, ttk.Button]:
|
|
114
116
|
return {
|
|
115
117
|
'ok': ttk.Button(
|
|
116
|
-
frame, text=
|
|
118
|
+
frame, text=txt.OK, command=self._ok, underline=0),
|
|
117
119
|
'yes': ttk.Button(
|
|
118
|
-
frame, text=
|
|
120
|
+
frame, text=txt.YES, command=self._yes, underline=0),
|
|
119
121
|
'no': ttk.Button(
|
|
120
|
-
frame, text=
|
|
122
|
+
frame, text=txt.NO, command=self._no, underline=0),
|
|
121
123
|
'cancel': ttk.Button(
|
|
122
|
-
frame, text=
|
|
124
|
+
frame, text=txt.CANCEL, command=self._cancel, underline=0),
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
def _ok(self, *args) -> None:
|
|
126
|
-
self.status =
|
|
128
|
+
self.status = Status.OK
|
|
127
129
|
self._dismiss()
|
|
128
130
|
|
|
129
131
|
def _yes(self, *args) -> None:
|
|
130
|
-
self.status =
|
|
132
|
+
self.status = Status.YES
|
|
131
133
|
self._dismiss()
|
|
132
134
|
|
|
133
135
|
def _no(self, *args) -> None:
|
|
134
|
-
self.status =
|
|
136
|
+
self.status = Status.NO
|
|
135
137
|
self._dismiss()
|
|
136
138
|
|
|
137
139
|
def _cancel(self, *args) -> None:
|
|
138
|
-
self.status =
|
|
140
|
+
self.status = Status.CANCEL
|
|
139
141
|
self._dismiss()
|
|
140
142
|
|
|
141
143
|
def _dismiss(self, *args) -> None:
|
|
@@ -1,52 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
CANCEL = 'Cancel'
|
|
3
|
-
CHECK = 'Check'
|
|
4
|
-
CLEAR = 'Clear'
|
|
5
|
-
CLOSE = 'Close'
|
|
6
|
-
CODE = 'Code'
|
|
7
|
-
COMPARE = 'Compare'
|
|
8
|
-
CONFIG = 'Config'
|
|
9
|
-
COPY = 'Copy'
|
|
10
|
-
DELETE = 'Delete'
|
|
11
|
-
DELETE_THESE_ITEMS = 'Are you sure you want to delete these item(s)?'
|
|
12
|
-
DIFF = 'Diff'
|
|
13
|
-
DONE = 'Done'
|
|
14
|
-
EDIT = 'Edit'
|
|
15
|
-
EVENT = 'Event'
|
|
16
|
-
EXIT = 'Exit'
|
|
17
|
-
HELP = 'Help'
|
|
18
|
-
NEW = 'New'
|
|
19
|
-
NEXT = 'Next'
|
|
20
|
-
NO = 'No'
|
|
21
|
-
NO_SUCH_FILE = 'no such file or directory'
|
|
22
|
-
OK = 'OK'
|
|
23
|
-
OPEN = 'Open'
|
|
24
|
-
PAUSE = 'Pause'
|
|
25
|
-
PREFERENCES = 'Preferences'
|
|
26
|
-
PREVIOUS = 'Prev'
|
|
27
|
-
PROCESS = 'Process'
|
|
28
|
-
QUIT = 'Quit'
|
|
29
|
-
REDO = 'Redo'
|
|
30
|
-
REFRESH = 'Refresh'
|
|
31
|
-
REPORT = 'Report'
|
|
32
|
-
RENAME = 'Rename'
|
|
33
|
-
RESET = 'Reset'
|
|
34
|
-
REVERT = 'Revert'
|
|
35
|
-
RUN = 'Run'
|
|
36
|
-
SAVE = 'Save'
|
|
37
|
-
SCRIPT = 'Script'
|
|
38
|
-
SAVE_PDF = 'Save as PDF'
|
|
39
|
-
SEARCH = 'Search'
|
|
40
|
-
SEND = 'Send'
|
|
41
|
-
START = 'Start'
|
|
42
|
-
UPDATE = 'Update'
|
|
43
|
-
UPGRADE = 'Upgrade'
|
|
44
|
-
USE = 'Use'
|
|
45
|
-
WINDOWS = 'Windows'
|
|
46
|
-
YES = 'Yes'
|
|
1
|
+
""" Handle standard text for psiutils."""
|
|
47
2
|
|
|
3
|
+
from copy import copy
|
|
48
4
|
|
|
49
|
-
|
|
5
|
+
|
|
6
|
+
psi_strings = {
|
|
50
7
|
'BUILD': 'Build',
|
|
51
8
|
'CANCEL': 'Cancel',
|
|
52
9
|
'CHECK': 'Check',
|
|
@@ -96,6 +53,8 @@ strings = {
|
|
|
96
53
|
'YES': 'Yes',
|
|
97
54
|
}
|
|
98
55
|
|
|
56
|
+
strings = copy(psi_strings)
|
|
57
|
+
|
|
99
58
|
|
|
100
59
|
class Text():
|
|
101
60
|
"""Combines package level and psiutils strings."""
|
|
@@ -119,9 +78,15 @@ class Text():
|
|
|
119
78
|
"""Print out contents of `strings` and compare if
|
|
120
79
|
a dict of strings is provided."""
|
|
121
80
|
duplicates = 0
|
|
122
|
-
overrides =0
|
|
81
|
+
overrides = 0
|
|
82
|
+
app_strings = 0
|
|
123
83
|
if not compare:
|
|
124
84
|
compare = {}
|
|
85
|
+
|
|
86
|
+
for key, item in compare.items():
|
|
87
|
+
if key not in strings:
|
|
88
|
+
strings[key] = item
|
|
89
|
+
|
|
125
90
|
for item in sorted(list(strings)):
|
|
126
91
|
output = f'{item:.<20} {strings[item]}'
|
|
127
92
|
if item in compare:
|
|
@@ -129,6 +94,9 @@ class Text():
|
|
|
129
94
|
output = (f'{output}, {compare[item]} '
|
|
130
95
|
f'<{"-"*10} //override//')
|
|
131
96
|
overrides += 1
|
|
97
|
+
elif item not in psi_strings:
|
|
98
|
+
output = f'{output} <{"="*10} //app string//'
|
|
99
|
+
app_strings += 1
|
|
132
100
|
else:
|
|
133
101
|
output = f'{output} <{"="*10} //duplicate//'
|
|
134
102
|
duplicates += 1
|
|
@@ -141,3 +109,7 @@ class Text():
|
|
|
141
109
|
if overrides:
|
|
142
110
|
print()
|
|
143
111
|
print(f'{overrides} overrides found')
|
|
112
|
+
|
|
113
|
+
if app_strings:
|
|
114
|
+
print()
|
|
115
|
+
print(f'{app_strings} application strings found')
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Common methods for psiutils."""
|
|
2
|
+
import sys
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
import tkinter as tk
|
|
4
5
|
import ctypes
|
|
@@ -6,11 +7,11 @@ from typing import Any
|
|
|
6
7
|
import platform
|
|
7
8
|
|
|
8
9
|
from psiconfig import TomlConfig
|
|
9
|
-
import psiutils.text as txt
|
|
10
|
-
|
|
11
|
-
# Exposes psi_logger to other applications
|
|
12
10
|
from psiutils._logger import psi_logger
|
|
13
11
|
from psiutils._notify import _notify as notify
|
|
12
|
+
from psiconfig import TomlConfig
|
|
13
|
+
from psiutils.text import Text
|
|
14
|
+
txt = Text()
|
|
14
15
|
|
|
15
16
|
DEFAULT_GEOMETRY = '500x400'
|
|
16
17
|
|
|
@@ -28,6 +29,16 @@ def display_icon(root: tk.Tk, icon_file_path: str,
|
|
|
28
29
|
print(f'Cannot find icon file: {icon_file_path}')
|
|
29
30
|
|
|
30
31
|
|
|
32
|
+
def resource_path(base: Path, relative_path: Path):
|
|
33
|
+
""" Get absolute path to resource, works for dev and for PyInstaller."""
|
|
34
|
+
try:
|
|
35
|
+
# PyInstaller creates a temp folder and stores path in _MEIPASS
|
|
36
|
+
base_path = sys._MEIPASS
|
|
37
|
+
except Exception:
|
|
38
|
+
base_path = Path(base).parent
|
|
39
|
+
return Path(base_path, relative_path)
|
|
40
|
+
|
|
41
|
+
|
|
31
42
|
class Enum():
|
|
32
43
|
def __init__(self, values: dict) -> None:
|
|
33
44
|
self.values = invert(values)
|
|
@@ -75,6 +86,7 @@ def enable_frame(parent: tk.Frame, enable: bool = True) -> None:
|
|
|
75
86
|
else:
|
|
76
87
|
child.configure(state=state)
|
|
77
88
|
|
|
89
|
+
|
|
78
90
|
def geometry(config: TomlConfig, file: Path, default: str = '') -> str:
|
|
79
91
|
if not default:
|
|
80
92
|
default = DEFAULT_GEOMETRY
|
|
@@ -62,6 +62,7 @@ def get_styles() -> ttk.Style:
|
|
|
62
62
|
|
|
63
63
|
style.configure('red-bg.TEntry', fieldbackground='red')
|
|
64
64
|
style.configure('green-bg.TEntry', fieldbackground='green')
|
|
65
|
+
style.configure('blue-bg.TEntry', fieldbackground='blue')
|
|
65
66
|
style.configure('orange-bg.TEntry', fieldbackground='orange')
|
|
66
67
|
style.configure(
|
|
67
68
|
'pale-umber-bg.TEntry', fieldbackground=COLOURS['pale-umber'])
|
|
@@ -71,6 +72,7 @@ def get_styles() -> ttk.Style:
|
|
|
71
72
|
# Entries - foreground
|
|
72
73
|
style.configure('red-fg.TEntry', foreground='red')
|
|
73
74
|
style.configure('green-fg.TEntry', foreground='green')
|
|
75
|
+
style.configure('blue-fg.TEntry', foreground='blue')
|
|
74
76
|
style.configure('orange-fg.TEntry', foreground='orange')
|
|
75
77
|
|
|
76
78
|
# Frames
|
|
@@ -83,6 +85,8 @@ def get_styles() -> ttk.Style:
|
|
|
83
85
|
# radiobuttons
|
|
84
86
|
style.configure('red-fg.TRadiobutton', foreground='red')
|
|
85
87
|
style.configure('green-fg.TRadiobutton', foreground='green')
|
|
88
|
+
style.configure('blue-fg.TRadiobutton', foreground='blue')
|
|
89
|
+
style.configure('orange-fg.TRadiobutton', foreground='orange')
|
|
86
90
|
|
|
87
91
|
# Tree view
|
|
88
92
|
style.map('Treeview',
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '0.2.11'
|
|
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
|
|
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
|