qsu 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.
- qsu-0.1.0/.gitignore +13 -0
- qsu-0.1.0/LICENSE +21 -0
- qsu-0.1.0/PKG-INFO +77 -0
- qsu-0.1.0/README.md +26 -0
- qsu-0.1.0/pyproject.toml +56 -0
- qsu-0.1.0/qsu/__init__.py +56 -0
- qsu-0.1.0/qsu/array/__init__.py +29 -0
- qsu-0.1.0/qsu/array/arrCount.py +8 -0
- qsu-0.1.0/qsu/array/arrGroupByMaxCount.py +15 -0
- qsu-0.1.0/qsu/array/arrMove.py +9 -0
- qsu-0.1.0/qsu/array/arrPick.py +8 -0
- qsu-0.1.0/qsu/array/arrRepeat.py +17 -0
- qsu-0.1.0/qsu/array/arrShuffle.py +15 -0
- qsu-0.1.0/qsu/array/arrTo1dArray.py +18 -0
- qsu-0.1.0/qsu/array/arrUnique.py +28 -0
- qsu-0.1.0/qsu/array/arrWithDefault.py +5 -0
- qsu-0.1.0/qsu/array/arrWithNumber.py +5 -0
- qsu-0.1.0/qsu/array/average.py +2 -0
- qsu-0.1.0/qsu/array/sortByObjectKey.py +20 -0
- qsu-0.1.0/qsu/array/sortNumeric.py +16 -0
- qsu-0.1.0/qsu/crypto/__init__.py +23 -0
- qsu-0.1.0/qsu/crypto/decodeBase64.py +5 -0
- qsu-0.1.0/qsu/crypto/decrypt.py +34 -0
- qsu-0.1.0/qsu/crypto/encodeBase64.py +5 -0
- qsu-0.1.0/qsu/crypto/encrypt.py +35 -0
- qsu-0.1.0/qsu/crypto/md5Hash.py +19 -0
- qsu-0.1.0/qsu/crypto/numberHash.py +14 -0
- qsu-0.1.0/qsu/crypto/objectId.py +9 -0
- qsu-0.1.0/qsu/crypto/sha1Hash.py +19 -0
- qsu-0.1.0/qsu/crypto/sha256Hash.py +19 -0
- qsu-0.1.0/qsu/crypto/sha512Hash.py +19 -0
- qsu-0.1.0/qsu/date/__init__.py +13 -0
- qsu-0.1.0/qsu/date/createDateListFromRange.py +55 -0
- qsu-0.1.0/qsu/date/dateToYYYYMMDD.py +20 -0
- qsu-0.1.0/qsu/date/dayDiff.py +10 -0
- qsu-0.1.0/qsu/date/isValidDate.py +27 -0
- qsu-0.1.0/qsu/date/today.py +19 -0
- qsu-0.1.0/qsu/file/__init__.py +51 -0
- qsu-0.1.0/qsu/file/_readLines.py +17 -0
- qsu-0.1.0/qsu/file/createDirectory.py +13 -0
- qsu-0.1.0/qsu/file/createFile.py +17 -0
- qsu-0.1.0/qsu/file/createFileWithDummy.py +21 -0
- qsu-0.1.0/qsu/file/deleteAllFileFromDirectory.py +15 -0
- qsu-0.1.0/qsu/file/deleteFile.py +16 -0
- qsu-0.1.0/qsu/file/getCopyFileName.py +21 -0
- qsu-0.1.0/qsu/file/getFileExtension.py +8 -0
- qsu-0.1.0/qsu/file/getFileHashFromPath.py +14 -0
- qsu-0.1.0/qsu/file/getFileHashFromStream.py +21 -0
- qsu-0.1.0/qsu/file/getFileInfo.py +42 -0
- qsu-0.1.0/qsu/file/getFileName.py +26 -0
- qsu-0.1.0/qsu/file/getFilePathLevel.py +12 -0
- qsu-0.1.0/qsu/file/getFileSize.py +10 -0
- qsu-0.1.0/qsu/file/getParentFilePath.py +10 -0
- qsu-0.1.0/qsu/file/headFile.py +19 -0
- qsu-0.1.0/qsu/file/isFileExists.py +9 -0
- qsu-0.1.0/qsu/file/isFileHidden.py +27 -0
- qsu-0.1.0/qsu/file/isValidFileName.py +14 -0
- qsu-0.1.0/qsu/file/joinFilePath.py +41 -0
- qsu-0.1.0/qsu/file/moveFile.py +8 -0
- qsu-0.1.0/qsu/file/normalizeFile.py +13 -0
- qsu-0.1.0/qsu/file/tailFile.py +24 -0
- qsu-0.1.0/qsu/file/toPosixFilePath.py +9 -0
- qsu-0.1.0/qsu/file/toValidFilePath.py +33 -0
- qsu-0.1.0/qsu/format/__init__.py +13 -0
- qsu-0.1.0/qsu/format/duration.py +45 -0
- qsu-0.1.0/qsu/format/fileSizeFormat.py +30 -0
- qsu-0.1.0/qsu/format/numberFormat.py +23 -0
- qsu-0.1.0/qsu/format/safeJSONParse.py +21 -0
- qsu-0.1.0/qsu/format/safeParseInt.py +39 -0
- qsu-0.1.0/qsu/math/__init__.py +15 -0
- qsu-0.1.0/qsu/math/div.py +9 -0
- qsu-0.1.0/qsu/math/mul.py +9 -0
- qsu-0.1.0/qsu/math/numPick.py +13 -0
- qsu-0.1.0/qsu/math/numUnique.py +10 -0
- qsu-0.1.0/qsu/math/sub.py +9 -0
- qsu-0.1.0/qsu/math/sum.py +9 -0
- qsu-0.1.0/qsu/misc/__init__.py +11 -0
- qsu-0.1.0/qsu/misc/debounce.py +14 -0
- qsu-0.1.0/qsu/misc/funcTimes.py +10 -0
- qsu-0.1.0/qsu/misc/logBox.py +174 -0
- qsu-0.1.0/qsu/misc/sleep.py +7 -0
- qsu-0.1.0/qsu/net/__init__.py +5 -0
- qsu-0.1.0/qsu/net/fetchData.py +186 -0
- qsu-0.1.0/qsu/object/__init__.py +19 -0
- qsu-0.1.0/qsu/object/objDeleteKeyByValue.py +29 -0
- qsu-0.1.0/qsu/object/objFindItemRecursiveByKey.py +25 -0
- qsu-0.1.0/qsu/object/objMergeNewKey.py +36 -0
- qsu-0.1.0/qsu/object/objTo1d.py +25 -0
- qsu-0.1.0/qsu/object/objToArray.py +16 -0
- qsu-0.1.0/qsu/object/objToPrettyStr.py +5 -0
- qsu-0.1.0/qsu/object/objToQueryString.py +27 -0
- qsu-0.1.0/qsu/object/objUpdate.py +25 -0
- qsu-0.1.0/qsu/os/__init__.py +17 -0
- qsu-0.1.0/qsu/os/getCpu.py +7 -0
- qsu-0.1.0/qsu/os/getHostname.py +28 -0
- qsu-0.1.0/qsu/os/getMachineId.py +33 -0
- qsu-0.1.0/qsu/os/getRamSize.py +34 -0
- qsu-0.1.0/qsu/os/getSid.py +60 -0
- qsu-0.1.0/qsu/os/getUptime.py +19 -0
- qsu-0.1.0/qsu/os/runCommand.py +28 -0
- qsu-0.1.0/qsu/string/__init__.py +41 -0
- qsu-0.1.0/qsu/string/capitalizeEachWords.py +43 -0
- qsu-0.1.0/qsu/string/capitalizeEverySentence.py +23 -0
- qsu-0.1.0/qsu/string/capitalizeFirst.py +5 -0
- qsu-0.1.0/qsu/string/getGroupKeys.py +103 -0
- qsu-0.1.0/qsu/string/getStrBytes.py +5 -0
- qsu-0.1.0/qsu/string/removeNewLine.py +8 -0
- qsu-0.1.0/qsu/string/removeSpecialChar.py +16 -0
- qsu-0.1.0/qsu/string/replaceBetween.py +15 -0
- qsu-0.1.0/qsu/string/split.py +45 -0
- qsu-0.1.0/qsu/string/strBlindRandom.py +26 -0
- qsu-0.1.0/qsu/string/strCount.py +12 -0
- qsu-0.1.0/qsu/string/strRandom.py +14 -0
- qsu-0.1.0/qsu/string/strShuffle.py +11 -0
- qsu-0.1.0/qsu/string/strToAscii.py +7 -0
- qsu-0.1.0/qsu/string/strUnique.py +5 -0
- qsu-0.1.0/qsu/string/trim.py +8 -0
- qsu-0.1.0/qsu/string/truncate.py +10 -0
- qsu-0.1.0/qsu/string/truncateExpect.py +25 -0
- qsu-0.1.0/qsu/string/urlJoin.py +27 -0
- qsu-0.1.0/qsu/verify/__init__.py +25 -0
- qsu-0.1.0/qsu/verify/between.py +7 -0
- qsu-0.1.0/qsu/verify/contains.py +12 -0
- qsu-0.1.0/qsu/verify/is2dArray.py +2 -0
- qsu-0.1.0/qsu/verify/isEmail.py +15 -0
- qsu-0.1.0/qsu/verify/isEmpty.py +12 -0
- qsu-0.1.0/qsu/verify/isEqual.py +32 -0
- qsu-0.1.0/qsu/verify/isEqualStrict.py +21 -0
- qsu-0.1.0/qsu/verify/isObject.py +2 -0
- qsu-0.1.0/qsu/verify/isTrueMinimumNumberOfTimes.py +8 -0
- qsu-0.1.0/qsu/verify/isUrl.py +20 -0
- qsu-0.1.0/qsu/verify/len.py +21 -0
- qsu-0.1.0/qsu/web/__init__.py +13 -0
- qsu-0.1.0/qsu/web/generateLicense.py +48 -0
- qsu-0.1.0/qsu/web/isBotAgent.py +10 -0
- qsu-0.1.0/qsu/web/isMatchPathname.py +24 -0
- qsu-0.1.0/qsu/web/isMobile.py +17 -0
- qsu-0.1.0/qsu/web/removeLocalePrefix.py +40 -0
qsu-0.1.0/.gitignore
ADDED
qsu-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021-2026 CDGet <jooy2.contact@gmail.com> (https://cdget.com).
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE
|
qsu-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qsu
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: qsu is a utility library that contains useful and frequently used functions. Start with your preferred language and the modern development environment.
|
|
5
|
+
Project-URL: Homepage, https://qsu.cdget.com
|
|
6
|
+
Project-URL: Repository, https://github.com/jooy2/qsu
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/jooy2/qsu/issues
|
|
8
|
+
Project-URL: Changelog, https://qsu.cdget.com/changelog/python
|
|
9
|
+
Author-email: CDGet <jooy2.contact@gmail.com>
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2021-2026 CDGet <jooy2.contact@gmail.com> (https://cdget.com).
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Keywords: array,date,format,helper,math,string,tool,toolkit,util,utility,verify
|
|
33
|
+
Classifier: Development Status :: 3 - Alpha
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Operating System :: OS Independent
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
44
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
45
|
+
Classifier: Topic :: Utilities
|
|
46
|
+
Requires-Python: >=3.8
|
|
47
|
+
Requires-Dist: cryptography>=42.0
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
50
|
+
Description-Content-Type: text/markdown
|
|
51
|
+
|
|
52
|
+
# qsu - Quick & Simple Utility (Python)
|
|
53
|
+
|
|
54
|
+
**qsu** is a library that collects frequently used utility functions.
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
**qsu** requires `Python 3.8` or later.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
$ pip install qsu
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## How to use
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from qsu import capitalizeFirst, strCount
|
|
68
|
+
|
|
69
|
+
print(capitalizeFirst('abcd')) # 'Abcd'
|
|
70
|
+
print(strCount('123412341234', '1')) # 3
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
For more information on all supported functions, see the [Reference](https://qsu.cdget.com/reference) documentation.
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
Please see the [LICENSE](LICENSE) file for more information.
|
qsu-0.1.0/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# qsu - Quick & Simple Utility (Python)
|
|
2
|
+
|
|
3
|
+
**qsu** is a library that collects frequently used utility functions.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
**qsu** requires `Python 3.8` or later.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
$ pip install qsu
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## How to use
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from qsu import capitalizeFirst, strCount
|
|
17
|
+
|
|
18
|
+
print(capitalizeFirst('abcd')) # 'Abcd'
|
|
19
|
+
print(strCount('123412341234', '1')) # 3
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
For more information on all supported functions, see the [Reference](https://qsu.cdget.com/reference) documentation.
|
|
23
|
+
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
Please see the [LICENSE](LICENSE) file for more information.
|
qsu-0.1.0/pyproject.toml
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "qsu"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "qsu is a utility library that contains useful and frequently used functions. Start with your preferred language and the modern development environment."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { file = "LICENSE" }
|
|
11
|
+
authors = [{ name = "CDGet", email = "jooy2.contact@gmail.com" }]
|
|
12
|
+
requires-python = ">=3.8"
|
|
13
|
+
dependencies = ["cryptography>=42.0"]
|
|
14
|
+
keywords = [
|
|
15
|
+
"util",
|
|
16
|
+
"utility",
|
|
17
|
+
"tool",
|
|
18
|
+
"toolkit",
|
|
19
|
+
"helper",
|
|
20
|
+
"array",
|
|
21
|
+
"string",
|
|
22
|
+
"date",
|
|
23
|
+
"math",
|
|
24
|
+
"verify",
|
|
25
|
+
"format",
|
|
26
|
+
]
|
|
27
|
+
classifiers = [
|
|
28
|
+
"Development Status :: 3 - Alpha",
|
|
29
|
+
"Intended Audience :: Developers",
|
|
30
|
+
"License :: OSI Approved :: MIT License",
|
|
31
|
+
"Operating System :: OS Independent",
|
|
32
|
+
"Programming Language :: Python :: 3",
|
|
33
|
+
"Programming Language :: Python :: 3.8",
|
|
34
|
+
"Programming Language :: Python :: 3.9",
|
|
35
|
+
"Programming Language :: Python :: 3.10",
|
|
36
|
+
"Programming Language :: Python :: 3.11",
|
|
37
|
+
"Programming Language :: Python :: 3.12",
|
|
38
|
+
"Programming Language :: Python :: 3.13",
|
|
39
|
+
"Topic :: Software Development :: Libraries",
|
|
40
|
+
"Topic :: Utilities",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://qsu.cdget.com"
|
|
45
|
+
Repository = "https://github.com/jooy2/qsu"
|
|
46
|
+
"Bug Tracker" = "https://github.com/jooy2/qsu/issues"
|
|
47
|
+
Changelog = "https://qsu.cdget.com/changelog/python"
|
|
48
|
+
|
|
49
|
+
[project.optional-dependencies]
|
|
50
|
+
dev = ["pytest>=8.0"]
|
|
51
|
+
|
|
52
|
+
[tool.hatch.build.targets.wheel]
|
|
53
|
+
packages = ["qsu"]
|
|
54
|
+
|
|
55
|
+
[tool.hatch.build.targets.sdist]
|
|
56
|
+
include = ["qsu", "README.md", "LICENSE"]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""qsu - Quick & Simple Utility.
|
|
2
|
+
|
|
3
|
+
A utility library that collects frequently used functions.
|
|
4
|
+
This package mirrors the JavaScript implementation of qsu.
|
|
5
|
+
|
|
6
|
+
Unlike the JavaScript package (where filesystem/OS/network/crypto helpers live
|
|
7
|
+
under `qsu/node`), Python has no browser/runtime split, so every function is
|
|
8
|
+
importable directly from the top-level `qsu` package.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from . import (
|
|
12
|
+
array,
|
|
13
|
+
crypto,
|
|
14
|
+
date,
|
|
15
|
+
file,
|
|
16
|
+
format,
|
|
17
|
+
math,
|
|
18
|
+
misc,
|
|
19
|
+
net,
|
|
20
|
+
object,
|
|
21
|
+
os,
|
|
22
|
+
string,
|
|
23
|
+
verify,
|
|
24
|
+
web,
|
|
25
|
+
)
|
|
26
|
+
from .array import * # noqa: F401,F403
|
|
27
|
+
from .crypto import * # noqa: F401,F403
|
|
28
|
+
from .date import * # noqa: F401,F403
|
|
29
|
+
from .file import * # noqa: F401,F403
|
|
30
|
+
from .format import * # noqa: F401,F403
|
|
31
|
+
from .math import * # noqa: F401,F403
|
|
32
|
+
from .misc import * # noqa: F401,F403
|
|
33
|
+
from .net import * # noqa: F401,F403
|
|
34
|
+
from .object import * # noqa: F401,F403
|
|
35
|
+
from .os import * # noqa: F401,F403
|
|
36
|
+
from .string import * # noqa: F401,F403
|
|
37
|
+
from .verify import * # noqa: F401,F403
|
|
38
|
+
from .web import * # noqa: F401,F403
|
|
39
|
+
|
|
40
|
+
__version__ = '0.1.0'
|
|
41
|
+
|
|
42
|
+
__all__ = [
|
|
43
|
+
*array.__all__,
|
|
44
|
+
*crypto.__all__,
|
|
45
|
+
*date.__all__,
|
|
46
|
+
*file.__all__,
|
|
47
|
+
*format.__all__,
|
|
48
|
+
*math.__all__,
|
|
49
|
+
*misc.__all__,
|
|
50
|
+
*net.__all__,
|
|
51
|
+
*object.__all__,
|
|
52
|
+
*os.__all__,
|
|
53
|
+
*string.__all__,
|
|
54
|
+
*verify.__all__,
|
|
55
|
+
*web.__all__,
|
|
56
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from .arrCount import arrCount
|
|
2
|
+
from .arrGroupByMaxCount import arrGroupByMaxCount
|
|
3
|
+
from .arrMove import arrMove
|
|
4
|
+
from .arrPick import arrPick
|
|
5
|
+
from .arrRepeat import arrRepeat
|
|
6
|
+
from .arrShuffle import arrShuffle
|
|
7
|
+
from .arrTo1dArray import arrTo1dArray
|
|
8
|
+
from .arrUnique import arrUnique
|
|
9
|
+
from .arrWithDefault import arrWithDefault
|
|
10
|
+
from .arrWithNumber import arrWithNumber
|
|
11
|
+
from .average import average
|
|
12
|
+
from .sortByObjectKey import sortByObjectKey
|
|
13
|
+
from .sortNumeric import sortNumeric
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
'arrCount',
|
|
17
|
+
'arrGroupByMaxCount',
|
|
18
|
+
'arrMove',
|
|
19
|
+
'arrPick',
|
|
20
|
+
'arrRepeat',
|
|
21
|
+
'arrShuffle',
|
|
22
|
+
'arrTo1dArray',
|
|
23
|
+
'arrUnique',
|
|
24
|
+
'arrWithDefault',
|
|
25
|
+
'arrWithNumber',
|
|
26
|
+
'average',
|
|
27
|
+
'sortByObjectKey',
|
|
28
|
+
'sortNumeric',
|
|
29
|
+
]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
def arrGroupByMaxCount(array: list, maxLengthPerGroup: int = 1) -> list:
|
|
2
|
+
result = []
|
|
3
|
+
tempArray = []
|
|
4
|
+
|
|
5
|
+
for item in array:
|
|
6
|
+
if len(tempArray) == maxLengthPerGroup:
|
|
7
|
+
result.append(tempArray)
|
|
8
|
+
tempArray = []
|
|
9
|
+
|
|
10
|
+
tempArray.append(item)
|
|
11
|
+
|
|
12
|
+
if len(tempArray) > 0:
|
|
13
|
+
result.append(tempArray)
|
|
14
|
+
|
|
15
|
+
return result
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from ..verify.isObject import isObject
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def arrRepeat(array, count: int) -> list:
|
|
5
|
+
if not array or count < 1 or not isinstance(array, (list, tuple, dict)):
|
|
6
|
+
return []
|
|
7
|
+
|
|
8
|
+
isObj = isObject(array)
|
|
9
|
+
result = []
|
|
10
|
+
|
|
11
|
+
for _ in range(count):
|
|
12
|
+
if isObj:
|
|
13
|
+
result.append(array)
|
|
14
|
+
else:
|
|
15
|
+
result.extend(array)
|
|
16
|
+
|
|
17
|
+
return result
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import random
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def arrShuffle(array: list):
|
|
6
|
+
if len(array) == 1:
|
|
7
|
+
return array[0]
|
|
8
|
+
|
|
9
|
+
newArray = array
|
|
10
|
+
|
|
11
|
+
for i in range(len(array) - 1, 0, -1):
|
|
12
|
+
j = math.floor(random.random() * (i + 1))
|
|
13
|
+
newArray[i], newArray[j] = array[j], array[i]
|
|
14
|
+
|
|
15
|
+
return newArray
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from ..verify.is2dArray import is2dArray
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def arrTo1dArray(array: list) -> list:
|
|
5
|
+
def convert1dArray(arr: list) -> list:
|
|
6
|
+
tempArr = []
|
|
7
|
+
|
|
8
|
+
for item in arr:
|
|
9
|
+
if not isinstance(item, (list, tuple)):
|
|
10
|
+
tempArr.append(item)
|
|
11
|
+
elif is2dArray(item):
|
|
12
|
+
tempArr.extend(convert1dArray(item))
|
|
13
|
+
else:
|
|
14
|
+
tempArr.extend(item)
|
|
15
|
+
|
|
16
|
+
return tempArr
|
|
17
|
+
|
|
18
|
+
return convert1dArray(array)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from ..verify.is2dArray import is2dArray
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def arrUnique(array: list) -> list:
|
|
7
|
+
if is2dArray(array):
|
|
8
|
+
seen = set()
|
|
9
|
+
result = []
|
|
10
|
+
|
|
11
|
+
for item in array:
|
|
12
|
+
key = json.dumps(item, separators=(',', ':'))
|
|
13
|
+
|
|
14
|
+
if key not in seen:
|
|
15
|
+
seen.add(key)
|
|
16
|
+
result.append(json.loads(key))
|
|
17
|
+
|
|
18
|
+
return result
|
|
19
|
+
|
|
20
|
+
seen = []
|
|
21
|
+
result = []
|
|
22
|
+
|
|
23
|
+
for item in array:
|
|
24
|
+
if not any(existing is item or (type(existing) is type(item) and existing == item) for existing in seen):
|
|
25
|
+
seen.append(item)
|
|
26
|
+
result.append(item)
|
|
27
|
+
|
|
28
|
+
return result
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from .sortNumeric import _naturalKey
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def sortByObjectKey(
|
|
5
|
+
array: list,
|
|
6
|
+
key: str,
|
|
7
|
+
descending: bool = False,
|
|
8
|
+
numerically: bool = False,
|
|
9
|
+
) -> list:
|
|
10
|
+
if numerically:
|
|
11
|
+
array.sort(key=lambda item: _naturalKey(item[key]))
|
|
12
|
+
|
|
13
|
+
if descending:
|
|
14
|
+
array.reverse()
|
|
15
|
+
|
|
16
|
+
return array
|
|
17
|
+
|
|
18
|
+
array.sort(key=lambda item: item[key], reverse=descending)
|
|
19
|
+
|
|
20
|
+
return array
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _naturalKey(value: str):
|
|
5
|
+
parts = re.split(r'(\d+)', str(value))
|
|
6
|
+
|
|
7
|
+
return [(0, int(part)) if part.isdigit() else (1, part) for part in parts if part != '']
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def sortNumeric(array: list, descending: bool = False) -> list:
|
|
11
|
+
array.sort(key=_naturalKey)
|
|
12
|
+
|
|
13
|
+
if descending:
|
|
14
|
+
array.reverse()
|
|
15
|
+
|
|
16
|
+
return array
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from .decodeBase64 import decodeBase64
|
|
2
|
+
from .decrypt import decrypt
|
|
3
|
+
from .encodeBase64 import encodeBase64
|
|
4
|
+
from .encrypt import encrypt
|
|
5
|
+
from .md5Hash import md5Hash
|
|
6
|
+
from .numberHash import numberHash
|
|
7
|
+
from .objectId import objectId
|
|
8
|
+
from .sha1Hash import sha1Hash
|
|
9
|
+
from .sha256Hash import sha256Hash
|
|
10
|
+
from .sha512Hash import sha512Hash
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
'decodeBase64',
|
|
14
|
+
'decrypt',
|
|
15
|
+
'encodeBase64',
|
|
16
|
+
'encrypt',
|
|
17
|
+
'md5Hash',
|
|
18
|
+
'numberHash',
|
|
19
|
+
'objectId',
|
|
20
|
+
'sha1Hash',
|
|
21
|
+
'sha256Hash',
|
|
22
|
+
'sha512Hash',
|
|
23
|
+
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
|
|
3
|
+
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def decrypt(
|
|
7
|
+
str: str,
|
|
8
|
+
secret: str,
|
|
9
|
+
algorithm: str = 'aes-256-cbc',
|
|
10
|
+
toBase64: bool = False,
|
|
11
|
+
) -> str:
|
|
12
|
+
if not str or len(str) < 1:
|
|
13
|
+
return ''
|
|
14
|
+
|
|
15
|
+
arrStr = str.split(':')
|
|
16
|
+
iv_part = arrStr.pop(0)
|
|
17
|
+
enc_part = ':'.join(arrStr)
|
|
18
|
+
|
|
19
|
+
if toBase64:
|
|
20
|
+
iv = base64.b64decode(iv_part)
|
|
21
|
+
enc = base64.b64decode(enc_part)
|
|
22
|
+
else:
|
|
23
|
+
iv = bytes.fromhex(iv_part)
|
|
24
|
+
enc = bytes.fromhex(enc_part)
|
|
25
|
+
|
|
26
|
+
cipher = Cipher(algorithms.AES(secret.encode('utf-8')), modes.CBC(iv))
|
|
27
|
+
decryptor = cipher.decryptor()
|
|
28
|
+
decrypted = decryptor.update(enc) + decryptor.finalize()
|
|
29
|
+
|
|
30
|
+
# Remove PKCS7 padding.
|
|
31
|
+
pad_len = decrypted[-1]
|
|
32
|
+
decrypted = decrypted[:-pad_len]
|
|
33
|
+
|
|
34
|
+
return decrypted.decode('utf-8')
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def encrypt(
|
|
8
|
+
str: str,
|
|
9
|
+
secret: str,
|
|
10
|
+
algorithm: str = 'aes-256-cbc',
|
|
11
|
+
ivSize: int = 16,
|
|
12
|
+
toBase64: bool = False,
|
|
13
|
+
) -> str:
|
|
14
|
+
if not str or len(str) < 1:
|
|
15
|
+
return ''
|
|
16
|
+
|
|
17
|
+
iv = os.urandom(ivSize)
|
|
18
|
+
cipher = Cipher(algorithms.AES(secret.encode('utf-8')), modes.CBC(iv))
|
|
19
|
+
encryptor = cipher.encryptor()
|
|
20
|
+
|
|
21
|
+
data = str.encode('utf-8')
|
|
22
|
+
block_size = 16
|
|
23
|
+
pad_len = block_size - (len(data) % block_size)
|
|
24
|
+
padded = data + bytes([pad_len]) * pad_len
|
|
25
|
+
|
|
26
|
+
enc = encryptor.update(padded) + encryptor.finalize()
|
|
27
|
+
|
|
28
|
+
if toBase64:
|
|
29
|
+
iv_str = base64.b64encode(iv).decode('ascii')
|
|
30
|
+
enc_str = base64.b64encode(enc).decode('ascii')
|
|
31
|
+
else:
|
|
32
|
+
iv_str = iv.hex()
|
|
33
|
+
enc_str = enc.hex()
|
|
34
|
+
|
|
35
|
+
return f'{iv_str}:{enc_str}'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import hashlib
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def md5Hash(str: str, encoding: Optional[str] = None) -> str:
|
|
7
|
+
digest = hashlib.md5(str.encode('utf-8')).digest()
|
|
8
|
+
enc = encoding or 'hex'
|
|
9
|
+
|
|
10
|
+
if enc == 'hex':
|
|
11
|
+
return digest.hex()
|
|
12
|
+
if enc == 'base64':
|
|
13
|
+
return base64.b64encode(digest).decode('ascii')
|
|
14
|
+
if enc == 'base64url':
|
|
15
|
+
return base64.urlsafe_b64encode(digest).decode('ascii').rstrip('=')
|
|
16
|
+
if enc == 'binary':
|
|
17
|
+
return digest.decode('latin-1')
|
|
18
|
+
|
|
19
|
+
raise ValueError(f'Unsupported encoding: {encoding}')
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
def numberHash(str: str) -> int:
|
|
2
|
+
if not str:
|
|
3
|
+
return 0
|
|
4
|
+
|
|
5
|
+
hash = 0
|
|
6
|
+
|
|
7
|
+
for ch in str:
|
|
8
|
+
hash = (hash << 5) - hash + ord(ch)
|
|
9
|
+
# Emulate JS `hash |= 0`: keep low 32 bits and interpret as signed.
|
|
10
|
+
hash &= 0xFFFFFFFF
|
|
11
|
+
if hash >= 0x80000000:
|
|
12
|
+
hash -= 0x100000000
|
|
13
|
+
|
|
14
|
+
return hash
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import hashlib
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def sha1Hash(str: str, encoding: Optional[str] = None) -> str:
|
|
7
|
+
digest = hashlib.sha1(str.encode('utf-8')).digest()
|
|
8
|
+
enc = encoding or 'hex'
|
|
9
|
+
|
|
10
|
+
if enc == 'hex':
|
|
11
|
+
return digest.hex()
|
|
12
|
+
if enc == 'base64':
|
|
13
|
+
return base64.b64encode(digest).decode('ascii')
|
|
14
|
+
if enc == 'base64url':
|
|
15
|
+
return base64.urlsafe_b64encode(digest).decode('ascii').rstrip('=')
|
|
16
|
+
if enc == 'binary':
|
|
17
|
+
return digest.decode('latin-1')
|
|
18
|
+
|
|
19
|
+
raise ValueError(f'Unsupported encoding: {encoding}')
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import hashlib
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def sha256Hash(str: str, encoding: Optional[str] = None) -> str:
|
|
7
|
+
digest = hashlib.sha256(str.encode('utf-8')).digest()
|
|
8
|
+
enc = encoding or 'hex'
|
|
9
|
+
|
|
10
|
+
if enc == 'hex':
|
|
11
|
+
return digest.hex()
|
|
12
|
+
if enc == 'base64':
|
|
13
|
+
return base64.b64encode(digest).decode('ascii')
|
|
14
|
+
if enc == 'base64url':
|
|
15
|
+
return base64.urlsafe_b64encode(digest).decode('ascii').rstrip('=')
|
|
16
|
+
if enc == 'binary':
|
|
17
|
+
return digest.decode('latin-1')
|
|
18
|
+
|
|
19
|
+
raise ValueError(f'Unsupported encoding: {encoding}')
|