astToolkit 0.1.1__tar.gz → 0.1.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.
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/PKG-INFO +1 -1
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_toolGrab.py +13 -21
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_toolIfThis.py +2 -2
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/transformationTools.py +3 -3
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit.egg-info/PKG-INFO +1 -1
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/pyproject.toml +1 -1
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/toolFactory/astFactory.py +13 -1
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/toolFactory/astFactory_annex.py +10 -11
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/LICENSE +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/README.md +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/__init__.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_astTypes.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_toolBe.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_toolDOT.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_toolMake.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_toolThen.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_toolboxAST.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_toolboxContainers.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_toolboxPython.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_types.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/_typesSpecial.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/py.typed +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit/theSSOT.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit.egg-info/SOURCES.txt +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit.egg-info/dependency_links.txt +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit.egg-info/requires.txt +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/astToolkit.egg-info/top_level.txt +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/setup.cfg +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/tests/test_basic.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/toolFactory/Z0Z_hardcoded.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/toolFactory/Z0Z_makeAstTools.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/toolFactory/__init__.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/toolFactory/docstrings.py +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/toolFactory/py.typed +0 -0
- {asttoolkit-0.1.1 → asttoolkit-0.1.2}/toolFactory/startHere.py +0 -0
|
@@ -23,7 +23,7 @@ class Grab:
|
|
|
23
23
|
def annotationAttribute(action: Callable[[ast.expr | (ast.expr | None)], ast.expr | (ast.expr | None)]) -> Callable[[hasDOTannotation], hasDOTannotation]:
|
|
24
24
|
|
|
25
25
|
def workhorse(node: hasDOTannotation) -> hasDOTannotation:
|
|
26
|
-
node.annotation = action(node.annotation)
|
|
26
|
+
node.annotation = action(node.annotation) # type: ignore[reportAttributeAccessIssue]
|
|
27
27
|
return node
|
|
28
28
|
return workhorse
|
|
29
29
|
|
|
@@ -31,7 +31,7 @@ class Grab:
|
|
|
31
31
|
def argAttribute(action: Callable[[ast_Identifier | (ast_Identifier | None)], ast_Identifier | (ast_Identifier | None)]) -> Callable[[hasDOTarg], hasDOTarg]:
|
|
32
32
|
|
|
33
33
|
def workhorse(node: hasDOTarg) -> hasDOTarg:
|
|
34
|
-
node.arg = action(node.arg)
|
|
34
|
+
node.arg = action(node.arg) # type: ignore[reportAttributeAccessIssue]
|
|
35
35
|
return node
|
|
36
36
|
return workhorse
|
|
37
37
|
|
|
@@ -39,7 +39,7 @@ class Grab:
|
|
|
39
39
|
def argsAttribute(action: Callable[[ast.arguments | Sequence[ast.expr] | list[ast.arg]], ast.arguments | Sequence[ast.expr] | list[ast.arg]]) -> Callable[[hasDOTargs], hasDOTargs]:
|
|
40
40
|
|
|
41
41
|
def workhorse(node: hasDOTargs) -> hasDOTargs:
|
|
42
|
-
node.args = action(node.args)
|
|
42
|
+
node.args = action(node.args) # type: ignore[reportAttributeAccessIssue]
|
|
43
43
|
return node
|
|
44
44
|
return workhorse
|
|
45
45
|
|
|
@@ -79,7 +79,7 @@ class Grab:
|
|
|
79
79
|
def bodyAttribute(action: Callable[[Sequence[ast.stmt] | ast.expr], Sequence[ast.stmt] | ast.expr]) -> Callable[[hasDOTbody], hasDOTbody]:
|
|
80
80
|
|
|
81
81
|
def workhorse(node: hasDOTbody) -> hasDOTbody:
|
|
82
|
-
node.body = action(node.body)
|
|
82
|
+
node.body = action(node.body) # type: ignore[reportAttributeAccessIssue]
|
|
83
83
|
return node
|
|
84
84
|
return workhorse
|
|
85
85
|
|
|
@@ -295,7 +295,7 @@ class Grab:
|
|
|
295
295
|
def keysAttribute(action: Callable[[Sequence[ast.expr | None] | Sequence[ast.expr]], Sequence[ast.expr | None] | Sequence[ast.expr]]) -> Callable[[hasDOTkeys], hasDOTkeys]:
|
|
296
296
|
|
|
297
297
|
def workhorse(node: hasDOTkeys) -> hasDOTkeys:
|
|
298
|
-
node.keys = list(action(node.keys))
|
|
298
|
+
node.keys = list(action(node.keys)) # type: ignore[reportAttributeAccessIssue]
|
|
299
299
|
return node
|
|
300
300
|
return workhorse
|
|
301
301
|
|
|
@@ -407,7 +407,7 @@ class Grab:
|
|
|
407
407
|
def nameAttribute(action: Callable[[ast_Identifier | (ast_Identifier | None) | ast_Identifier | ast.Name], ast_Identifier | (ast_Identifier | None) | ast_Identifier | ast.Name]) -> Callable[[hasDOTname], hasDOTname]:
|
|
408
408
|
|
|
409
409
|
def workhorse(node: hasDOTname) -> hasDOTname:
|
|
410
|
-
node.name = action(node.name)
|
|
410
|
+
node.name = action(node.name) # type: ignore[reportAttributeAccessIssue]
|
|
411
411
|
return node
|
|
412
412
|
return workhorse
|
|
413
413
|
|
|
@@ -415,7 +415,7 @@ class Grab:
|
|
|
415
415
|
def namesAttribute(action: Callable[[list[ast.alias] | list[ast_Identifier]], list[ast.alias] | list[ast_Identifier]]) -> Callable[[hasDOTnames], hasDOTnames]:
|
|
416
416
|
|
|
417
417
|
def workhorse(node: hasDOTnames) -> hasDOTnames:
|
|
418
|
-
node.names = action(node.names)
|
|
418
|
+
node.names = action(node.names) # type: ignore[reportAttributeAccessIssue]
|
|
419
419
|
return node
|
|
420
420
|
return workhorse
|
|
421
421
|
|
|
@@ -423,7 +423,7 @@ class Grab:
|
|
|
423
423
|
def opAttribute(action: Callable[[ast.operator | ast.boolop | ast.unaryop], ast.operator | ast.boolop | ast.unaryop]) -> Callable[[hasDOTop], hasDOTop]:
|
|
424
424
|
|
|
425
425
|
def workhorse(node: hasDOTop) -> hasDOTop:
|
|
426
|
-
node.op = action(node.op)
|
|
426
|
+
node.op = action(node.op) # type: ignore[reportAttributeAccessIssue]
|
|
427
427
|
return node
|
|
428
428
|
return workhorse
|
|
429
429
|
|
|
@@ -455,7 +455,7 @@ class Grab:
|
|
|
455
455
|
def orelseAttribute(action: Callable[[Sequence[ast.stmt] | ast.expr], Sequence[ast.stmt] | ast.expr]) -> Callable[[hasDOTorelse], hasDOTorelse]:
|
|
456
456
|
|
|
457
457
|
def workhorse(node: hasDOTorelse) -> hasDOTorelse:
|
|
458
|
-
node.orelse = action(node.orelse)
|
|
458
|
+
node.orelse = action(node.orelse) # type: ignore[reportAttributeAccessIssue]
|
|
459
459
|
return node
|
|
460
460
|
return workhorse
|
|
461
461
|
|
|
@@ -463,7 +463,7 @@ class Grab:
|
|
|
463
463
|
def patternAttribute(action: Callable[[ast.pattern | (ast.pattern | None)], ast.pattern | (ast.pattern | None)]) -> Callable[[hasDOTpattern], hasDOTpattern]:
|
|
464
464
|
|
|
465
465
|
def workhorse(node: hasDOTpattern) -> hasDOTpattern:
|
|
466
|
-
node.pattern = action(node.pattern)
|
|
466
|
+
node.pattern = action(node.pattern) # type: ignore[reportAttributeAccessIssue]
|
|
467
467
|
return node
|
|
468
468
|
return workhorse
|
|
469
469
|
|
|
@@ -495,7 +495,7 @@ class Grab:
|
|
|
495
495
|
def returnsAttribute(action: Callable[[ast.expr | (ast.expr | None)], ast.expr | (ast.expr | None)]) -> Callable[[hasDOTreturns], hasDOTreturns]:
|
|
496
496
|
|
|
497
497
|
def workhorse(node: hasDOTreturns) -> hasDOTreturns:
|
|
498
|
-
node.returns = action(node.returns)
|
|
498
|
+
node.returns = action(node.returns) # type: ignore[reportAttributeAccessIssue]
|
|
499
499
|
return node
|
|
500
500
|
return workhorse
|
|
501
501
|
|
|
@@ -551,7 +551,7 @@ class Grab:
|
|
|
551
551
|
def targetAttribute(action: Callable[[ast.Name | ast.Attribute | ast.Subscript | ast.expr | ast.Name], ast.Name | ast.Attribute | ast.Subscript | ast.expr | ast.Name]) -> Callable[[hasDOTtarget], hasDOTtarget]:
|
|
552
552
|
|
|
553
553
|
def workhorse(node: hasDOTtarget) -> hasDOTtarget:
|
|
554
|
-
node.target = action(node.target)
|
|
554
|
+
node.target = action(node.target) # type: ignore[reportAttributeAccessIssue]
|
|
555
555
|
return node
|
|
556
556
|
return workhorse
|
|
557
557
|
|
|
@@ -615,7 +615,7 @@ class Grab:
|
|
|
615
615
|
def valueAttribute(action: Callable[[ast.expr | None | ast.expr | Any | (Literal[True, False] | None)], ast.expr | None | ast.expr | Any | (Literal[True, False] | None)]) -> Callable[[hasDOTvalue], hasDOTvalue]:
|
|
616
616
|
|
|
617
617
|
def workhorse(node: hasDOTvalue) -> hasDOTvalue:
|
|
618
|
-
node.value = action(node.value)
|
|
618
|
+
node.value = action(node.value) # type: ignore[reportAttributeAccessIssue]
|
|
619
619
|
return node
|
|
620
620
|
return workhorse
|
|
621
621
|
|
|
@@ -642,12 +642,4 @@ class Grab:
|
|
|
642
642
|
for action in listOfActions:
|
|
643
643
|
node = action(node)
|
|
644
644
|
return node
|
|
645
|
-
return workhorse
|
|
646
|
-
|
|
647
|
-
@staticmethod
|
|
648
|
-
def funcDOTidAttribute(action: Callable[[ast_Identifier], Any]) -> Callable[[ast.Call], ast.Call]:
|
|
649
|
-
|
|
650
|
-
def workhorse(node: ast.Call) -> ast.Call:
|
|
651
|
-
node.func = Grab.idAttribute(action)(node.func)
|
|
652
|
-
return node
|
|
653
645
|
return workhorse
|
|
@@ -21,7 +21,7 @@ they implement a declarative approach to AST manipulation that separates node id
|
|
|
21
21
|
|
|
22
22
|
from collections.abc import Callable
|
|
23
23
|
from astToolkit import ast_Identifier, Be, DOT
|
|
24
|
-
from typing import Any, TypeGuard
|
|
24
|
+
from typing import Any, TypeGuard, cast
|
|
25
25
|
import ast
|
|
26
26
|
|
|
27
27
|
class IfThis:
|
|
@@ -91,7 +91,7 @@ class IfThis:
|
|
|
91
91
|
@staticmethod
|
|
92
92
|
def isCall_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Call] | bool]:
|
|
93
93
|
def workhorse(node: ast.AST) -> TypeGuard[ast.Call] | bool:
|
|
94
|
-
return IfThis.isCallToName(node) and IfThis.isIdentifier(identifier)(DOT.id(DOT.func(node)))
|
|
94
|
+
return IfThis.isCallToName(node) and IfThis.isIdentifier(identifier)(DOT.id(cast(ast.Name, DOT.func(node))))
|
|
95
95
|
return workhorse
|
|
96
96
|
|
|
97
97
|
@staticmethod
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from autoflake import fix_code as autoflake_fix_code
|
|
2
|
-
from collections.abc import Mapping
|
|
2
|
+
from collections.abc import Callable, Mapping
|
|
3
3
|
from copy import deepcopy
|
|
4
4
|
from astToolkit import (
|
|
5
5
|
ast_Identifier,
|
|
@@ -19,7 +19,7 @@ from astToolkit import FREAKOUT
|
|
|
19
19
|
from Z0Z_tools import writeStringToHere
|
|
20
20
|
from os import PathLike
|
|
21
21
|
from pathlib import PurePath
|
|
22
|
-
from typing import Any
|
|
22
|
+
from typing import Any, cast
|
|
23
23
|
import ast
|
|
24
24
|
|
|
25
25
|
def makeDictionaryFunctionDef(module: ast.Module) -> dict[ast_Identifier, ast.FunctionDef]:
|
|
@@ -65,7 +65,7 @@ def inlineFunctionDef(identifierToInline: ast_Identifier, module: ast.Module) ->
|
|
|
65
65
|
raise ValueError(f"FunctionDefToInline not found in dictionaryIdentifier2FunctionDef: {identifierToInline = }") from ERRORmessage
|
|
66
66
|
|
|
67
67
|
listIdentifiersCalledFunctions: list[ast_Identifier] = []
|
|
68
|
-
findIdentifiersToInline = NodeTourist(findThis = IfThis.isCallToName, doThat = Grab.
|
|
68
|
+
findIdentifiersToInline = NodeTourist(findThis = IfThis.isCallToName, doThat = Grab.funcAttribute(cast(Callable[[ast.expr], ast.expr], Grab.idAttribute(cast(Callable[[ast_Identifier], ast_Identifier], Then.appendTo(listIdentifiersCalledFunctions))))))
|
|
69
69
|
findIdentifiersToInline.visit(FunctionDefToInline)
|
|
70
70
|
|
|
71
71
|
dictionary4Inlining: dict[ast_Identifier, ast.FunctionDef] = {}
|
|
@@ -32,7 +32,7 @@ optional-dependencies = { testing = [
|
|
|
32
32
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
33
33
|
requires-python = ">=3.10"
|
|
34
34
|
urls = { Donate = "https://www.patreon.com/integrated", Homepage = "https://github.com/hunterhogan/astToolkit", Issues = "https://github.com/hunterhogan/astToolkit/issues", Repository = "https://github.com/hunterhogan/astToolkit.git" }
|
|
35
|
-
version = "0.1.
|
|
35
|
+
version = "0.1.2"
|
|
36
36
|
|
|
37
37
|
[tool.coverage]
|
|
38
38
|
report = { exclude_lines = [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from pathlib import PurePosixPath
|
|
2
2
|
from string import ascii_letters
|
|
3
3
|
from toolFactory import ast_Identifier, fileExtension, list_astDOTnew, pathPackage, str_nameDOTname, sys_version_infoTarget
|
|
4
|
-
from toolFactory.astFactory_annex import handmadeMethodsGrab, handmadeTypeAlias_astTypes, MakeAttributeFunctionDef, MakeImportFunctionDef
|
|
4
|
+
from toolFactory.astFactory_annex import handmadeMethodsGrab, handmadeTypeAlias_astTypes, listPylanceErrors, MakeAttributeFunctionDef, MakeImportFunctionDef
|
|
5
5
|
from toolFactory.docstrings import docstringWarning, ClassDefDocstringBe, ClassDefDocstringDOT, ClassDefDocstringGrab, ClassDefDocstringMake
|
|
6
6
|
from typing import cast, TypedDict
|
|
7
7
|
from Z0Z_tools import writeStringToHere
|
|
@@ -74,6 +74,18 @@ def makeTools(astStubFile: ast.AST) -> None:
|
|
|
74
74
|
pythonSource: str = ast.unparse(astModule)
|
|
75
75
|
if 'Grab' in moduleIdentifier or 'DOT' in moduleIdentifier:
|
|
76
76
|
pythonSource = "# ruff: noqa: F403, F405\n" + pythonSource
|
|
77
|
+
if 'Grab' in moduleIdentifier:
|
|
78
|
+
listTypeIgnore: list[ast.TypeIgnore] = []
|
|
79
|
+
tag = '[reportAttributeAccessIssue]'
|
|
80
|
+
for attribute in listPylanceErrors:
|
|
81
|
+
for lineno, line in enumerate(pythonSource.splitlines()):
|
|
82
|
+
if 'node.'+attribute in line:
|
|
83
|
+
listTypeIgnore.append(ast.TypeIgnore(lineno+1, tag))
|
|
84
|
+
break
|
|
85
|
+
astModule = ast.parse(pythonSource)
|
|
86
|
+
astModule.type_ignores.extend(listTypeIgnore)
|
|
87
|
+
pythonSource: str = ast.unparse(astModule)
|
|
88
|
+
pythonSource = "# ruff: noqa: F403, F405\n" + pythonSource
|
|
77
89
|
pathFilenameModule = PurePosixPath(pathPackage, moduleIdentifier + fileExtension)
|
|
78
90
|
writeStringToHere(pythonSource, pathFilenameModule)
|
|
79
91
|
|
|
@@ -21,16 +21,8 @@ def andDoAllOf(listOfActions: list[Callable[[NodeORattribute], NodeORattribute]]
|
|
|
21
21
|
return workhorse
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
Grab_funcDOTidAttribute: str ="""@staticmethod
|
|
25
|
-
def funcDOTidAttribute(action: Callable[[ast_Identifier], Any]) -> Callable[[ast.Call], ast.Call]:
|
|
26
|
-
def workhorse(node: ast.Call) -> ast.Call:
|
|
27
|
-
node.func = Grab.idAttribute(action)(node.func)
|
|
28
|
-
return node
|
|
29
|
-
return workhorse
|
|
30
|
-
"""
|
|
31
|
-
|
|
32
24
|
handmadeMethodsGrab: list[ast.FunctionDef] = []
|
|
33
|
-
for string in [Grab_andDoAllOf
|
|
25
|
+
for string in [Grab_andDoAllOf]:
|
|
34
26
|
astModule = ast.parse(string)
|
|
35
27
|
for node in ast.iter_child_nodes(astModule):
|
|
36
28
|
if isinstance(node, ast.FunctionDef):
|
|
@@ -55,9 +47,16 @@ MakeAttributeFunctionDef: ast.FunctionDef = ast.FunctionDef(
|
|
|
55
47
|
|
|
56
48
|
MakeImportFunctionDef: ast.FunctionDef = ast.FunctionDef(name='Import', args=ast.arguments(args=[ast.arg(arg='moduleWithLogicalPath', annotation=ast.Name(id='str_nameDOTname', ctx=ast.Load())), ast.arg(arg='asName', annotation=ast.BinOp(left=ast.Name(id='ast_Identifier', ctx=ast.Load()), op=ast.BitOr(), right=ast.Constant(value=None)))], kwarg=ast.arg(arg='keywordArguments', annotation=ast.Name(id='int', ctx=ast.Load())), defaults=[ast.Constant(value=None)]), body=[ast.Return(value=ast.Call(func=ast.Attribute(value=ast.Name(id='ast', ctx=ast.Load()), attr='Import', ctx=ast.Load()), keywords=[ast.keyword(arg='names', value=ast.List(elts=[ast.Call(func=ast.Attribute(value=ast.Name(id='Make', ctx=ast.Load()), attr='alias', ctx=ast.Load()), args=[ast.Name(id='moduleWithLogicalPath', ctx=ast.Load()), ast.Name(id='asName', ctx=ast.Load())])], ctx=ast.Load())), ast.keyword(value=ast.Name(id='keywordArguments', ctx=ast.Load()))]))], decorator_list=[ast.Name(id='staticmethod', ctx=ast.Load())], returns=ast.Attribute(value=ast.Name(id='ast', ctx=ast.Load()), attr='Import', ctx=ast.Load()))
|
|
57
49
|
|
|
50
|
+
listPylanceErrors: list[str] = ['annotation', 'arg', 'args', 'body', 'keys', 'name', 'names', 'op', 'orelse', 'pattern', 'returns', 'target', 'value',]
|
|
51
|
+
|
|
58
52
|
# ww='''
|
|
59
|
-
#
|
|
53
|
+
# def argAttribute(action: Callable[[ast_Identifier | (ast_Identifier | None)], ast_Identifier | (ast_Identifier | None)]) -> Callable[[hasDOTarg], hasDOTarg]:
|
|
54
|
+
|
|
55
|
+
# def workhorse(node: hasDOTarg) -> hasDOTarg:
|
|
56
|
+
# node.arg = action(node.arg) # type: ignore[reportAttributeAccessIssue]
|
|
57
|
+
# return node
|
|
58
|
+
# return workhorse
|
|
60
59
|
# '''
|
|
61
60
|
|
|
62
|
-
# print(ast.dump(ast.parse(ww), indent=4))
|
|
61
|
+
# print(ast.dump(ast.parse(ww, type_comments=True), indent=4))
|
|
63
62
|
# from ast import *
|
|
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
|