deepboard 0.0.1__tar.gz → 0.1.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.
- {deepboard-0.0.1 → deepboard-0.1.0}/PKG-INFO +3 -1
- {deepboard-0.0.1 → deepboard-0.1.0}/README.md +2 -0
- deepboard-0.1.0/deepboard/__version__.py +1 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/assets/datagrid.css +3 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/assets/right_panel.css +5 -1
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/assets/theme.css +2 -2
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/main.py +4 -2
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/datagrid.py +11 -3
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/row.py +2 -2
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/handlers.py +6 -4
- deepboard-0.1.0/deepboard/gui/pages/main_page/main_page.py +21 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/right_panel/template.py +4 -3
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/routes.py +5 -1
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/utils.py +6 -2
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard.egg-info/PKG-INFO +3 -1
- deepboard-0.0.1/deepboard/__version__.py +0 -1
- deepboard-0.0.1/deepboard/gui/pages/main_page/main_page.py +0 -17
- {deepboard-0.0.1 → deepboard-0.1.0}/MANIFEST.in +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/THEME.yml +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/assets/base.css +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/assets/base.js +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/assets/charts.css +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/assets/compare.css +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/assets/fileview.css +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/components/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/components/chart_type.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/components/legend.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/components/smoother.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/entry.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/compare_page.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/components/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/components/card_list.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/components/chart.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/components/compare_setup.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/components/split_card.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/components/utils.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/routes.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/compare_button.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/handlers.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/header.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/routes.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/sortable_column_js.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/utils.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/right_panel/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/right_panel/config.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/right_panel/hparams.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/right_panel/run_info.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/right_panel/scalars.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/not_found.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/__init__.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/cursor.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/logwritter.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/resultTable.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/results/configs/1.yml +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/results/configs/2.yml +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/results/configs/3.yml +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/results/configs/4.yml +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/results/configs/5.yml +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/results/configs/6.yml +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/results/myconfig.yml +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/scalar.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/table_schema.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard/resultTable/utils.py +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard.egg-info/SOURCES.txt +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard.egg-info/dependency_links.txt +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard.egg-info/entry_points.txt +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard.egg-info/requires.txt +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/deepboard.egg-info/top_level.txt +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/setup.cfg +0 -0
- {deepboard-0.0.1 → deepboard-0.1.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: deepboard
|
3
|
-
Version: 0.0
|
3
|
+
Version: 0.1.0
|
4
4
|
Summary: A tool to log you experiment results and explore them in a gui
|
5
5
|
Home-page: https://github.com/anthol42/deepboard
|
6
6
|
Author: Anthony Lavertu
|
@@ -42,6 +42,8 @@ curves of any runs. In addition, it lets you commpare training curves
|
|
42
42
|
between runs. You can even download the charts that you have generated:)
|
43
43
|
## 🔥 Screenshots 🔥
|
44
44
|

|
45
|
+
|
46
|
+
|
45
47
|

|
46
48
|
## 🌟 Project Philosophy
|
47
49
|
Before diving in, it’s important to understand the philosophy behind this project. In deep learning, it’s easy to get
|
@@ -8,6 +8,8 @@ curves of any runs. In addition, it lets you commpare training curves
|
|
8
8
|
between runs. You can even download the charts that you have generated:)
|
9
9
|
## 🔥 Screenshots 🔥
|
10
10
|

|
11
|
+
|
12
|
+
|
11
13
|

|
12
14
|
## 🌟 Project Philosophy
|
13
15
|
Before diving in, it’s important to understand the philosophy behind this project. In deep learning, it’s easy to get
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.1.0"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
.right-panel {
|
3
3
|
position: relative;
|
4
4
|
width: 100%;
|
5
5
|
display: flex;
|
@@ -7,6 +7,10 @@
|
|
7
7
|
align-items: center;
|
8
8
|
}
|
9
9
|
|
10
|
+
.right-panel-closed{
|
11
|
+
width: 0;
|
12
|
+
visibility: hidden;
|
13
|
+
}
|
10
14
|
.right-panel-placeholder {
|
11
15
|
color: var(--secondary-text-color);
|
12
16
|
font-size: 1.1rem;
|
@@ -3,8 +3,8 @@
|
|
3
3
|
--background-color: #121212;
|
4
4
|
--text_color: #e0e0e0;
|
5
5
|
--secondary-text-color: #ccc;
|
6
|
-
--primary-color: #
|
7
|
-
--primary-color-hover: #
|
6
|
+
--primary-color: #50A76F;
|
7
|
+
--primary-color-hover: #6FBF91;
|
8
8
|
--button-shadow-color: rgba(255, 255, 255, 0.15);
|
9
9
|
|
10
10
|
--success-color: #4caf50;
|
@@ -10,6 +10,7 @@ from deepboard.gui.pages import _not_found
|
|
10
10
|
from deepboard.resultTable import ResultTable
|
11
11
|
from fh_plotly import plotly_headers
|
12
12
|
|
13
|
+
DEBUG = False
|
13
14
|
# Create config files to customize the UI
|
14
15
|
initiate_files()
|
15
16
|
|
@@ -23,7 +24,8 @@ prepare_db()
|
|
23
24
|
# Load the result Table
|
24
25
|
rTable = ResultTable(DATABASE)
|
25
26
|
|
26
|
-
|
27
|
+
cls = FastHTMLWithLiveReload if DEBUG else FastHTML
|
28
|
+
app = cls(
|
27
29
|
exception_handlers={404: _not_found},
|
28
30
|
hdrs=(
|
29
31
|
Link(rel='stylesheet', href='assets/base.css', type='text/css'),
|
@@ -81,4 +83,4 @@ def get(session, elementIds: str, top: int, left: int):
|
|
81
83
|
|
82
84
|
build_main_page_endpoints(rt)
|
83
85
|
build_compare_routes(rt)
|
84
|
-
serve(reload=
|
86
|
+
serve(reload=DEBUG)
|
@@ -3,7 +3,10 @@ from fasthtml.common import *
|
|
3
3
|
from .row import Row
|
4
4
|
from .header import Header, HeaderRename
|
5
5
|
|
6
|
-
def DataGrid(session, rename_col: str = None, wrapincontainer: bool = False):
|
6
|
+
def DataGrid(session, rename_col: str = None, wrapincontainer: bool = False, fullscreen: bool = False):
|
7
|
+
"""
|
8
|
+
Note that fullscreen only work if the container is requested because it applies on the container
|
9
|
+
"""
|
7
10
|
from __main__ import rTable, CONFIG
|
8
11
|
|
9
12
|
if "datagrid" not in session:
|
@@ -44,7 +47,12 @@ def DataGrid(session, rename_col: str = None, wrapincontainer: bool = False):
|
|
44
47
|
)
|
45
48
|
),
|
46
49
|
Tbody(
|
47
|
-
*[Row(row,
|
50
|
+
*[Row(row,
|
51
|
+
run_id,
|
52
|
+
max_decimals=CONFIG.MAX_DEC,
|
53
|
+
selected=run_id in rows_selected,
|
54
|
+
hidden=run_id in rows_hidden,
|
55
|
+
fullscreen=fullscreen) for row, run_id in zip(data, run_ids)],
|
48
56
|
),
|
49
57
|
cls="data-grid"
|
50
58
|
),
|
@@ -52,7 +60,7 @@ def DataGrid(session, rename_col: str = None, wrapincontainer: bool = False):
|
|
52
60
|
if wrapincontainer:
|
53
61
|
return Div(
|
54
62
|
table,
|
55
|
-
cls="scroll-container",
|
63
|
+
cls="scroll-container" if not fullscreen else "scroll-container fullscreen",
|
56
64
|
id="experiment-table",
|
57
65
|
),
|
58
66
|
else:
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from typing import *
|
2
2
|
from fasthtml.common import *
|
3
3
|
from .utils import format_value
|
4
|
-
def Row(data, run_id, selected: bool, hidden: bool, max_decimals: int):
|
4
|
+
def Row(data, run_id, selected: bool, hidden: bool, max_decimals: int, fullscreen: bool):
|
5
5
|
cls = "table-row"
|
6
6
|
if selected:
|
7
7
|
cls += " table-row-selected"
|
@@ -11,7 +11,7 @@ def Row(data, run_id, selected: bool, hidden: bool, max_decimals: int):
|
|
11
11
|
|
12
12
|
return Tr(
|
13
13
|
*[Td(format_value(value, decimals=max_decimals)) for value in data],
|
14
|
-
hx_get=f"/click_row?run_id={run_id}", # HTMX will GET this URL
|
14
|
+
hx_get=f"/click_row?run_id={run_id}&fullscreen={fullscreen}", # HTMX will GET this URL
|
15
15
|
hx_trigger="click[!event.ctrlKey && !event.metaKey]",
|
16
16
|
hx_target="#experiment-table", # Target DOM element to update
|
17
17
|
hx_swap="innerHTML", # Optional: how to replace content
|
@@ -2,13 +2,15 @@ from typing import *
|
|
2
2
|
from fasthtml.common import *
|
3
3
|
from .datagrid import DataGrid, CompareButton
|
4
4
|
from .right_panel import RightPanel, reset_scalar_session
|
5
|
-
|
5
|
+
from .main_page import MainPage
|
6
6
|
|
7
7
|
# Choose a row in the datagrid
|
8
|
-
def click_row_handler(session, run_id: int):
|
8
|
+
def click_row_handler(session, run_id: int, fullscreen: bool):
|
9
9
|
reset_scalar_session(session)
|
10
10
|
if "datagrid" not in session:
|
11
11
|
session["datagrid"] = dict()
|
12
12
|
session["datagrid"]["selected-rows"] = [run_id]
|
13
|
-
|
14
|
-
|
13
|
+
if fullscreen:
|
14
|
+
return MainPage(session, swap=True)
|
15
|
+
else:
|
16
|
+
return DataGrid(session), CompareButton(session, swap=True), RightPanel(session)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
from typing import *
|
2
|
+
from fasthtml.common import *
|
3
|
+
from .datagrid import DataGrid, CompareButton
|
4
|
+
from .right_panel import RightPanel
|
5
|
+
|
6
|
+
def MainPage(session, swap: bool = False, fullscreen: bool = False):
|
7
|
+
return Div(
|
8
|
+
Div(
|
9
|
+
DataGrid(session, wrapincontainer=True, fullscreen=fullscreen),
|
10
|
+
CompareButton(session),
|
11
|
+
Div(hx_target="#container",
|
12
|
+
hx_swap="outerHTML",
|
13
|
+
hx_trigger="keyup[key=='f' || key=='F'] from:body",
|
14
|
+
hx_get=f"/fullscreen?full={'true' if not fullscreen else 'false'}",),
|
15
|
+
cls="table-container"
|
16
|
+
),
|
17
|
+
RightPanel(session, closed = fullscreen),
|
18
|
+
cls='container',
|
19
|
+
id="container",
|
20
|
+
hx_swap_oob="true" if swap else None
|
21
|
+
)
|
@@ -56,10 +56,10 @@ def OpenPanel(session, run_id: int, active_tab: str = 'scalars'):
|
|
56
56
|
cls="open-right-panel"
|
57
57
|
)
|
58
58
|
|
59
|
-
def RightPanel(session):
|
59
|
+
def RightPanel(session, closed: bool = False):
|
60
60
|
placeholder_text = [
|
61
|
-
P("
|
62
|
-
P("
|
61
|
+
P("⌘ / ctrl + click to compare runs", cls="right-panel-placeholder"),
|
62
|
+
P("'F' for fullscreen", cls="right-panel-placeholder")
|
63
63
|
]
|
64
64
|
if "datagrid" in session and session["datagrid"].get("selected-rows") and len(session["datagrid"]["selected-rows"]) == 1:
|
65
65
|
run_id = session["datagrid"]["selected-rows"][0]
|
@@ -75,6 +75,7 @@ def RightPanel(session):
|
|
75
75
|
) if run_id is not None else None,
|
76
76
|
Div(*placeholder_text) if run_id is None else OpenPanel(session, run_id),
|
77
77
|
id='right-panel',
|
78
|
+
cls="right-panel" if not closed else "right-panel-closed",
|
78
79
|
hx_swap_oob='true'
|
79
80
|
),
|
80
81
|
|
@@ -6,6 +6,7 @@ from .main_page import MainPage
|
|
6
6
|
def build_main_page_endpoints(rt):
|
7
7
|
rt("/click_row")(click_row_handler)
|
8
8
|
rt("/reset")(reset)
|
9
|
+
rt("/fullscreen")(fullscreen)
|
9
10
|
build_datagrid_endpoints(rt)
|
10
11
|
build_right_panel_routes(rt)
|
11
12
|
|
@@ -13,4 +14,7 @@ def reset(session):
|
|
13
14
|
if "show_hidden" not in session:
|
14
15
|
session["show_hidden"] = False
|
15
16
|
session["datagrid"] = dict()
|
16
|
-
return MainPage(session, swap=True)
|
17
|
+
return MainPage(session, swap=True)
|
18
|
+
|
19
|
+
def fullscreen(session, full: bool):
|
20
|
+
return MainPage(session, swap=True, fullscreen=full)
|
@@ -139,13 +139,17 @@ def make_fig(lines, type: str = "step", smoothness: float = 0.):
|
|
139
139
|
def smart_round(val, decimals=4):
|
140
140
|
"""
|
141
141
|
Round a float to the given number of decimal places. However, if the float already has less decimal, noting is done!
|
142
|
+
In addition, if the value is about to get rounded to zero, it is converted to scientific notation.
|
142
143
|
:param val: The value to round.
|
143
144
|
:param decimals: The maximum number of decimal places to round.
|
144
145
|
:return: The rounded value.
|
145
146
|
"""
|
147
|
+
val_dec = Decimal(str(val))
|
146
148
|
quantizer = Decimal('1').scaleb(-decimals)
|
147
|
-
|
148
|
-
|
149
|
+
rounded = val_dec.quantize(quantizer, rounding=ROUND_HALF_UP)
|
150
|
+
if rounded.is_zero() and not val_dec.is_zero():
|
151
|
+
return f"{val:.{decimals}e}"
|
152
|
+
return str(rounded.normalize())
|
149
153
|
|
150
154
|
def initiate_files():
|
151
155
|
abs_path = os.path.abspath(os.path.dirname(__file__))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: deepboard
|
3
|
-
Version: 0.0
|
3
|
+
Version: 0.1.0
|
4
4
|
Summary: A tool to log you experiment results and explore them in a gui
|
5
5
|
Home-page: https://github.com/anthol42/deepboard
|
6
6
|
Author: Anthony Lavertu
|
@@ -42,6 +42,8 @@ curves of any runs. In addition, it lets you commpare training curves
|
|
42
42
|
between runs. You can even download the charts that you have generated:)
|
43
43
|
## 🔥 Screenshots 🔥
|
44
44
|

|
45
|
+
|
46
|
+
|
45
47
|

|
46
48
|
## 🌟 Project Philosophy
|
47
49
|
Before diving in, it’s important to understand the philosophy behind this project. In deep learning, it’s easy to get
|
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "0.0.1"
|
@@ -1,17 +0,0 @@
|
|
1
|
-
from typing import *
|
2
|
-
from fasthtml.common import *
|
3
|
-
from .datagrid import DataGrid, CompareButton
|
4
|
-
from .right_panel import RightPanel
|
5
|
-
|
6
|
-
def MainPage(session, swap: bool = False):
|
7
|
-
return Div(
|
8
|
-
Div(
|
9
|
-
DataGrid(session, wrapincontainer=True),
|
10
|
-
CompareButton(session),
|
11
|
-
cls="table-container"
|
12
|
-
),
|
13
|
-
RightPanel(session),
|
14
|
-
cls='container',
|
15
|
-
id="container",
|
16
|
-
hx_swap_oob="true" if swap else None
|
17
|
-
)
|
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
|
{deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/components/card_list.py
RENAMED
File without changes
|
File without changes
|
{deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/components/compare_setup.py
RENAMED
File without changes
|
{deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/compare_page/components/split_card.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/compare_button.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{deepboard-0.0.1 → deepboard-0.1.0}/deepboard/gui/pages/main_page/datagrid/sortable_column_js.py
RENAMED
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
|