snk-cli 0.3.0__tar.gz → 0.3.2__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.
- {snk_cli-0.3.0 → snk_cli-0.3.2}/PKG-INFO +5 -5
- {snk_cli-0.3.0 → snk_cli-0.3.2}/pyproject.toml +4 -4
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/__about__.py +1 -1
- snk_cli-0.3.2/src/snk_cli/subcommands/profile.py +110 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/subcommands/script.py +3 -1
- snk_cli-0.3.2/tests/test_cli/test_profile.py +69 -0
- snk_cli-0.3.0/src/snk_cli/subcommands/profile.py +0 -60
- {snk_cli-0.3.0 → snk_cli-0.3.2}/.github/workflows/publish.yml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/.github/workflows/tests.yml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/.gitignore +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/LICENSE.txt +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/README.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/index.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/reference/cli.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/reference/config.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/reference/dynamic_typer.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/reference/options.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/reference/subcommands.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/reference/testing.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/reference/utils.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/reference/validate.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/docs/reference/workflow.md +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/mkdocs.yml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/__init__.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/cli.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/conda.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/config/__init__.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/config/config.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/config/utils.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/dynamic_typer.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/options/__init__.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/options/option.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/options/utils.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/subcommands/__init__.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/subcommands/config.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/subcommands/env.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/subcommands/run.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/testing.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/utils.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/validate.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/src/snk_cli/workflow.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/__init__.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/conftest.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/artic_v4.1.bed +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/config.yaml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/cov.fasta +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/print_config/Snakefile +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/print_config/cli.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/print_config/config.yaml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/print_config/snk.yaml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/cli.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/config.yaml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/resources/data.txt +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/snk.yaml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/things/__about__.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/workflow/Snakefile +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/workflow/envs/wget.yml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/workflow/profiles/base/config.yaml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/workflow/profiles/slurm/config.yaml +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/data/workflow/workflow/scripts/hello.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/test_cli/__init__.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/test_cli/test_dynamic_options.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/test_cli/test_run.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/test_cli/test_snk_config.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/test_cli/test_subcommands.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/test_cli/test_validate.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/test_cli/test_workflow_cli.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/test_conda_env.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/test_dynamic_typer.py +0 -0
- {snk_cli-0.3.0 → snk_cli-0.3.2}/tests/utils.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: snk-cli
|
|
3
|
-
Version: 0.3.
|
|
4
|
-
Project-URL: Documentation, https://github.com/
|
|
5
|
-
Project-URL: Issues, https://github.com/
|
|
6
|
-
Project-URL: Source, https://github.com/
|
|
3
|
+
Version: 0.3.2
|
|
4
|
+
Project-URL: Documentation, https://github.com/wytamma/snk-cli#readme
|
|
5
|
+
Project-URL: Issues, https://github.com/wytamma/snk-cli/issues
|
|
6
|
+
Project-URL: Source, https://github.com/wytamma/snk-cli
|
|
7
7
|
Author-email: Wytamma Wirth <wytamma.wirth@me.com>
|
|
8
8
|
License-Expression: MIT
|
|
9
9
|
License-File: LICENSE.txt
|
|
@@ -23,7 +23,7 @@ Requires-Dist: gitpython~=3.1
|
|
|
23
23
|
Requires-Dist: makefun~=1.15
|
|
24
24
|
Requires-Dist: pulp<2.8
|
|
25
25
|
Requires-Dist: snakemake>=7
|
|
26
|
-
Requires-Dist: typer[all]~=0.9
|
|
26
|
+
Requires-Dist: typer[all]~=0.9
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
28
28
|
|
|
29
29
|
# snk-cli
|
|
@@ -26,7 +26,7 @@ classifiers = [
|
|
|
26
26
|
]
|
|
27
27
|
dependencies = [
|
|
28
28
|
"snakemake>=7",
|
|
29
|
-
"typer[all]~=0.9
|
|
29
|
+
"typer[all]~=0.9",
|
|
30
30
|
"GitPython~=3.1",
|
|
31
31
|
"pulp<2.8", # Pin pulp <2.8 for snakemake: https://github.com/snakemake/snakemake/issues/2607
|
|
32
32
|
"art~=5.9",
|
|
@@ -35,9 +35,9 @@ dependencies = [
|
|
|
35
35
|
]
|
|
36
36
|
|
|
37
37
|
[project.urls]
|
|
38
|
-
Documentation = "https://github.com/
|
|
39
|
-
Issues = "https://github.com/
|
|
40
|
-
Source = "https://github.com/
|
|
38
|
+
Documentation = "https://github.com/wytamma/snk-cli#readme"
|
|
39
|
+
Issues = "https://github.com/wytamma/snk-cli/issues"
|
|
40
|
+
Source = "https://github.com/wytamma/snk-cli"
|
|
41
41
|
|
|
42
42
|
[tool.hatch.version]
|
|
43
43
|
path = "src/snk_cli/__about__.py"
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from snk_cli.dynamic_typer import DynamicTyper
|
|
3
|
+
from ..workflow import Workflow
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
from rich.syntax import Syntax
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ProfileApp(DynamicTyper):
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
workflow: Workflow,
|
|
13
|
+
):
|
|
14
|
+
self.workflow = workflow
|
|
15
|
+
self.register_command(self.list, help="List the profiles in the workflow.")
|
|
16
|
+
self.register_command(self.show, help="Show the contents of a profile.")
|
|
17
|
+
self.register_command(self.edit, help="Edit the contents of a profile.")
|
|
18
|
+
|
|
19
|
+
def list(
|
|
20
|
+
self,
|
|
21
|
+
verbose: bool = typer.Option(
|
|
22
|
+
False, "--verbose", "-v", help="Show profiles as paths."
|
|
23
|
+
),
|
|
24
|
+
):
|
|
25
|
+
from rich.console import Console
|
|
26
|
+
from rich.table import Table
|
|
27
|
+
|
|
28
|
+
table = Table("Name", "CMD", show_header=True, show_lines=True)
|
|
29
|
+
if verbose:
|
|
30
|
+
table.add_column("Path")
|
|
31
|
+
for profile in self.workflow.profiles:
|
|
32
|
+
if verbose:
|
|
33
|
+
path = str(profile.resolve())
|
|
34
|
+
table.add_row(
|
|
35
|
+
profile.stem,
|
|
36
|
+
f"{self.workflow.name} profile show {profile.stem}",
|
|
37
|
+
path,
|
|
38
|
+
)
|
|
39
|
+
else:
|
|
40
|
+
table.add_row(
|
|
41
|
+
profile.stem, f"{self.workflow.name} profile show {profile.stem}"
|
|
42
|
+
)
|
|
43
|
+
console = Console()
|
|
44
|
+
console.print(table)
|
|
45
|
+
|
|
46
|
+
def _get_profile_path(self, name: str) -> Path:
|
|
47
|
+
profile = [
|
|
48
|
+
p for p in self.workflow.profiles if p.name == name or p.stem == name
|
|
49
|
+
]
|
|
50
|
+
if not profile:
|
|
51
|
+
self.error(f"Profile {name} not found!")
|
|
52
|
+
return profile[0] / "config.yaml"
|
|
53
|
+
|
|
54
|
+
def show(
|
|
55
|
+
self,
|
|
56
|
+
name: str = typer.Argument(..., help="The name of the profile."),
|
|
57
|
+
pretty: bool = typer.Option(
|
|
58
|
+
False, "--pretty", "-p", help="Pretty print the profile."
|
|
59
|
+
),
|
|
60
|
+
):
|
|
61
|
+
profile_path = self._get_profile_path(name)
|
|
62
|
+
profile_file_text = profile_path.read_text()
|
|
63
|
+
if pretty:
|
|
64
|
+
syntax = Syntax(profile_file_text, "yaml")
|
|
65
|
+
console = Console()
|
|
66
|
+
console.print(syntax)
|
|
67
|
+
else:
|
|
68
|
+
typer.echo(profile_file_text)
|
|
69
|
+
|
|
70
|
+
def _open_text_editor(self, file_path):
|
|
71
|
+
"""
|
|
72
|
+
Opens the system's default text editor to edit the specified file.
|
|
73
|
+
|
|
74
|
+
Parameters:
|
|
75
|
+
file_path (str): The path to the file to be edited.
|
|
76
|
+
"""
|
|
77
|
+
import subprocess
|
|
78
|
+
import os
|
|
79
|
+
import platform
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
if platform.system() == "Windows":
|
|
83
|
+
os.startfile(file_path)
|
|
84
|
+
elif platform.system() == "Darwin": # macOS
|
|
85
|
+
subprocess.call(("open", file_path))
|
|
86
|
+
else: # Linux and other Unix-like systems
|
|
87
|
+
editors = ["nano", "vim", "vi"]
|
|
88
|
+
editor = None
|
|
89
|
+
for e in editors:
|
|
90
|
+
if (
|
|
91
|
+
subprocess.call(
|
|
92
|
+
["which", e], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
93
|
+
)
|
|
94
|
+
== 0
|
|
95
|
+
):
|
|
96
|
+
editor = e
|
|
97
|
+
break
|
|
98
|
+
if editor:
|
|
99
|
+
subprocess.call([editor, file_path])
|
|
100
|
+
else:
|
|
101
|
+
self.error(
|
|
102
|
+
"No suitable text editor found. Please install nano or vim."
|
|
103
|
+
)
|
|
104
|
+
except Exception as e:
|
|
105
|
+
print(f"An error occurred: {e}")
|
|
106
|
+
|
|
107
|
+
def edit(self, name: str = typer.Argument(..., help="The name of the profile.")):
|
|
108
|
+
profile_path = self._get_profile_path(name)
|
|
109
|
+
## open the profile in the system editor
|
|
110
|
+
self._open_text_editor(profile_path)
|
|
@@ -113,7 +113,9 @@ class ScriptApp(DynamicTyper):
|
|
|
113
113
|
):
|
|
114
114
|
script_path = self._get_script_path(name)
|
|
115
115
|
executor = self._get_executor(script_path.suffix[1:])
|
|
116
|
-
cmd = [executor, f'"{script_path}"']
|
|
116
|
+
cmd = [executor, f'"{script_path}"']
|
|
117
|
+
if args:
|
|
118
|
+
cmd += args
|
|
117
119
|
if env:
|
|
118
120
|
env_path = self._get_conda_env_path(env)
|
|
119
121
|
env = conda_environment_factory(env_path, self.conda_prefix_dir)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import subprocess
|
|
3
|
+
import os # noqa: F401
|
|
4
|
+
import platform # noqa: F401
|
|
5
|
+
import typer # noqa: F401
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from unittest.mock import patch, call
|
|
8
|
+
|
|
9
|
+
from ..utils import SnkCliRunner
|
|
10
|
+
|
|
11
|
+
@pytest.fixture
|
|
12
|
+
def mock_platform_system():
|
|
13
|
+
with patch('platform.system') as mock:
|
|
14
|
+
yield mock
|
|
15
|
+
|
|
16
|
+
@pytest.fixture
|
|
17
|
+
def mock_os_startfile():
|
|
18
|
+
if platform.system() == 'Windows':
|
|
19
|
+
with patch('os.startfile') as mock:
|
|
20
|
+
yield mock
|
|
21
|
+
else:
|
|
22
|
+
yield None
|
|
23
|
+
|
|
24
|
+
@pytest.fixture
|
|
25
|
+
def mock_subprocess_call():
|
|
26
|
+
with patch('subprocess.call') as mock:
|
|
27
|
+
yield mock
|
|
28
|
+
|
|
29
|
+
def test_open_text_editor_windows(mock_platform_system, mock_os_startfile, local_runner: SnkCliRunner):
|
|
30
|
+
mock_platform_system.return_value = 'Windows'
|
|
31
|
+
file_path = Path('tests/data/workflow/workflow/profiles/slurm/config.yaml')
|
|
32
|
+
|
|
33
|
+
res = local_runner(["profile", "edit", "slurm"])
|
|
34
|
+
assert res.exit_code == 0, res.stderr
|
|
35
|
+
if mock_os_startfile:
|
|
36
|
+
mock_os_startfile.assert_called_once_with(file_path)
|
|
37
|
+
|
|
38
|
+
def test_open_text_editor_mac(mock_platform_system, mock_subprocess_call, local_runner: SnkCliRunner):
|
|
39
|
+
mock_platform_system.return_value = 'Darwin'
|
|
40
|
+
file_path = Path('tests/data/workflow/workflow/profiles/slurm/config.yaml')
|
|
41
|
+
|
|
42
|
+
res = local_runner(["profile", "edit", "slurm"])
|
|
43
|
+
assert res.exit_code == 0, res.stderr
|
|
44
|
+
mock_subprocess_call.assert_called_once_with(('open', file_path))
|
|
45
|
+
|
|
46
|
+
def test_open_text_editor_linux(mock_platform_system, mock_subprocess_call, local_runner: SnkCliRunner):
|
|
47
|
+
mock_platform_system.return_value = 'Linux'
|
|
48
|
+
file_path = Path('tests/data/workflow/workflow/profiles/slurm/config.yaml')
|
|
49
|
+
|
|
50
|
+
with patch('subprocess.call') as mock_call:
|
|
51
|
+
mock_call.side_effect = [1, 1, 0] # Mocking 'which' command results: nano not found, vim not found, vi found
|
|
52
|
+
|
|
53
|
+
res = local_runner(["profile", "edit", "slurm"])
|
|
54
|
+
assert res.exit_code == 0, res.stderr
|
|
55
|
+
mock_call.assert_has_calls([call(['which', 'nano'], stdout=subprocess.PIPE, stderr=subprocess.PIPE),
|
|
56
|
+
call(['which', 'vim'], stdout=subprocess.PIPE, stderr=subprocess.PIPE),
|
|
57
|
+
call(['which', 'vi'], stdout=subprocess.PIPE, stderr=subprocess.PIPE),
|
|
58
|
+
call(['vi', file_path])])
|
|
59
|
+
|
|
60
|
+
def test_open_text_editor_no_editor_found(mock_platform_system, mock_subprocess_call, local_runner: SnkCliRunner):
|
|
61
|
+
mock_platform_system.return_value = 'Linux'
|
|
62
|
+
|
|
63
|
+
with patch('subprocess.call') as mock_call:
|
|
64
|
+
mock_call.side_effect = [1, 1, 1] # Mocking 'which' command results: none of the editors found
|
|
65
|
+
|
|
66
|
+
with patch('typer.secho') as mock_print:
|
|
67
|
+
res = local_runner(["profile", "edit", "slurm"])
|
|
68
|
+
assert res.exit_code == 0, res.stderr
|
|
69
|
+
mock_print.assert_called_once_with("No suitable text editor found. Please install nano or vim.", fg='red', err=True)
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import typer
|
|
2
|
-
from snk_cli.dynamic_typer import DynamicTyper
|
|
3
|
-
from ..workflow import Workflow
|
|
4
|
-
from rich.console import Console
|
|
5
|
-
from rich.syntax import Syntax
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class ProfileApp(DynamicTyper):
|
|
10
|
-
def __init__(
|
|
11
|
-
self,
|
|
12
|
-
workflow: Workflow,
|
|
13
|
-
):
|
|
14
|
-
self.workflow = workflow
|
|
15
|
-
self.register_command(self.list, help="List the profiles in the workflow.")
|
|
16
|
-
self.register_command(
|
|
17
|
-
self.show, help="Show the contents of a profile."
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
def list(
|
|
21
|
-
self,
|
|
22
|
-
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show profiles as paths."),
|
|
23
|
-
):
|
|
24
|
-
from rich.console import Console
|
|
25
|
-
from rich.table import Table
|
|
26
|
-
table = Table("Name", "CMD", show_header=True, show_lines=True)
|
|
27
|
-
if verbose:
|
|
28
|
-
table.add_column("Path")
|
|
29
|
-
for profile in self.workflow.profiles:
|
|
30
|
-
if verbose:
|
|
31
|
-
path = str(profile.resolve())
|
|
32
|
-
table.add_row(profile.stem, f"{self.workflow.name} profile show {profile.stem}", path)
|
|
33
|
-
else:
|
|
34
|
-
table.add_row(profile.stem, f"{self.workflow.name} profile show {profile.stem}")
|
|
35
|
-
console = Console()
|
|
36
|
-
console.print(table)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def _get_profile_path(self, name: str) -> Path:
|
|
41
|
-
profile = [p for p in self.workflow.profiles if p.name == name or p.stem == name]
|
|
42
|
-
if not profile:
|
|
43
|
-
self.error(f"Profile {name} not found!")
|
|
44
|
-
return profile[0] / "config.yaml"
|
|
45
|
-
|
|
46
|
-
def show(
|
|
47
|
-
self,
|
|
48
|
-
name: str = typer.Argument(..., help="The name of the profile."),
|
|
49
|
-
pretty: bool = typer.Option(
|
|
50
|
-
False, "--pretty", "-p", help="Pretty print the profile."
|
|
51
|
-
),
|
|
52
|
-
):
|
|
53
|
-
profile_path = self._get_profile_path(name)
|
|
54
|
-
profile_file_text = profile_path.read_text()
|
|
55
|
-
if pretty:
|
|
56
|
-
syntax = Syntax(profile_file_text, "yaml")
|
|
57
|
-
console = Console()
|
|
58
|
-
console.print(syntax)
|
|
59
|
-
else:
|
|
60
|
-
typer.echo(profile_file_text)
|
|
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
|
|
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
|