pmemstat 2.3.20__tar.gz → 2.3.22__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pmemstat
3
- Version: 2.3.20
3
+ Version: 2.3.22
4
4
  Summary: Report Proportional Memory on Linux
5
5
  Project-URL: Homepage, https://github.com/joedefen/pmemstat
6
6
  Project-URL: Bug Tracker, https://github.com/joedefen/pmemstat/issues
@@ -16,10 +16,16 @@ Requires-Dist: importlib-metadata; python_version < '3.8'
16
16
  Requires-Dist: requests
17
17
  Description-Content-Type: text/markdown
18
18
 
19
- > **Quick Start**: from the CLI:
20
- > * `sudo python3 -m pip install pmemstat # to install`
21
- > * `pmemstat # to run`
22
- > * `? # within pmemstat, show help screen`
19
+ > **Quick Start**: from the CLI
20
+ > * **If `python3 -V` shows v3.11 or later, install using `pipx`**:
21
+ > * `python3 -m pip install --user pipx # if pipx not installed`
22
+ > * `python3 -m pipx ensurepath # if needed (restart terminal)`
23
+ > * `pipx upgrade pmemstat || pipx install pmemstat # to install/upgrade`
24
+ > * **Else for python3.10 and lesser versions, install using `pip`**:
25
+ > * `python3 -m pip install --user --upgrade pmemstat`
26
+ > * **To run**:
27
+ > * `pmemstat # to run`
28
+ > * Type "?" within pmemstat, show help screen.
23
29
 
24
30
 
25
31
  # pmemstat - Proportional Memory Status
@@ -30,11 +36,11 @@ Description-Content-Type: text/markdown
30
36
 
31
37
  Computing proportional memory avoids overstating memory use as many programs do (e.g., `top`). Specifically, proportional memory splits the cost of common memory to the processes sharing it (rather than counting common memory multiple times). And, it does not include uninstantiated virtual memory.
32
38
 
33
- Without `-o`, `pmemstat` show less details and is much faster and sometimes less accurate (e.g., it will not report classes of memory such as SysV shared memory which often are not present). With `-o` providing full detail, digging out the numbers is slower; thus, `pmemstat -o` may take a few seconds to start, but, in its loop mode, refreshes are relatively fast and efficient by avoiding recomputing unchanged numbers. When in it window mode, typing `o` toggles low/high detail.
39
+ Without `-o`, `pmemstat` shows less details and is much faster and sometimes less accurate (e.g., it will not report classes of memory such as SysV shared memory which are often are not present anyhow). With `-o` providing full detail, digging out the numbers is slower; thus, `pmemstat -o` may take a few seconds to start, but, in its loop mode, refreshes are relatively fast and efficient by avoiding recomputing unchanged numbers. When in its window mode, typing `o` toggles low/high detail.
34
40
 
35
- `pmemstat`'s grouping feature rolls up the resources of multiple processes of a feature (e.g., a browser) to make the total impact much more apparent.
41
+ `pmemstat`'s grouping feature rolls up the resources of multiple processes of a feature (e.g., a browser) to make the total memory/cpu impact much more apparent.
36
42
 
37
- Its looping features allow monitoring for changes in memory growth which may be "leaks". Its precision numbers and segregating memory by types makes identifying leaks faster and more certain.
43
+ Its looping features allow monitoring for changes in memory growth which may be "leaks". Segregating memory by types can make identifying leaks faster and more certain.
38
44
 
39
45
  **In version 2.0, `pmemstat` has many new features including**:
40
46
  * In its **window mode**, `pmemstat` updates the terminal in place (using "curses") rather than scrolling.
@@ -44,36 +50,12 @@ Its looping features allow monitoring for changes in memory growth which may be
44
50
 
45
51
  ## Installation Options
46
52
  Note that:
47
- * `pmemstat` needs to run as root to read the memory statistics for all processes
48
- (which is normally desired).
53
+ * `pmemstat` needs to run as root to read the memory statistics for all processes (which is normally desired).
49
54
  * By default, `pmemstat` reruns itself as with `sudo` (thus you need `sudo` privileges).
50
55
  * To defeat re-running with `sudo`, use the `--run-as-user` or `-U` option.
51
56
 
52
- Choose the best way to install:
53
- * **From PyPi as non-root**. You need `~/.local/bin` on your `$PATH`.
54
- ```
55
- python -m pip install --user pmemstat
56
- # to uninstall: python -m pip uninstall pmemstat
57
- ```
58
- * Or **from PyPi as root**. This makes `pememstat` available to all users
59
- with `/usr/local/bin` on `$PATH`. Note: `PIP_BREAK_SYSTEM_PACKAGES=1`
60
- may be required on some distros.
61
- ```
62
- PIP_BREAK_SYSTEM_PACKAGES=1 sudo python -m pip install pmemstat
63
- # to uninstall: sudo python -m pip uninstall pmemstat
64
- ```
65
- * Or **from GitHub, scripted install**. The included `deploy` script installs
66
- a single-file `pmemstat` to `/usr/bin/pmemstat`;
67
- `deploy` installs/reinstalls `stickytape`, too.
68
- These commands install/update `pmemstat` w/o leftovers (except `stickytape`):
69
- ```
70
- # NOTE: requires "git" to be installed beforehand
71
- cd /tmp; rm -rf pmemstat;
72
- git clone https://github.com/joedefen/pmemstat.git;
73
- ./pmemstat/deploy; rm -rf pmemstat
74
- # to uninstall run: sudo rm /usr/bin/pmemstat
75
- ```
76
- * Or **from GitHub, manual install**: If you clone `pmemstat` from GitHub, then you may run its `deploy` script OR run "`pip install .`" as root or not OR just directly run `pmemstat/main.py`.
57
+ See the Quick Start at the top for preferred install instructions using `pipx`. If not acceptable, see the "Alternative Installation Options" section below.
58
+
77
59
 
78
60
  ## Usage
79
61
  ```
@@ -123,7 +105,7 @@ Explanation of some options and arguments:
123
105
  * `pids` - the positional arguments may be pids (i.e., numbers) or the names of executables (as shown by `-gexe`)
124
106
 
125
107
 
126
- # Example Usage with Explanation of Output
108
+ ## Example Usage with Explanation of Output
127
109
  ```
128
110
  10:38:17 Tot=31.3G Avail=21.8G Oth=2.4G Tmp=326.7M Dirty=1.2M PIDs: 202/202
129
111
  cpu_pct pswap other data ptotal key/info (exe by mem)
@@ -148,11 +130,10 @@ Explanation of some options and arguments:
148
130
  In the default refreshed window loop, we see
149
131
  * a **leader line** with:
150
132
  * the current time
151
- * from `/proc/meminfo` in MemTotal (Tot), MemAvailable (Avail), Tmp (Shmem), and Dirty.
133
+ * from `/proc/meminfo` in MemTotal (Tot), MemAvailable (Avail), Tmp (Shmem+TmpFS), and Dirty.
152
134
  * 'Oth' is the unaccounted for memory belonging to the kernel, reserve,
153
- drivers, imprecision, etc.; `Oth=Tot-Avail-Tmp-ptotal`.
154
- * Features such as BTRFS, ZFS, zRAM, unattached SysV Shared Memory,
155
- etc., can cause 'Oth' to be significant.
135
+ drivers, imprecision, etc.; `Oth = Tot - Avail - Tmp - ptotal`.
136
+ * Features such as BTRFS, ZFS, zRAM, unattached SysV Shared Memory, etc., can cause 'Oth' to be significant.
156
137
  * Determining the contributors can be difficult, but start with `sudo slabtop -sc` and feature specific tools (e.g., `zpool list`).
157
138
  * how many PIDs are contributing to the report vs the total number of PIDs excluding kernel threads
158
139
  * a **header line with the reported fields** including:
@@ -201,14 +182,14 @@ Sometimes, the horizontal line between the header and scrollable region has a re
201
182
  * Its length indicates, roughly, how much of the entire document you can see.
202
183
  * Again, you can press 'f' to fit the document to the screen with a "rollup" line summarizing the lines that would not fit.
203
184
 
204
- # Quirks and Details
185
+ ## Quirks and Details
205
186
  * **pswap** seems to be only provided by the `smaps_rollups` file, and thus it may be slightly out of sync with the data gathered by `smaps`.
206
187
  * the **ptotal** (from 'smaps') and **pss** (from `smaps_rollups` and usually hidden) seem differ more than expected but still close.
207
188
  * after the first loop, **pss** is read and only groups with sufficient aggregate change are probed for the details. Thus, subsequent loops are more efficient by avoiding the reading of `smaps` in many cases (with some loss of accuracy).
208
189
  * the "exe" value comes from the command line (based `/proc/{PID}/cmdline` which is a bit funky). Firstly, the leading path is stripped; secondly, if the resulting executable is a script interpreter (e.g., python, perl, bash, ...) AND the first argument seems to be a full path (i.e., starts with "/"), then the "exe" will be represented as "{interpreter}->{basename(script)}". For example, "python3->pmemstat.py" in the example above.
209
190
 
210
191
 
211
- # Test Program and Test Suggestions
192
+ ## Test Program and Test Suggestions
212
193
  The C program, `memtest.c` is included and can be compiled by running `cc memtest.c -o memtest`. This program:
213
194
  * regularly allocates more memory of all types
214
195
  * can be run several times simultaneously,
@@ -217,3 +198,30 @@ The C program, `memtest.c` is included and can be compiled by running `cc memtes
217
198
  When running `pmemstat` to monitor its memory use and changes, you should use `-uKB` and `-k{small-number}` so that you can "see" the very modest memory use of the test program and its changes.
218
199
 
219
200
  Running a number of sleeps of various durations in the background in a loop, plus one foreground sleep, can make for a robustness tests with lots of processes coming and going. There are many "races" (i.e., a process may appear in `/proc`, but its`smaps` is gone), and this test helps ensure the races are handled properly.
201
+
202
+ ## Alternative Installation Options
203
+ If the `pipx` install is not acceptable, choose the best way to install:
204
+ * **From PyPi as non-root**. You need `~/.local/bin` on your `$PATH`.
205
+ ```
206
+ python -m pip install --user pmemstat
207
+ # to uninstall: python -m pip uninstall pmemstat
208
+ ```
209
+ * Or **from PyPi as root**. This makes `pememstat` available to all users
210
+ with `/usr/local/bin` on `$PATH`. Note: `PIP_BREAK_SYSTEM_PACKAGES=1`
211
+ may be required on some distros.
212
+ ```
213
+ PIP_BREAK_SYSTEM_PACKAGES=1 sudo python -m pip install pmemstat
214
+ # to uninstall: sudo python -m pip uninstall pmemstat
215
+ ```
216
+ * Or **from GitHub, scripted install**. The included `deploy` script installs
217
+ a single-file `pmemstat` to `/usr/bin/pmemstat`;
218
+ `deploy` installs/reinstalls `stickytape`, too.
219
+ These commands install/update `pmemstat` w/o leftovers (except `stickytape`):
220
+ ```
221
+ # NOTE: requires "git" to be installed beforehand
222
+ cd /tmp; rm -rf pmemstat;
223
+ git clone https://github.com/joedefen/pmemstat.git;
224
+ ./pmemstat/deploy; rm -rf pmemstat
225
+ # to uninstall run: sudo rm /usr/bin/pmemstat
226
+ ```
227
+ * Or **from GitHub, manual install**: If you clone `pmemstat` from GitHub, then you may run its `deploy` script OR run "`pip install .`" as root or not OR just directly run `pmemstat/main.py`.
@@ -1,7 +1,13 @@
1
- > **Quick Start**: from the CLI:
2
- > * `sudo python3 -m pip install pmemstat # to install`
3
- > * `pmemstat # to run`
4
- > * `? # within pmemstat, show help screen`
1
+ > **Quick Start**: from the CLI
2
+ > * **If `python3 -V` shows v3.11 or later, install using `pipx`**:
3
+ > * `python3 -m pip install --user pipx # if pipx not installed`
4
+ > * `python3 -m pipx ensurepath # if needed (restart terminal)`
5
+ > * `pipx upgrade pmemstat || pipx install pmemstat # to install/upgrade`
6
+ > * **Else for python3.10 and lesser versions, install using `pip`**:
7
+ > * `python3 -m pip install --user --upgrade pmemstat`
8
+ > * **To run**:
9
+ > * `pmemstat # to run`
10
+ > * Type "?" within pmemstat, show help screen.
5
11
 
6
12
 
7
13
  # pmemstat - Proportional Memory Status
@@ -12,11 +18,11 @@
12
18
 
13
19
  Computing proportional memory avoids overstating memory use as many programs do (e.g., `top`). Specifically, proportional memory splits the cost of common memory to the processes sharing it (rather than counting common memory multiple times). And, it does not include uninstantiated virtual memory.
14
20
 
15
- Without `-o`, `pmemstat` show less details and is much faster and sometimes less accurate (e.g., it will not report classes of memory such as SysV shared memory which often are not present). With `-o` providing full detail, digging out the numbers is slower; thus, `pmemstat -o` may take a few seconds to start, but, in its loop mode, refreshes are relatively fast and efficient by avoiding recomputing unchanged numbers. When in it window mode, typing `o` toggles low/high detail.
21
+ Without `-o`, `pmemstat` shows less details and is much faster and sometimes less accurate (e.g., it will not report classes of memory such as SysV shared memory which are often are not present anyhow). With `-o` providing full detail, digging out the numbers is slower; thus, `pmemstat -o` may take a few seconds to start, but, in its loop mode, refreshes are relatively fast and efficient by avoiding recomputing unchanged numbers. When in its window mode, typing `o` toggles low/high detail.
16
22
 
17
- `pmemstat`'s grouping feature rolls up the resources of multiple processes of a feature (e.g., a browser) to make the total impact much more apparent.
23
+ `pmemstat`'s grouping feature rolls up the resources of multiple processes of a feature (e.g., a browser) to make the total memory/cpu impact much more apparent.
18
24
 
19
- Its looping features allow monitoring for changes in memory growth which may be "leaks". Its precision numbers and segregating memory by types makes identifying leaks faster and more certain.
25
+ Its looping features allow monitoring for changes in memory growth which may be "leaks". Segregating memory by types can make identifying leaks faster and more certain.
20
26
 
21
27
  **In version 2.0, `pmemstat` has many new features including**:
22
28
  * In its **window mode**, `pmemstat` updates the terminal in place (using "curses") rather than scrolling.
@@ -26,36 +32,12 @@ Its looping features allow monitoring for changes in memory growth which may be
26
32
 
27
33
  ## Installation Options
28
34
  Note that:
29
- * `pmemstat` needs to run as root to read the memory statistics for all processes
30
- (which is normally desired).
35
+ * `pmemstat` needs to run as root to read the memory statistics for all processes (which is normally desired).
31
36
  * By default, `pmemstat` reruns itself as with `sudo` (thus you need `sudo` privileges).
32
37
  * To defeat re-running with `sudo`, use the `--run-as-user` or `-U` option.
33
38
 
34
- Choose the best way to install:
35
- * **From PyPi as non-root**. You need `~/.local/bin` on your `$PATH`.
36
- ```
37
- python -m pip install --user pmemstat
38
- # to uninstall: python -m pip uninstall pmemstat
39
- ```
40
- * Or **from PyPi as root**. This makes `pememstat` available to all users
41
- with `/usr/local/bin` on `$PATH`. Note: `PIP_BREAK_SYSTEM_PACKAGES=1`
42
- may be required on some distros.
43
- ```
44
- PIP_BREAK_SYSTEM_PACKAGES=1 sudo python -m pip install pmemstat
45
- # to uninstall: sudo python -m pip uninstall pmemstat
46
- ```
47
- * Or **from GitHub, scripted install**. The included `deploy` script installs
48
- a single-file `pmemstat` to `/usr/bin/pmemstat`;
49
- `deploy` installs/reinstalls `stickytape`, too.
50
- These commands install/update `pmemstat` w/o leftovers (except `stickytape`):
51
- ```
52
- # NOTE: requires "git" to be installed beforehand
53
- cd /tmp; rm -rf pmemstat;
54
- git clone https://github.com/joedefen/pmemstat.git;
55
- ./pmemstat/deploy; rm -rf pmemstat
56
- # to uninstall run: sudo rm /usr/bin/pmemstat
57
- ```
58
- * Or **from GitHub, manual install**: If you clone `pmemstat` from GitHub, then you may run its `deploy` script OR run "`pip install .`" as root or not OR just directly run `pmemstat/main.py`.
39
+ See the Quick Start at the top for preferred install instructions using `pipx`. If not acceptable, see the "Alternative Installation Options" section below.
40
+
59
41
 
60
42
  ## Usage
61
43
  ```
@@ -105,7 +87,7 @@ Explanation of some options and arguments:
105
87
  * `pids` - the positional arguments may be pids (i.e., numbers) or the names of executables (as shown by `-gexe`)
106
88
 
107
89
 
108
- # Example Usage with Explanation of Output
90
+ ## Example Usage with Explanation of Output
109
91
  ```
110
92
  10:38:17 Tot=31.3G Avail=21.8G Oth=2.4G Tmp=326.7M Dirty=1.2M PIDs: 202/202
111
93
  cpu_pct pswap other data ptotal key/info (exe by mem)
@@ -130,11 +112,10 @@ Explanation of some options and arguments:
130
112
  In the default refreshed window loop, we see
131
113
  * a **leader line** with:
132
114
  * the current time
133
- * from `/proc/meminfo` in MemTotal (Tot), MemAvailable (Avail), Tmp (Shmem), and Dirty.
115
+ * from `/proc/meminfo` in MemTotal (Tot), MemAvailable (Avail), Tmp (Shmem+TmpFS), and Dirty.
134
116
  * 'Oth' is the unaccounted for memory belonging to the kernel, reserve,
135
- drivers, imprecision, etc.; `Oth=Tot-Avail-Tmp-ptotal`.
136
- * Features such as BTRFS, ZFS, zRAM, unattached SysV Shared Memory,
137
- etc., can cause 'Oth' to be significant.
117
+ drivers, imprecision, etc.; `Oth = Tot - Avail - Tmp - ptotal`.
118
+ * Features such as BTRFS, ZFS, zRAM, unattached SysV Shared Memory, etc., can cause 'Oth' to be significant.
138
119
  * Determining the contributors can be difficult, but start with `sudo slabtop -sc` and feature specific tools (e.g., `zpool list`).
139
120
  * how many PIDs are contributing to the report vs the total number of PIDs excluding kernel threads
140
121
  * a **header line with the reported fields** including:
@@ -183,14 +164,14 @@ Sometimes, the horizontal line between the header and scrollable region has a re
183
164
  * Its length indicates, roughly, how much of the entire document you can see.
184
165
  * Again, you can press 'f' to fit the document to the screen with a "rollup" line summarizing the lines that would not fit.
185
166
 
186
- # Quirks and Details
167
+ ## Quirks and Details
187
168
  * **pswap** seems to be only provided by the `smaps_rollups` file, and thus it may be slightly out of sync with the data gathered by `smaps`.
188
169
  * the **ptotal** (from 'smaps') and **pss** (from `smaps_rollups` and usually hidden) seem differ more than expected but still close.
189
170
  * after the first loop, **pss** is read and only groups with sufficient aggregate change are probed for the details. Thus, subsequent loops are more efficient by avoiding the reading of `smaps` in many cases (with some loss of accuracy).
190
171
  * the "exe" value comes from the command line (based `/proc/{PID}/cmdline` which is a bit funky). Firstly, the leading path is stripped; secondly, if the resulting executable is a script interpreter (e.g., python, perl, bash, ...) AND the first argument seems to be a full path (i.e., starts with "/"), then the "exe" will be represented as "{interpreter}->{basename(script)}". For example, "python3->pmemstat.py" in the example above.
191
172
 
192
173
 
193
- # Test Program and Test Suggestions
174
+ ## Test Program and Test Suggestions
194
175
  The C program, `memtest.c` is included and can be compiled by running `cc memtest.c -o memtest`. This program:
195
176
  * regularly allocates more memory of all types
196
177
  * can be run several times simultaneously,
@@ -199,3 +180,30 @@ The C program, `memtest.c` is included and can be compiled by running `cc memtes
199
180
  When running `pmemstat` to monitor its memory use and changes, you should use `-uKB` and `-k{small-number}` so that you can "see" the very modest memory use of the test program and its changes.
200
181
 
201
182
  Running a number of sleeps of various durations in the background in a loop, plus one foreground sleep, can make for a robustness tests with lots of processes coming and going. There are many "races" (i.e., a process may appear in `/proc`, but its`smaps` is gone), and this test helps ensure the races are handled properly.
183
+
184
+ ## Alternative Installation Options
185
+ If the `pipx` install is not acceptable, choose the best way to install:
186
+ * **From PyPi as non-root**. You need `~/.local/bin` on your `$PATH`.
187
+ ```
188
+ python -m pip install --user pmemstat
189
+ # to uninstall: python -m pip uninstall pmemstat
190
+ ```
191
+ * Or **from PyPi as root**. This makes `pememstat` available to all users
192
+ with `/usr/local/bin` on `$PATH`. Note: `PIP_BREAK_SYSTEM_PACKAGES=1`
193
+ may be required on some distros.
194
+ ```
195
+ PIP_BREAK_SYSTEM_PACKAGES=1 sudo python -m pip install pmemstat
196
+ # to uninstall: sudo python -m pip uninstall pmemstat
197
+ ```
198
+ * Or **from GitHub, scripted install**. The included `deploy` script installs
199
+ a single-file `pmemstat` to `/usr/bin/pmemstat`;
200
+ `deploy` installs/reinstalls `stickytape`, too.
201
+ These commands install/update `pmemstat` w/o leftovers (except `stickytape`):
202
+ ```
203
+ # NOTE: requires "git" to be installed beforehand
204
+ cd /tmp; rm -rf pmemstat;
205
+ git clone https://github.com/joedefen/pmemstat.git;
206
+ ./pmemstat/deploy; rm -rf pmemstat
207
+ # to uninstall run: sudo rm /usr/bin/pmemstat
208
+ ```
209
+ * Or **from GitHub, manual install**: If you clone `pmemstat` from GitHub, then you may run its `deploy` script OR run "`pip install .`" as root or not OR just directly run `pmemstat/main.py`.
@@ -1,32 +1,36 @@
1
1
  # HOW TO PUBLISH...
2
2
  #
3
3
  # Prep Work (ensure need modules are up-to-date):
4
- # python3 -m pip install --upgrade pip
5
- # python3 -m pip install --upgrade build
6
- # python3 -m pip install --upgrade twine
7
- #
8
- # Build and test (from project directory):
9
- # ## BUMP the version (below in [project])
10
- # rm -r dist; python3 -m build
11
- # python3 -m twine upload --repository testpypi dist/*
12
- # ## Enter __token__ and the saved TOKEN (in bitwarden)
13
- # sudo python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps pmemstat
14
- # ## VISIT https://test.pypi.org/project/pmemstat and delete old versions
4
+ # sudo pacman -Syu python-pip
5
+ # sudo pacman -Syu python-build
6
+ # sudo pacman -Syu python-twine
7
+ # -- antiquated way
8
+ # python3 -m pip install --upgrade pip
9
+ # python3 -m pip install --upgrade build
10
+ # python3 -m pip install --upgrade twine
15
11
  #
16
- # Build and deploy (from project directory):
12
+ # PUBLIC Build and deploy (from project directory):
17
13
  # ## BUMP the version (below in [project])
18
14
  # rm -r dist; python3 -m build; ls dist/.
19
15
  # python3 -m twine upload dist/*
20
16
  # ## Enter __token__ and the saved TOKEN (in bitwarden)
21
17
  # sudo python3 -m pip install pmemstat
22
18
  # ## VISIT https://pypi.org/project/pmemstat and delete old versions
19
+ #
20
+ # TEST Build and test (from project directory):
21
+ # ## BUMP the version (below in [project])
22
+ # rm -r dist; python3 -m build
23
+ # python3 -m twine upload --repository testpypi dist/*
24
+ # ## Enter __token__ and the saved TOKEN (in bitwarden)
25
+ # sudo python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps pmemstat
26
+ # ## VISIT https://test.pypi.org/project/pmemstat and delete old versions
23
27
 
24
28
  [build-system]
25
29
  requires = ["hatchling"]
26
30
  build-backend = "hatchling.build"
27
31
 
28
32
  [project]
29
- version = "2.3.20"
33
+ version = "2.3.22"
30
34
  name = "pmemstat"
31
35
  authors = [
32
36
  {name = "Joe Defen", email = "joedef@gmail.com"},
File without changes
File without changes
File without changes
File without changes
File without changes